Thu Jul 9 13:41:01 2009

Asterisk developer's documentation


chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/signal.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/event.h"

Go to the source code of this file.

Data Structures

struct  mgcp_endpoint
struct  mgcp_gateway
struct  mgcp_message
 mgcp_message: MGCP message for queuing up More...
struct  mgcp_request
struct  mgcp_response
struct  mgcp_subchannel

Defines

#define CANREINVITE   1
#define DEFAULT_EXPIRY   120
#define DEFAULT_MGCP_CA_PORT   2727
#define DEFAULT_MGCP_GW_PORT   2427
#define DEFAULT_RETRANS   1000
#define INADDR_NONE   (in_addr_t)(-1)
#define MAX_EXPIRY   3600
#define MAX_RETRANS   5
#define MAX_SUBS   2
#define MGCP_CX_CONF   3
#define MGCP_CX_CONFERENCE   3
#define MGCP_CX_INACTIVE   4
#define MGCP_CX_MUTE   4
#define MGCP_CX_RECVONLY   1
#define MGCP_CX_SENDONLY   0
#define MGCP_CX_SENDRECV   2
#define MGCP_DTMF_HYBRID   (1 << 2)
#define MGCP_DTMF_INBAND   (1 << 1)
#define MGCP_DTMF_RFC2833   (1 << 0)
#define MGCP_MAX_HEADERS   64
#define MGCP_MAX_LINES   64
#define MGCP_MAX_PACKET   1500
#define MGCP_OFFHOOK   2
#define MGCP_ONHOOK   1
#define MGCP_SUBCHANNEL_MAGIC   "!978!"
#define MGCPDUMPER
#define RESPONSE_TIMEOUT   30
#define SUB_ALT   1
#define SUB_REAL   0
#define TYPE_LINE   2
#define TYPE_TRUNK   1

Enumerations

enum  {
  MGCP_CMD_EPCF, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_CMD_DLCX,
  MGCP_CMD_RQNT, MGCP_CMD_NTFY, MGCP_CMD_AUEP, MGCP_CMD_AUCX,
  MGCP_CMD_RSIP
}

Functions

static char * __get_header (struct mgcp_request *req, char *name, int *start)
static int __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len)
static void __reg_module (void)
static void __unreg_module (void)
static int add_header (struct mgcp_request *req, char *var, char *value)
static void add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp)
static int add_line (struct mgcp_request *req, char *line)
static int add_sdp (struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
static int attempt_transfer (struct mgcp_endpoint *p)
static struct mgcp_gatewaybuild_gateway (char *cat, struct ast_variable *v)
 build_gateway: parse mgcp.conf and create gateway/endpoint structures
static char * control2str (int ind)
static void destroy_endpoint (struct mgcp_endpoint *e)
static void destroy_gateway (struct mgcp_gateway *g)
static void * do_monitor (void *data)
static void dump_cmd_queues (struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
 dump_cmd_queues: (SC:) cleanup pending commands
static void dump_queue (struct mgcp_gateway *gw, struct mgcp_endpoint *p)
static int find_and_retrans (struct mgcp_subchannel *sub, struct mgcp_request *req)
static struct mgcp_requestfind_command (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request **queue, ast_mutex_t *l, int ident)
 find_command: (SC:) remove command transaction from queue
static struct mgcp_subchannelfind_subchannel_and_lock (char *name, int msgid, struct sockaddr_in *sin)
static char * get_csv (char *c, int *len, char **next)
 get_csv: (SC:) get comma separated value
static char * get_header (struct mgcp_request *req, char *name)
static char * get_sdp (struct mgcp_request *req, char *name)
static char * get_sdp_by_line (char *line, char *name, int nameLen)
static char * get_sdp_iterate (int *iterator, struct mgcp_request *req, char *name)
static void handle_hd_hf (struct mgcp_subchannel *sub, char *ev)
static char * handle_mgcp_audit_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mgcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mgcp_set_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mgcp_show_endpoints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
static void handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
static int has_voicemail (struct mgcp_endpoint *p)
static int init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
static int init_resp (struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
static int load_module (void)
 load_module: PBX load module - initialization ---
static int mgcp_answer (struct ast_channel *ast)
static int mgcp_call (struct ast_channel *ast, char *dest, int timeout)
static int mgcp_devicestate (void *data)
 mgcp_devicestate: channel callback for device status monitoring
static int mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_get_result mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static int mgcp_hangup (struct ast_channel *ast)
static int mgcp_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelmgcp_new (struct mgcp_subchannel *sub, int state)
static int mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
static void mgcp_queue_control (struct mgcp_subchannel *sub, int control)
static void mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f)
static void mgcp_queue_hangup (struct mgcp_subchannel *sub)
static struct ast_framemgcp_read (struct ast_channel *ast)
static char * mgcp_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_channelmgcp_request (const char *type, int format, void *data, int *cause)
static struct ast_framemgcp_rtp_read (struct mgcp_subchannel *sub)
static int mgcp_senddigit_begin (struct ast_channel *ast, char digit)
static int mgcp_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int mgcp_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
static void * mgcp_ss (void *data)
static int mgcp_write (struct ast_channel *ast, struct ast_frame *frame)
static int mgcpsock_read (int *id, int fd, short events, void *ignore)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static void parse (struct mgcp_request *req)
static int process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req)
static void prune_gateways (void)
static int reload (void)
static int reload_config (int reload)
static int reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
static int resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp)
static int respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
static int restart_monitor (void)
static int retrans_pkt (const void *data)
static void sdpLineNum_iterator_init (int *iterator)
static int send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
static int send_response (struct mgcp_subchannel *sub, struct mgcp_request *req)
static void start_rtp (struct mgcp_subchannel *sub)
static int transmit_audit_endpoint (struct mgcp_endpoint *p)
static int transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp)
static int transmit_connection_del (struct mgcp_subchannel *sub)
static int transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident)
static int transmit_modify_request (struct mgcp_subchannel *sub)
static int transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
static int transmit_notify_request (struct mgcp_subchannel *sub, char *tone)
static int transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
static int transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
static int unalloc_sub (struct mgcp_subchannel *sub)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static char accountcode [AST_MAX_ACCOUNT_CODE] = ""
static int adsi = 0
static int amaflags = 0
static const struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static int callreturn = 0
static int callwaiting = 0
static int cancallforward = 0
static int canreinvite = CANREINVITE
static int capability = AST_FORMAT_ULAW
static char cid_name [AST_MAX_EXTENSION] = ""
static char cid_num [AST_MAX_EXTENSION] = ""
static struct ast_cli_entry cli_mgcp []
static struct ast_cli_entry cli_mgcp_set_debug_deprecated = { .handler = handle_mgcp_set_debug_deprecated , .summary = "Enable/Disable MGCP debugging" ,__VA_ARGS__ }
static const char config [] = "mgcp.conf"
static char context [AST_MAX_EXTENSION] = "default"
static unsigned int cos = 0
static unsigned int cos_audio = 0
static ast_group_t cur_callergroup = 0
static ast_group_t cur_pickupgroup = 0
static struct ast_jb_conf default_jbconf
static int dtmfmode = 0
static int firstdigittimeout = 16000
static ast_mutex_t gatelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 gatelock: mutex for gateway/endpoint lists
static struct mgcp_gatewaygateways
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
static int immediate = 0
static struct io_contextio
static char language [MAX_LANGUAGE] = ""
static char mailbox [AST_MAX_EXTENSION]
static int matchdigittimeout = 3000
static char * mgcp_cxmodes []
static ast_mutex_t mgcp_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int mgcp_reloading = 0
static struct ast_rtp_protocol mgcp_rtp
static struct ast_channel_tech mgcp_tech
static int mgcpdebug = 0
static int mgcpsock = -1
static int * mgcpsock_read_id = NULL
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int nonCodecCapability = AST_RTP_DTMF
static unsigned int oseq
static char ourhost [MAXHOSTNAMELEN]
static int ourport
static struct sched_contextsched
static int singlepath = 0
static int slowsequence = 0
static const char tdesc [] = "Media Gateway Control Protocol (MGCP)"
static int threewaycalling = 0
static unsigned int tos = 0
static unsigned int tos_audio = 0
static int transfer = 0


Detailed Description

Implementation of Media Gateway Control Protocol.

Author:
Mark Spencer <markster@digium.com>
See also

Definition in file chan_mgcp.c.


Define Documentation

#define CANREINVITE   1

Definition at line 83 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_EXPIRY   120

Definition at line 81 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 107 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 106 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 109 of file chan_mgcp.c.

Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt().

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 86 of file chan_mgcp.c.

Referenced by build_gateway().

#define MAX_EXPIRY   3600

Definition at line 82 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 110 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 265 of file chan_mgcp.c.

Referenced by build_gateway(), destroy_endpoint(), reload_config(), and unistim_info().

#define MGCP_CX_CONF   3

Definition at line 116 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 117 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 119 of file chan_mgcp.c.

Referenced by build_gateway(), mgcp_hangup(), and unalloc_sub().

#define MGCP_CX_MUTE   4

Definition at line 118 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

Definition at line 114 of file chan_mgcp.c.

Referenced by handle_request(), mgcp_call(), and mgcp_hangup().

#define MGCP_CX_SENDONLY   0

MGCP rtp stream modes {

Definition at line 113 of file chan_mgcp.c.

#define MGCP_CX_SENDRECV   2

Definition at line 115 of file chan_mgcp.c.

Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), and mgcp_call().

#define MGCP_DTMF_HYBRID   (1 << 2)

Definition at line 104 of file chan_mgcp.c.

Referenced by add_header_offhook(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().

#define MGCP_DTMF_INBAND   (1 << 1)

Definition at line 103 of file chan_mgcp.c.

Referenced by add_header_offhook(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().

#define MGCP_DTMF_RFC2833   (1 << 0)

Definition at line 102 of file chan_mgcp.c.

Referenced by build_gateway(), mgcp_rtp_read(), mgcp_senddigit_begin(), and mgcp_senddigit_end().

#define MGCP_MAX_HEADERS   64

The private structures of the mgcp channels are linked for ! selecting outgoing channels

Definition at line 224 of file chan_mgcp.c.

Referenced by add_header(), init_req(), init_resp(), and parse().

#define MGCP_MAX_LINES   64

Definition at line 225 of file chan_mgcp.c.

Referenced by add_line(), and parse().

#define MGCP_MAX_PACKET   1500

Also from RFC 2543, should sub headers tho

Definition at line 108 of file chan_mgcp.c.

#define MGCP_OFFHOOK   2

Definition at line 299 of file chan_mgcp.c.

Referenced by handle_hd_hf(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

#define MGCP_ONHOOK   1

Definition at line 298 of file chan_mgcp.c.

Referenced by build_gateway(), do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_request(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

#define MGCP_SUBCHANNEL_MAGIC   "!978!"

subchannel magic string. Needed to prove that any subchannel pointer passed by asterisk really points to a valid subchannel memory area. Ugly.. But serves the purpose for the time being.

Definition at line 276 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 80 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 255 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 268 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 267 of file chan_mgcp.c.

#define TYPE_LINE   2

Definition at line 302 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), do_monitor(), mgcp_call(), and skinny_hangup().

#define TYPE_TRUNK   1

Definition at line 301 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().


Enumeration Type Documentation

anonymous enum

Enumerator:
MGCP_CMD_EPCF 
MGCP_CMD_CRCX 
MGCP_CMD_MDCX 
MGCP_CMD_DLCX 
MGCP_CMD_RQNT 
MGCP_CMD_NTFY 
MGCP_CMD_AUEP 
MGCP_CMD_AUCX 
MGCP_CMD_RSIP 

Definition at line 130 of file chan_mgcp.c.

00130      {
00131    MGCP_CMD_EPCF,
00132    MGCP_CMD_CRCX,
00133    MGCP_CMD_MDCX,
00134    MGCP_CMD_DLCX,
00135    MGCP_CMD_RQNT,
00136    MGCP_CMD_NTFY,
00137    MGCP_CMD_AUEP,
00138    MGCP_CMD_AUCX,
00139    MGCP_CMD_RSIP
00140 };


Function Documentation

static char* __get_header ( struct mgcp_request req,
char *  name,
int *  start 
) [static]

Definition at line 1600 of file chan_mgcp.c.

References mgcp_request::header, mgcp_request::headers, and len().

Referenced by build_route(), copy_all_header(), copy_via_headers(), func_header_read(), get_header(), and handle_response_register().

01601 {
01602    int x;
01603    int len = strlen(name);
01604    char *r;
01605    for (x=*start;x<req->headers;x++) {
01606       if (!strncasecmp(req->header[x], name, len) && 
01607           (req->header[x][len] == ':')) {
01608          r = req->header[x] + len + 1;
01609          while(*r && (*r < 33))
01610             r++;
01611          *start = x+1;
01612          return r;
01613       }
01614    }
01615    /* Don't return NULL, so get_header is always a valid pointer */
01616    return "";
01617 }

static int __mgcp_xmit ( struct mgcp_gateway gw,
char *  data,
int  len 
) [static]

Definition at line 511 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_log(), mgcp_gateway::defaddr, errno, and LOG_WARNING.

Referenced by mgcp_postrequest(), resend_response(), retrans_pkt(), and send_response().

00512 {
00513    int res;
00514    if (gw->addr.sin_addr.s_addr)
00515       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00516    else 
00517       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00518    if (res != len) {
00519       ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00520    }
00521    return res;
00522 }

static void __reg_module ( void   )  [static]

Definition at line 4408 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

Definition at line 4408 of file chan_mgcp.c.

static int add_header ( struct mgcp_request req,
char *  var,
char *  value 
) [static]

Definition at line 1946 of file chan_mgcp.c.

References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_request::len, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_HEADERS.

Referenced by __transmit_response(), add_digit(), add_header_contentLength(), add_header_offhook(), add_route(), add_sdp(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), initreqprep(), reqprep(), respprep(), sip_notify(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_invite(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_minse(), transmit_response_with_unsupported(), and transmit_state_notify().

01947 {
01948    if (req->len >= sizeof(req->data) - 4) {
01949       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01950       return -1;
01951    }
01952    if (req->lines) {
01953       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01954       return -1;
01955    }
01956    req->header[req->headers] = req->data + req->len;
01957    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01958    req->len += strlen(req->header[req->headers]);
01959    if (req->headers < MGCP_MAX_HEADERS)
01960       req->headers++;
01961    else {
01962       ast_log(LOG_WARNING, "Out of header space\n");
01963       return -1;
01964    }
01965    return 0;   
01966 }

static void add_header_offhook ( struct mgcp_subchannel sub,
struct mgcp_request resp 
) [static]

Definition at line 2341 of file chan_mgcp.c.

References ast_channel::_state, add_header(), AST_STATE_RINGING, mgcp_endpoint::dtmfmode, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_subchannel::owner, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

02342 {
02343    struct mgcp_endpoint *p = sub->parent;
02344 
02345    if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
02346       add_header(resp, "R", "L/hu(N),L/hf(N)");
02347    else
02348       add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
02349 }

static int add_line ( struct mgcp_request req,
char *  line 
) [static]

Definition at line 1968 of file chan_mgcp.c.

References ast_copy_string(), ast_log(), mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES.

Referenced by add_digit(), add_sdp(), add_text(), add_vidupdate(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), and transmit_state_notify().

01969 {
01970    if (req->len >= sizeof(req->data) - 4) {
01971       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01972       return -1;
01973    }
01974    if (!req->lines) {
01975       /* Add extra empty return */
01976       ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
01977       req->len += strlen(req->data + req->len);
01978    }
01979    req->line[req->lines] = req->data + req->len;
01980    snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01981    req->len += strlen(req->line[req->lines]);
01982    if (req->lines < MGCP_MAX_LINES)
01983       req->lines++;
01984    else {
01985       ast_log(LOG_WARNING, "Out of line space\n");
01986       return -1;
01987    }
01988    return 0;   
01989 }

static int add_sdp ( struct mgcp_request resp,
struct mgcp_subchannel sub,
struct ast_rtp rtp 
) [static]

Definition at line 2069 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_verbose(), mgcp_endpoint::capability, len(), LOG_WARNING, mgcpdebug, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.

Referenced by transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), and transmit_response_with_t38_sdp().

02070 {
02071    int len;
02072    int codec;
02073    char costr[80];
02074    struct sockaddr_in sin;
02075    char v[256];
02076    char s[256];
02077    char o[256];
02078    char c[256];
02079    char t[256];
02080    char m[256] = "";
02081    char a[1024] = "";
02082    int x;
02083    struct sockaddr_in dest;
02084    struct mgcp_endpoint *p = sub->parent;
02085    /* XXX We break with the "recommendation" and send our IP, in order that our
02086           peer doesn't have to ast_gethostbyname() us XXX */
02087    len = 0;
02088    if (!sub->rtp) {
02089       ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02090       return -1;
02091    }
02092    ast_rtp_get_us(sub->rtp, &sin);
02093    if (rtp) {
02094       ast_rtp_get_peer(rtp, &dest);
02095    } else {
02096       if (sub->tmpdest.sin_addr.s_addr) {
02097          dest.sin_addr = sub->tmpdest.sin_addr;
02098          dest.sin_port = sub->tmpdest.sin_port;
02099          /* Reset temporary destination */
02100          memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02101       } else {
02102          dest.sin_addr = p->parent->ourip;
02103          dest.sin_port = sin.sin_port;
02104       }
02105    }
02106    if (mgcpdebug) {
02107       ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02108    }
02109    ast_copy_string(v, "v=0\r\n", sizeof(v));
02110    snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02111    ast_copy_string(s, "s=session\r\n", sizeof(s));
02112    snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02113    ast_copy_string(t, "t=0 0\r\n", sizeof(t));
02114    snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02115    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02116       if (p->capability & x) {
02117          if (mgcpdebug) {
02118             ast_verbose("Answering with capability %d\n", x);
02119          }
02120          codec = ast_rtp_lookup_code(sub->rtp, 1, x);
02121          if (codec > -1) {
02122             snprintf(costr, sizeof(costr), " %d", codec);
02123             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02124             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
02125             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02126          }
02127       }
02128    }
02129    for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02130       if (p->nonCodecCapability & x) {
02131          if (mgcpdebug) {
02132             ast_verbose("Answering with non-codec capability %d\n", x);
02133          }
02134          codec = ast_rtp_lookup_code(sub->rtp, 0, x);
02135          if (codec > -1) {
02136             snprintf(costr, sizeof(costr), " %d", codec);
02137             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02138             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
02139             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02140             if (x == AST_RTP_DTMF) {
02141                /* Indicate we support DTMF...  Not sure about 16,
02142                   but MSN supports it so dang it, we will too... */
02143                snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02144                strncat(a, costr, sizeof(a) - strlen(a) - 1);
02145             }
02146          }
02147       }
02148    }
02149    strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02150    len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02151    snprintf(costr, sizeof(costr), "%d", len);
02152    add_line(resp, v);
02153    add_line(resp, o);
02154    add_line(resp, s);
02155    add_line(resp, c);
02156    add_line(resp, t);
02157    add_line(resp, m);
02158    add_line(resp, a);
02159    return 0;
02160 }

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

Definition at line 2906 of file chan_mgcp.c.

References ast_channel::_softhangup, ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verb, mgcp_subchannel::id, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().

02907 {
02908    /* *************************
02909     * I hope this works.
02910     * Copied out of chan_zap
02911     * Cross your fingers
02912     * *************************/
02913 
02914    /* In order to transfer, we need at least one of the channels to
02915       actually be in a call bridge.  We can't conference two applications
02916       together (but then, why would we want to?) */
02917    if (ast_bridged_channel(p->sub->owner)) {
02918       /* The three-way person we're about to transfer to could still be in MOH, so
02919          stop if now if appropriate */
02920       if (ast_bridged_channel(p->sub->next->owner))
02921          ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02922       if (p->sub->owner->_state == AST_STATE_RINGING) {
02923          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02924       }
02925       if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
02926          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02927             ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
02928          return -1;
02929       }
02930       /* Orphan the channel */
02931       unalloc_sub(p->sub->next);
02932    } else if (ast_bridged_channel(p->sub->next->owner)) {
02933       if (p->sub->owner->_state == AST_STATE_RINGING) {
02934          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02935       }
02936       ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
02937       if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
02938          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02939             ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
02940          return -1;
02941       }
02942       /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
02943       ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
02944       p->sub = p->sub->next;
02945       unalloc_sub(p->sub->next);
02946       /* Tell the caller not to hangup */
02947       return 1;
02948    } else {
02949       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
02950          p->sub->owner->name, p->sub->next->owner->name);
02951       p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02952       if (p->sub->next->owner) {
02953          p->sub->next->alreadygone = 1;
02954          mgcp_queue_hangup(p->sub->next);
02955       }
02956    }
02957    return 0;
02958 }

static struct mgcp_gateway* build_gateway ( char *  cat,
struct ast_variable v 
) [static]

build_gateway: parse mgcp.conf and create gateway/endpoint structures

Definition at line 3574 of file chan_mgcp.c.

References __ourip, mgcp_endpoint::accountcode, accountcode, mgcp_endpoint::adsi, adsi, mgcp_endpoint::amaflags, amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free, ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verb, mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, callreturn, mgcp_endpoint::callwaiting, callwaiting, mgcp_endpoint::cancallforward, cancallforward, mgcp_endpoint::canreinvite, CANREINVITE, canreinvite, capability, mgcp_endpoint::capability, mgcp_endpoint::cid_name, cid_name, mgcp_endpoint::cid_num, cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, context, cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::dtmfmode, dtmfmode, gateways, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, immediate, INADDR_NONE, mgcp_endpoint::language, language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, mailbox, MAX_SUBS, MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, musicclass, mwi_event_cb(), mgcp_endpoint::mwi_event_sub, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, nat, mgcp_endpoint::needaudit, ast_variable::next, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::pickupgroup, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, singlepath, mgcp_endpoint::slowsequence, slowsequence, strsep(), mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, threewaycalling, mgcp_endpoint::transfer, transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, and ast_variable::value.

Referenced by reload_config().

03575 {
03576    struct mgcp_gateway *gw;
03577    struct mgcp_endpoint *e;
03578    struct mgcp_subchannel *sub;
03579    /*char txident[80];*/
03580    int i=0, y=0;
03581    int gw_reload = 0;
03582    int ep_reload = 0;
03583    canreinvite = CANREINVITE;
03584 
03585    /* locate existing gateway */
03586    gw = gateways;
03587    while (gw) {
03588       if (!strcasecmp(cat, gw->name)) {
03589          /* gateway already exists */
03590          gw->delme = 0;
03591          gw_reload = 1;
03592          break;
03593       }
03594       gw = gw->next;
03595    }
03596 
03597    if (!gw)
03598       gw = ast_calloc(1, sizeof(*gw));
03599 
03600    if (gw) {
03601       if (!gw_reload) {
03602          gw->expire = -1;
03603          gw->retransid = -1; /* SC */
03604          ast_mutex_init(&gw->msgs_lock);
03605          ast_copy_string(gw->name, cat, sizeof(gw->name));
03606          /* check if the name is numeric ip */
03607          if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
03608             gw->isnamedottedip = 1;
03609       }
03610       while(v) {
03611          if (!strcasecmp(v->name, "host")) {
03612             if (!strcasecmp(v->value, "dynamic")) {
03613                /* They'll register with us */
03614                gw->dynamic = 1;
03615                memset(&gw->addr.sin_addr, 0, 4);
03616                if (gw->addr.sin_port) {
03617                   /* If we've already got a port, make it the default rather than absolute */
03618                   gw->defaddr.sin_port = gw->addr.sin_port;
03619                   gw->addr.sin_port = 0;
03620                }
03621             } else {
03622                /* Non-dynamic.  Make sure we become that way if we're not */
03623                AST_SCHED_DEL(sched, gw->expire);
03624                gw->dynamic = 0;
03625                if (ast_get_ip(&gw->addr, v->value)) {
03626                   if (!gw_reload) {
03627                      ast_mutex_destroy(&gw->msgs_lock);
03628                      ast_free(gw);
03629                   }
03630                   return NULL;
03631                }
03632             }
03633          } else if (!strcasecmp(v->name, "defaultip")) {
03634             if (ast_get_ip(&gw->defaddr, v->value)) {
03635                if (!gw_reload) {
03636                   ast_mutex_destroy(&gw->msgs_lock);
03637                   ast_free(gw);
03638                }
03639                return NULL;
03640             }
03641          } else if (!strcasecmp(v->name, "permit") ||
03642             !strcasecmp(v->name, "deny")) {
03643             gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
03644          } else if (!strcasecmp(v->name, "port")) {
03645             gw->addr.sin_port = htons(atoi(v->value));
03646          } else if (!strcasecmp(v->name, "context")) {
03647             ast_copy_string(context, v->value, sizeof(context));
03648          } else if (!strcasecmp(v->name, "dtmfmode")) {
03649             if (!strcasecmp(v->value, "inband"))
03650                dtmfmode = MGCP_DTMF_INBAND;
03651             else if (!strcasecmp(v->value, "rfc2833")) 
03652                dtmfmode = MGCP_DTMF_RFC2833;
03653             else if (!strcasecmp(v->value, "hybrid"))
03654                dtmfmode = MGCP_DTMF_HYBRID;
03655             else if (!strcasecmp(v->value, "none")) 
03656                dtmfmode = 0;
03657             else
03658                ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
03659          } else if (!strcasecmp(v->name, "nat")) {
03660             nat = ast_true(v->value);
03661          } else if (!strcasecmp(v->name, "callerid")) {
03662             if (!strcasecmp(v->value, "asreceived")) {
03663                cid_num[0] = '\0';
03664                cid_name[0] = '\0';
03665             } else {
03666                ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
03667             }
03668          } else if (!strcasecmp(v->name, "language")) {
03669             ast_copy_string(language, v->value, sizeof(language));
03670          } else if (!strcasecmp(v->name, "accountcode")) {
03671             ast_copy_string(accountcode, v->value, sizeof(accountcode));
03672          } else if (!strcasecmp(v->name, "amaflags")) {
03673             y = ast_cdr_amaflags2int(v->value);
03674             if (y < 0) {
03675                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
03676             } else {
03677                amaflags = y;
03678             }
03679          } else if (!strcasecmp(v->name, "musiconhold")) {
03680             ast_copy_string(musicclass, v->value, sizeof(musicclass));
03681          } else if (!strcasecmp(v->name, "callgroup")) {
03682             cur_callergroup = ast_get_group(v->value);
03683          } else if (!strcasecmp(v->name, "pickupgroup")) {
03684             cur_pickupgroup = ast_get_group(v->value);
03685          } else if (!strcasecmp(v->name, "immediate")) {
03686             immediate = ast_true(v->value);
03687          } else if (!strcasecmp(v->name, "cancallforward")) {
03688             cancallforward = ast_true(v->value);
03689          } else if (!strcasecmp(v->name, "singlepath")) {
03690             singlepath = ast_true(v->value);
03691          } else if (!strcasecmp(v->name, "canreinvite")) {
03692             canreinvite = ast_true(v->value);
03693          } else if (!strcasecmp(v->name, "mailbox")) {
03694             ast_copy_string(mailbox, v->value, sizeof(mailbox));
03695          } else if (!strcasecmp(v->name, "hasvoicemail")) {
03696             if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
03697                ast_copy_string(mailbox, gw->name, sizeof(mailbox));
03698             }
03699          } else if (!strcasecmp(v->name, "adsi")) {
03700             adsi = ast_true(v->value);
03701          } else if (!strcasecmp(v->name, "callreturn")) {
03702             callreturn = ast_true(v->value);
03703          } else if (!strcasecmp(v->name, "callwaiting")) {
03704             callwaiting = ast_true(v->value);
03705          } else if (!strcasecmp(v->name, "slowsequence")) {
03706             slowsequence = ast_true(v->value);
03707          } else if (!strcasecmp(v->name, "transfer")) {
03708             transfer = ast_true(v->value);
03709          } else if (!strcasecmp(v->name, "threewaycalling")) {
03710             threewaycalling = ast_true(v->value);
03711          } else if (!strcasecmp(v->name, "wcardep")) {
03712             /* locate existing endpoint */
03713             e = gw->endpoints;
03714             while (e) {
03715                if (!strcasecmp(v->value, e->name)) {
03716                   /* endpoint already exists */
03717                   e->delme = 0;
03718                   ep_reload = 1;
03719                   break;
03720                }
03721                e = e->next;
03722             }
03723 
03724             if (!e) {
03725                /* Allocate wildcard endpoint */
03726                e = ast_calloc(1, sizeof(*e));
03727                ep_reload = 0;
03728             }
03729 
03730             if (e) {
03731                if (!ep_reload) {
03732                   memset(e, 0, sizeof(struct mgcp_endpoint));
03733                   ast_mutex_init(&e->lock);
03734                   ast_mutex_init(&e->rqnt_queue_lock);
03735                   ast_mutex_init(&e->cmd_queue_lock);
03736                   ast_copy_string(e->name, v->value, sizeof(e->name));
03737                   e->needaudit = 1;
03738                }
03739                ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
03740                /* XXX Should we really check for uniqueness?? XXX */
03741                ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03742                ast_copy_string(e->context, context, sizeof(e->context));
03743                ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03744                ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03745                ast_copy_string(e->language, language, sizeof(e->language));
03746                ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03747                ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03748                if (!ast_strlen_zero(e->mailbox)) {
03749                   char *mailbox, *context;
03750                   context = mailbox = ast_strdupa(e->mailbox);
03751                   strsep(&context, "@");
03752                   if (ast_strlen_zero(context))
03753                      context = "default";
03754                   e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
03755                      AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03756                      AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03757                      AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
03758                      AST_EVENT_IE_END);
03759                }
03760                snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03761                e->msgstate = -1;
03762                e->amaflags = amaflags;
03763                e->capability = capability;
03764                e->parent = gw;
03765                e->dtmfmode = dtmfmode;
03766                if (!ep_reload && e->sub && e->sub->rtp)
03767                   e->dtmfmode |= MGCP_DTMF_INBAND;
03768                e->adsi = adsi;
03769                e->type = TYPE_LINE;
03770                e->immediate = immediate;
03771                e->callgroup=cur_callergroup;
03772                e->pickupgroup=cur_pickupgroup;
03773                e->callreturn = callreturn;
03774                e->cancallforward = cancallforward;
03775                e->singlepath = singlepath;
03776                e->canreinvite = canreinvite;
03777                e->callwaiting = callwaiting;
03778                e->hascallwaiting = callwaiting;
03779                e->slowsequence = slowsequence;
03780                e->transfer = transfer;
03781                e->threewaycalling = threewaycalling;
03782                e->onhooktime = time(NULL);
03783                /* ASSUME we're onhook */
03784                e->hookstate = MGCP_ONHOOK;
03785                if (!ep_reload) {
03786                   /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
03787                   for (i = 0; i < MAX_SUBS; i++) {
03788                      sub = ast_calloc(1, sizeof(*sub));
03789                      if (sub) {
03790                         ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03791                         ast_mutex_init(&sub->lock);
03792                         ast_mutex_init(&sub->cx_queue_lock);
03793                         sub->parent = e;
03794                         sub->id = i;
03795                         snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03796                         /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
03797                         sub->cxmode = MGCP_CX_INACTIVE;
03798                         sub->nat = nat;
03799                         sub->next = e->sub;
03800                         e->sub = sub;
03801                      } else {
03802                         /* XXX Should find a way to clean up our memory */
03803                         ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03804                         return NULL;
03805                      }
03806                   }
03807                   /* Make out subs a circular linked list so we can always sping through the whole bunch */
03808                   sub = e->sub;
03809                   /* find the end of the list */
03810                   while(sub->next){
03811                      sub = sub->next;
03812                   }
03813                   /* set the last sub->next to the first sub */
03814                   sub->next = e->sub;
03815 
03816                   e->next = gw->endpoints;
03817                   gw->endpoints = e;
03818                }
03819             }
03820          } else if (!strcasecmp(v->name, "trunk") ||
03821                     !strcasecmp(v->name, "line")) {
03822 
03823             /* locate existing endpoint */
03824             e = gw->endpoints;
03825             while (e) {
03826                if (!strcasecmp(v->value, e->name)) {
03827                   /* endpoint already exists */
03828                   e->delme = 0;
03829                   ep_reload = 1;
03830                   break;
03831                }
03832                e = e->next;
03833             }
03834 
03835             if (!e) {
03836                e = ast_calloc(1, sizeof(*e));
03837                ep_reload = 0;
03838             }
03839 
03840             if (e) {
03841                if (!ep_reload) {
03842                   ast_mutex_init(&e->lock);
03843                   ast_mutex_init(&e->rqnt_queue_lock);
03844                   ast_mutex_init(&e->cmd_queue_lock);
03845                   ast_copy_string(e->name, v->value, sizeof(e->name));
03846                   e->needaudit = 1;
03847                }
03848                /* XXX Should we really check for uniqueness?? XXX */
03849                ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
03850                ast_copy_string(e->context, context, sizeof(e->context));
03851                ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
03852                ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
03853                ast_copy_string(e->language, language, sizeof(e->language));
03854                ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
03855                ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
03856                if (!ast_strlen_zero(mailbox)) {
03857                   ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
03858                }
03859                if (!ep_reload) {
03860                   /* XXX potential issue due to reload */
03861                   e->msgstate = -1;
03862                   e->parent = gw;
03863                }
03864                e->amaflags = amaflags;
03865                e->capability = capability;
03866                e->dtmfmode = dtmfmode;
03867                e->adsi = adsi;
03868                if (!strcasecmp(v->name, "trunk"))
03869                   e->type = TYPE_TRUNK;
03870                else
03871                   e->type = TYPE_LINE;
03872 
03873                e->immediate = immediate;
03874                e->callgroup=cur_callergroup;
03875                e->pickupgroup=cur_pickupgroup;
03876                e->callreturn = callreturn;
03877                e->cancallforward = cancallforward;
03878                e->canreinvite = canreinvite;
03879                e->singlepath = singlepath;
03880                e->callwaiting = callwaiting;
03881                e->hascallwaiting = callwaiting;
03882                e->slowsequence = slowsequence;
03883                e->transfer = transfer;
03884                e->threewaycalling = threewaycalling;
03885                if (!ep_reload) {
03886                   e->onhooktime = time(NULL);
03887                   /* ASSUME we're onhook */
03888                   e->hookstate = MGCP_ONHOOK;
03889                   snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
03890                }
03891 
03892                for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
03893                   if (!ep_reload) {
03894                      sub = ast_calloc(1, sizeof(*sub));
03895                   } else {
03896                      if (!sub)
03897                         sub = e->sub;
03898                      else
03899                         sub = sub->next;
03900                   }
03901 
03902                   if (sub) {
03903                      if (!ep_reload) {
03904                         ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
03905                         ast_mutex_init(&sub->lock);
03906                         ast_mutex_init(&sub->cx_queue_lock);
03907                         ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
03908                         sub->parent = e;
03909                         sub->id = i;
03910                         snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
03911                         sub->cxmode = MGCP_CX_INACTIVE;
03912                         sub->next = e->sub;
03913                         e->sub = sub;
03914                      }
03915                      sub->nat = nat;
03916                   } else {
03917                      /* XXX Should find a way to clean up our memory */
03918                      ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
03919                      return NULL;
03920                   }
03921                }
03922                if (!ep_reload) {
03923                   /* Make out subs a circular linked list so we can always sping through the whole bunch */
03924                   sub = e->sub;
03925                   /* find the end of the list */
03926                   while (sub->next) {
03927                      sub = sub->next;
03928                   }
03929                   /* set the last sub->next to the first sub */
03930                   sub->next = e->sub;
03931 
03932                   e->next = gw->endpoints;
03933                   gw->endpoints = e;
03934                }
03935             }
03936          } else
03937             ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
03938          v = v->next;
03939       }
03940    }
03941    if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
03942       ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
03943       if (!gw_reload) {
03944          ast_mutex_destroy(&gw->msgs_lock);
03945          ast_free(gw);
03946       }
03947       return NULL;
03948    }
03949    gw->defaddr.sin_family = AF_INET;
03950    gw->addr.sin_family = AF_INET;
03951    if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 
03952       gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03953    if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
03954       gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
03955    if (gw->addr.sin_addr.s_addr)
03956       if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
03957          memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
03958 
03959    return (gw_reload ? NULL : gw);
03960 }

static char* control2str ( int  ind  )  [static]

Definition at line 1416 of file chan_mgcp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, and AST_CONTROL_WINK.

Referenced by mgcp_indicate(), skinny_indicate(), and unistim_indicate().

01416                                   {
01417    switch (ind) {
01418    case AST_CONTROL_HANGUP:
01419       return "Other end has hungup";
01420    case AST_CONTROL_RING:
01421       return "Local ring";
01422    case AST_CONTROL_RINGING:
01423       return "Remote end is ringing";
01424    case AST_CONTROL_ANSWER:
01425       return "Remote end has answered";
01426    case AST_CONTROL_BUSY:
01427       return "Remote end is busy";
01428    case AST_CONTROL_TAKEOFFHOOK:
01429       return "Make it go off hook";
01430    case AST_CONTROL_OFFHOOK:
01431       return "Line is off hook";
01432    case AST_CONTROL_CONGESTION:
01433       return "Congestion (circuits busy)";
01434    case AST_CONTROL_FLASH:
01435       return "Flash hook";
01436    case AST_CONTROL_WINK:
01437       return "Wink";
01438    case AST_CONTROL_OPTION:
01439       return "Set a low-level option";
01440    case AST_CONTROL_RADIO_KEY:
01441       return "Key Radio";
01442    case AST_CONTROL_RADIO_UNKEY:
01443       return "Un-Key Radio";
01444    }
01445    return "UNKNOWN";
01446 }

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

Definition at line 3995 of file chan_mgcp.c.

References ast_mutex_lock(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::cxident, mgcp_subchannel::lock, MAX_SUBS, mgcp_subchannel::next, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and transmit_connection_del().

Referenced by prune_gateways().

03996 {
03997    struct mgcp_subchannel *sub = e->sub->next, *s;
03998    int i;
03999 
04000    for (i = 0; i < MAX_SUBS; i++) {
04001       ast_mutex_lock(&sub->lock);
04002       if (!ast_strlen_zero(sub->cxident)) {
04003          transmit_connection_del(sub);
04004       }
04005       if (sub->rtp) {
04006          ast_rtp_destroy(sub->rtp);
04007          sub->rtp = NULL;
04008       }
04009       memset(sub->magic, 0, sizeof(sub->magic));
04010       mgcp_queue_hangup(sub);
04011       dump_cmd_queues(NULL, sub);
04012       ast_mutex_unlock(&sub->lock);
04013       sub = sub->next;
04014    }
04015 
04016    if (e->dsp) {
04017       ast_dsp_free(e->dsp);
04018    }
04019 
04020    dump_queue(e->parent, e);
04021    dump_cmd_queues(e, NULL);
04022 
04023    sub = e->sub;
04024    for (i = 0; (i < MAX_SUBS) && sub; i++) {
04025       s = sub;
04026       sub = sub->next;
04027       ast_mutex_destroy(&s->lock);
04028       ast_mutex_destroy(&s->cx_queue_lock);
04029       ast_free(s);
04030    }
04031 
04032    if (e->mwi_event_sub)
04033       ast_event_unsubscribe(e->mwi_event_sub);
04034 
04035    ast_mutex_destroy(&e->lock);
04036    ast_mutex_destroy(&e->rqnt_queue_lock);
04037    ast_mutex_destroy(&e->cmd_queue_lock);
04038    ast_free(e);
04039 }

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4041 of file chan_mgcp.c.

References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.

04042 {
04043    if (g->ha)
04044       ast_free_ha(g->ha);
04045 
04046    dump_queue(g, NULL);
04047 
04048    ast_free(g);
04049 }

static void* do_monitor ( void *  data  )  [static]

Definition at line 3405 of file chan_mgcp.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, gateways, has_voicemail(), io, MGCP_ONHOOK, mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), monlock, netlock, reload_config(), transmit_notify_request(), and TYPE_LINE.

03406 {
03407    int res;
03408    int reloading;
03409    /*struct mgcp_gateway *g;*/
03410    /*struct mgcp_endpoint *e;*/
03411    /*time_t thispass = 0, lastpass = 0;*/
03412 
03413    /* Add an I/O event to our UDP socket */
03414    if (mgcpsock > -1) 
03415       mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03416    
03417    /* This thread monitors all the frame relay interfaces which are not yet in use
03418       (and thus do not have a separate thread) indefinitely */
03419    /* From here on out, we die whenever asked */
03420    for(;;) {
03421       /* Check for a reload request */
03422       ast_mutex_lock(&mgcp_reload_lock);
03423       reloading = mgcp_reloading;
03424       mgcp_reloading = 0;
03425       ast_mutex_unlock(&mgcp_reload_lock);
03426       if (reloading) {
03427          ast_verb(1, "Reloading MGCP\n");
03428          reload_config(1);
03429          /* Add an I/O event to our UDP socket */
03430          if (mgcpsock > -1 && !mgcpsock_read_id) {
03431             mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03432          }
03433       }
03434 
03435       /* Check for interfaces needing to be killed */
03436       /* Don't let anybody kill us right away.  Nobody should lock the interface list
03437          and wait for the monitor list, but the other way around is okay. */
03438       ast_mutex_lock(&monlock);
03439       /* Lock the network interface */
03440       ast_mutex_lock(&netlock);
03441 
03442 #if 0
03443       /* XXX THIS IS COMPLETELY HOSED */
03444       /* The gateway goes into a state of panic */
03445       /* If the vmwi indicator is sent while it is reseting interfaces */
03446       lastpass = thispass;
03447       thispass = time(NULL);
03448       g = gateways;
03449       while(g) {
03450          if (thispass != lastpass) {
03451             e = g->endpoints;
03452             while(e) {
03453                if (e->type == TYPE_LINE) {
03454                   res = has_voicemail(e);
03455                   if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03456                      if (res) {
03457                         transmit_notify_request(e, "L/vmwi(+)");
03458                      } else {
03459                         transmit_notify_request(e, "L/vmwi(-)");
03460                      }
03461                      e->msgstate = res;
03462                      e->onhooktime = thispass;
03463                   }
03464                }
03465                e = e->next;
03466             }
03467          }
03468          g = g->next;
03469       }
03470 #endif
03471       /* Okay, now that we know what to do, release the network lock */
03472       ast_mutex_unlock(&netlock);
03473       /* And from now on, we're okay to be killed, so release the monitor lock as well */
03474       ast_mutex_unlock(&monlock);
03475       pthread_testcancel();
03476       /* Wait for sched or io */
03477       res = ast_sched_wait(sched);
03478       /* copied from chan_sip.c */
03479       if ((res < 0) || (res > 1000))
03480          res = 1000;
03481       res = ast_io_wait(io, res);
03482       ast_mutex_lock(&monlock);
03483       if (res >= 0) 
03484          ast_sched_runq(sched);
03485       ast_mutex_unlock(&monlock);
03486    }
03487    /* Never reached */
03488    return NULL;
03489 }

static void dump_cmd_queues ( struct mgcp_endpoint p,
struct mgcp_subchannel sub 
) [static]

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2410 of file chan_mgcp.c.

References ast_free, ast_mutex_lock(), ast_mutex_unlock(), mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::next, mgcp_request::next, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::sub.

Referenced by handle_request(), handle_response(), and unalloc_sub().

02411 {
02412    struct mgcp_request *t, *q;
02413 
02414    if (p) {
02415       ast_mutex_lock(&p->rqnt_queue_lock);
02416       for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
02417       p->rqnt_queue = NULL;
02418       ast_mutex_unlock(&p->rqnt_queue_lock);
02419 
02420       ast_mutex_lock(&p->cmd_queue_lock);
02421       for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
02422       p->cmd_queue = NULL;
02423       ast_mutex_unlock(&p->cmd_queue_lock);
02424 
02425       ast_mutex_lock(&p->sub->cx_queue_lock);
02426       for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02427       p->sub->cx_queue = NULL;
02428       ast_mutex_unlock(&p->sub->cx_queue_lock);
02429 
02430       ast_mutex_lock(&p->sub->next->cx_queue_lock);
02431       for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
02432       p->sub->next->cx_queue = NULL;
02433       ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02434    } else if (sub) {
02435       ast_mutex_lock(&sub->cx_queue_lock);
02436       for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02437       sub->cx_queue = NULL;
02438       ast_mutex_unlock(&sub->cx_queue_lock);
02439    }
02440 }

static void dump_queue ( struct mgcp_gateway gw,
struct mgcp_endpoint p 
) [static]

Definition at line 551 of file chan_mgcp.c.

References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_NOTICE, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, and mgcp_message::next.

Referenced by destroy_gateway(), and handle_request().

00552 {
00553    struct mgcp_message *cur, *q = NULL, *w, *prev;
00554 
00555    ast_mutex_lock(&gw->msgs_lock);
00556    prev = NULL, cur = gw->msgs;
00557    while (cur) {
00558       if (!p || cur->owner_ep == p) {
00559          if (prev)
00560             prev->next = cur->next;
00561          else
00562             gw->msgs = cur->next;
00563 
00564          ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 
00565             gw->name, cur->seqno);
00566 
00567          w = cur;
00568          cur = cur->next;
00569          if (q) {
00570             w->next = q;
00571          } else {
00572             w->next = NULL;
00573          }
00574          q = w;
00575       } else {
00576          prev = cur, cur=cur->next;
00577       }
00578    }
00579    ast_mutex_unlock(&gw->msgs_lock);
00580 
00581    while (q) {
00582       cur = q;
00583       q = q->next;
00584       ast_free(cur);
00585    }
00586 }

static int find_and_retrans ( struct mgcp_subchannel sub,
struct mgcp_request req 
) [static]

Definition at line 3284 of file chan_mgcp.c.

References ast_free, mgcp_request::identifier, mgcp_response::next, mgcp_endpoint::parent, mgcp_subchannel::parent, resend_response(), RESPONSE_TIMEOUT, and mgcp_gateway::responses.

Referenced by mgcpsock_read().

03285 {
03286    int seqno=0;
03287    time_t now;
03288    struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03289    time(&now);
03290    if (sscanf(req->identifier, "%d", &seqno) != 1) 
03291       seqno = 0;
03292    cur = sub->parent->parent->responses;
03293    while(cur) {
03294       next = cur->next;
03295       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03296          /* Delete this entry */
03297          if (prev)
03298             prev->next = next;
03299          else
03300             sub->parent->parent->responses = next;
03301          ast_free(cur);
03302       } else {
03303          if (seqno == cur->seqno)
03304             answer = cur;
03305          prev = cur;
03306       }
03307       cur = next;
03308    }
03309    if (answer) {
03310       resend_response(sub, answer);
03311       return 1;
03312    }
03313    return 0;
03314 }

static struct mgcp_request* find_command ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
struct mgcp_request **  queue,
ast_mutex_t l,
int  ident 
) [static]

find_command: (SC:) remove command transaction from queue

Definition at line 2444 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_inet_ntoa(), ast_mutex_lock(), ast_verbose(), mgcp_postrequest(), mgcp_request::next, and mgcp_endpoint::parent.

Referenced by agi_handle_command(), ast_agi_register(), handle_cli_agi_show(), and handle_response().

02446 {
02447    struct mgcp_request *prev, *req;
02448 
02449    ast_mutex_lock(l);
02450    for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02451       if (req->trid == ident) {
02452          /* remove from queue */
02453          if (!prev)
02454             *queue = req->next;
02455          else
02456             prev->next = req->next;
02457 
02458          /* send next pending command */
02459          if (*queue) {
02460             if (mgcpdebug) {
02461                ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 
02462                   ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02463             }
02464 
02465             mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02466          }
02467          break;
02468       }
02469    }
02470    ast_mutex_unlock(l);
02471    return req;
02472 }

static struct mgcp_subchannel* find_subchannel_and_lock ( char *  name,
int  msgid,
struct sockaddr_in *  sin 
) [static]

Definition at line 1647 of file chan_mgcp.c.

References __ourip, mgcp_gateway::addr, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_ouraddrfor(), ast_verb, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_subchannel::next, mgcp_gateway::next, mgcp_gateway::ourip, and mgcp_endpoint::sub.

Referenced by mgcp_request(), and mgcpsock_read().

01648 {
01649    struct mgcp_endpoint *p = NULL;
01650    struct mgcp_subchannel *sub = NULL;
01651    struct mgcp_gateway *g;
01652    char tmp[256] = "";
01653    char *at = NULL, *c;
01654    int found = 0;
01655    if (name) {
01656       ast_copy_string(tmp, name, sizeof(tmp));
01657       at = strchr(tmp, '@');
01658       if (!at) {
01659          ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01660          return NULL;
01661       }
01662       *at++ = '\0';
01663    }
01664    ast_mutex_lock(&gatelock);
01665    if (at && (at[0] == '[')) {
01666       at++;
01667       c = strrchr(at, ']');
01668       if (c)
01669          *c = '\0';
01670    }
01671    g = gateways;
01672    while(g) {
01673       if ((!name || !strcasecmp(g->name, at)) && 
01674           (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01675          /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
01676          if (sin && g->dynamic && name) {
01677             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01678                (g->addr.sin_port != sin->sin_port)) {
01679                memcpy(&g->addr, sin, sizeof(g->addr));
01680                if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01681                   memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01682                ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
01683             }
01684          }
01685          /* not dynamic, check if the name matches */
01686          else if (name) {
01687             if (strcasecmp(g->name, at)) {
01688                g = g->next;
01689                continue;
01690             }
01691          }
01692          /* not dynamic, no name, check if the addr matches */
01693          else if (!name && sin) {
01694             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01695                 (g->addr.sin_port != sin->sin_port)) {
01696                g = g->next;
01697                continue;
01698             }
01699          } else {
01700             g = g->next;
01701             continue;
01702          }
01703          /* SC */
01704          p = g->endpoints;
01705          while(p) {
01706             ast_debug(1, "Searching on %s@%s for subchannel\n",
01707                p->name, g->name);
01708             if (msgid) {
01709 #if 0 /* new transport mech */
01710                sub = p->sub;
01711                do {
01712                   ast_debug(1, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01713                      p->name, g->name, sub->id, msgid);
01714                   if (sub->lastout == msgid) {
01715                      ast_debug(1, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01716                         sub->id, msgid, sub->lastout);
01717                      found = 1;
01718                      break;
01719                   }
01720                   sub = sub->next;
01721                } while (sub != p->sub);
01722                if (found) {
01723                   break;
01724                }
01725 #endif
01726                /* SC */
01727                sub = p->sub;
01728                found = 1;
01729                /* SC */
01730                break;
01731             } else if (name && !strcasecmp(p->name, tmp)) {
01732                ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
01733                   p->name, g->name, p->sub->id);
01734                sub = p->sub;
01735                found = 1;
01736                break;
01737             }
01738             p = p->next;
01739          }
01740          if (sub && found) {
01741             ast_mutex_lock(&sub->lock);
01742             break;
01743          }
01744       }
01745       g = g->next;
01746    }
01747    ast_mutex_unlock(&gatelock);
01748    if (!sub) {
01749       if (name) {
01750          if (g)
01751             ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01752          else
01753             ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01754       } 
01755    }
01756    return sub;
01757 }

static char* get_csv ( char *  c,
int *  len,
char **  next 
) [static]

get_csv: (SC:) get comma separated value

Definition at line 1626 of file chan_mgcp.c.

References s.

Referenced by handle_response().

01627 {
01628    char *s;
01629 
01630    *next = NULL, *len = 0;
01631    if (!c) return NULL;
01632 
01633    while (*c && (*c < 33 || *c == ','))
01634       c++;
01635 
01636    s = c;
01637    while (*c && (*c >= 33 && *c != ','))
01638       c++, (*len)++;
01639    *next = c;
01640 
01641    if (*len == 0)
01642       s = NULL, *next = NULL;
01643 
01644    return s;
01645 }

static char* get_header ( struct mgcp_request req,
char *  name 
) [static]

Definition at line 1619 of file chan_mgcp.c.

References __get_header().

Referenced by __transmit_response(), _sip_tcp_helper_thread(), build_route(), check_auth(), check_peer_ok(), check_user_full(), check_via(), check_via_response(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), gettag(), handle_incoming(), handle_request(), handle_request_bye(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_refer(), handle_response_register(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), proc_422_rsp(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_sipredirect(), transmit_fake_auth_response(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_state_notify().

01620 {
01621    int start = 0;
01622    return __get_header(req, name, &start);
01623 }

static char* get_sdp ( struct mgcp_request req,
char *  name 
) [static]

Definition at line 1571 of file chan_mgcp.c.

References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.

Referenced by process_sdp().

01572 {
01573    int x;
01574    int len = strlen(name);
01575    char *r;
01576 
01577    for (x=0; x<req->lines; x++) {
01578       r = get_sdp_by_line(req->line[x], name, len);
01579       if (r[0] != '\0') return r;
01580    }
01581    return "";
01582 }

static char* get_sdp_by_line ( char *  line,
char *  name,
int  nameLen 
) [static]

Definition at line 1561 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01562 {
01563    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01564       char* r = line + nameLen + 1;
01565       while (*r && (*r < 33)) ++r;
01566       return r;
01567    }
01568    return "";
01569 }

static char* get_sdp_iterate ( int *  iterator,
struct mgcp_request req,
char *  name 
) [static]

Definition at line 1589 of file chan_mgcp.c.

References get_sdp_by_line(), len(), and mgcp_request::line.

Referenced by get_ip_and_port_from_sdp(), get_sdp(), and process_sdp().

01590 {
01591    int len = strlen(name);
01592    char *r;
01593    while (*iterator < req->lines) {
01594       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01595       if (r[0] != '\0') return r;
01596    }
01597    return "";
01598 }

static void handle_hd_hf ( struct mgcp_subchannel sub,
char *  ev 
) [static]

Definition at line 2960 of file chan_mgcp.c.

References ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_UNHOLD, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), AST_STATE_DOWN, AST_STATE_RING, mgcp_subchannel::cxmode, errno, has_voicemail(), mgcp_endpoint::hookstate, mgcp_endpoint::immediate, LOG_WARNING, MGCP_CX_SENDRECV, mgcp_new(), MGCP_OFFHOOK, mgcp_queue_control(), mgcp_ss(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), mgcp_endpoint::sub, transmit_modify_request(), and transmit_notify_request().

Referenced by handle_request().

02961 {
02962    struct mgcp_endpoint *p = sub->parent;
02963    struct ast_channel *c;
02964    pthread_t t;
02965 
02966    /* Off hook / answer */
02967    if (sub->outgoing) {
02968       /* Answered */
02969       if (sub->owner) {
02970          if (ast_bridged_channel(sub->owner))
02971             ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
02972          sub->cxmode = MGCP_CX_SENDRECV;
02973          if (!sub->rtp) {
02974             start_rtp(sub);
02975          } else {
02976             transmit_modify_request(sub);
02977          }
02978          /*transmit_notify_request(sub, "aw");*/
02979          transmit_notify_request(sub, "");
02980          mgcp_queue_control(sub, AST_CONTROL_ANSWER);
02981       }
02982    } else {
02983       /* Start switch */
02984       /*sub->cxmode = MGCP_CX_SENDRECV;*/
02985       if (!sub->owner) {
02986          if (!sub->rtp) {
02987             start_rtp(sub);
02988          } else {
02989             transmit_modify_request(sub);
02990          }
02991          if (p->immediate) {
02992             /* The channel is immediately up. Start right away */
02993 #ifdef DLINK_BUGGY_FIRMWARE   
02994             transmit_notify_request(sub, "rt");
02995 #else
02996             transmit_notify_request(sub, "G/rt");
02997 #endif      
02998             c = mgcp_new(sub, AST_STATE_RING);
02999             if (!c) {
03000                ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
03001                transmit_notify_request(sub, "G/cg");
03002                ast_hangup(c);
03003             }
03004          } else {
03005             if (has_voicemail(p)) {
03006                transmit_notify_request(sub, "L/sl");
03007             } else {
03008                transmit_notify_request(sub, "L/dl");
03009             }
03010             c = mgcp_new(sub, AST_STATE_DOWN);
03011             if (c) {
03012                if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
03013                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03014                   ast_hangup(c);
03015                }
03016             } else {
03017                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03018             }
03019          }
03020       } else {
03021          if (p->hookstate == MGCP_OFFHOOK) {
03022             ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03023          } else {
03024             ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03025             ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03026          }
03027          if (ast_bridged_channel(sub->owner))
03028             ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03029          sub->cxmode = MGCP_CX_SENDRECV;
03030          if (!sub->rtp) {
03031             start_rtp(sub);
03032          } else {
03033             transmit_modify_request(sub);
03034          }
03035          /*transmit_notify_request(sub, "aw");*/
03036          transmit_notify_request(sub, "");
03037          /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
03038       }
03039    }
03040 }

static char* handle_mgcp_audit_endpoint ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1073 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcpdebug, mgcp_gateway::name, mgcp_gateway::next, transmit_audit_endpoint(), and ast_cli_entry::usage.

01074 {
01075    struct mgcp_gateway  *mg;
01076    struct mgcp_endpoint *me;
01077    int found = 0;
01078    char *ename,*gname, *c;
01079 
01080    switch (cmd) {
01081    case CLI_INIT:
01082       e->command = "mgcp audit endpoint";
01083       e->usage =
01084          "Usage: mgcp audit endpoint <endpointid>\n"
01085          "       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
01086          "       mgcp debug MUST be on to see the results of this command.\n";
01087       return NULL;
01088    case CLI_GENERATE:
01089       return NULL;
01090    }
01091 
01092    if (!mgcpdebug) {
01093       return CLI_SHOWUSAGE;
01094    }
01095    if (a->argc != 4)
01096       return CLI_SHOWUSAGE;
01097    /* split the name into parts by null */
01098    ename = a->argv[3];
01099    gname = ename;
01100    while (*gname) {
01101       if (*gname == '@') {
01102          *gname = 0;
01103          gname++;
01104          break;
01105       }
01106       gname++;
01107    }
01108    if (gname[0] == '[')
01109       gname++;
01110    if ((c = strrchr(gname, ']')))
01111       *c = '\0';
01112    ast_mutex_lock(&gatelock);
01113    mg = gateways;
01114    while(mg) {
01115       if (!strcasecmp(mg->name, gname)) {
01116          me = mg->endpoints;
01117          while(me) {
01118             if (!strcasecmp(me->name, ename)) {
01119                found = 1;
01120                transmit_audit_endpoint(me);
01121                break;
01122             }
01123             me = me->next;
01124          }
01125          if (found) {
01126             break;
01127          }
01128       }
01129       mg = mg->next;
01130    }
01131    if (!found) {
01132       ast_cli(a->fd, "   << Could not find endpoint >>     ");
01133    }
01134    ast_mutex_unlock(&gatelock);
01135    return CLI_SUCCESS;
01136 }

static char* handle_mgcp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1163 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mgcpdebug, and ast_cli_entry::usage.

01164 {
01165    switch (cmd) {
01166    case CLI_INIT:
01167       e->command = "mgcp set debug {on|off}";
01168       e->usage =
01169          "Usage: mgcp set debug {on|off}\n"
01170          "       Enables/Disables dumping of MGCP packets for debugging purposes\n";   
01171       return NULL;
01172    case CLI_GENERATE:
01173       return NULL;
01174    }
01175 
01176    if (a->argc != e->args)
01177       return CLI_SHOWUSAGE;
01178 
01179    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
01180       mgcpdebug = 1;
01181       ast_cli(a->fd, "MGCP Debugging Enabled\n");
01182    } else if (!strncasecmp(a->argv[3], "off", 3)) {
01183       mgcpdebug = 0;
01184       ast_cli(a->fd, "MGCP Debugging Disabled\n");
01185    } else {
01186       return CLI_SHOWUSAGE;
01187    }
01188    return CLI_SUCCESS;
01189 }

static char* handle_mgcp_set_debug_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1138 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mgcpdebug, and ast_cli_entry::usage.

01139 {
01140    switch (cmd) {
01141    case CLI_INIT:
01142       e->command = "mgcp set debug [off]";
01143       e->usage =
01144          "Usage: mgcp set debug [off]\n"
01145          "       Enables/Disables dumping of MGCP packets for debugging purposes\n";   
01146       return NULL;
01147    case CLI_GENERATE:
01148       return NULL;
01149    }
01150 
01151    if (a->argc < 3 || a->argc > 4)
01152       return CLI_SHOWUSAGE;
01153    if (a->argc == 3) {
01154       mgcpdebug = 1;
01155       ast_cli(a->fd, "MGCP Debugging Enabled\n");
01156    } else if (!strncasecmp(a->argv[3], "off", 3)) {
01157       mgcpdebug = 0;
01158       ast_cli(a->fd, "MGCP Debugging Disabled\n");
01159    }
01160    return CLI_SUCCESS;
01161 }

static char* handle_mgcp_show_endpoints ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1033 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcp_gateway::name, mgcp_gateway::next, ast_cli_entry::usage, and mgcp_gateway::wcardep.

01034 {
01035    struct mgcp_gateway  *mg;
01036    struct mgcp_endpoint *me;
01037    int hasendpoints = 0;
01038 
01039    switch (cmd) {
01040    case CLI_INIT:
01041       e->command = "mgcp show endpoints";
01042       e->usage =
01043          "Usage: mgcp show endpoints\n"
01044          "       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
01045       return NULL;
01046    case CLI_GENERATE:
01047       return NULL;
01048    }
01049 
01050    if (a->argc != 3) 
01051       return CLI_SHOWUSAGE;
01052    ast_mutex_lock(&gatelock);
01053    mg = gateways;
01054    while(mg) {
01055       me = mg->endpoints;
01056       ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static");
01057       while(me) {
01058          /* Don't show wilcard endpoint */
01059          if (strcmp(me->name, mg->wcardep) != 0)
01060             ast_cli(a->fd, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
01061          hasendpoints = 1;
01062          me = me->next;
01063       }
01064       if (!hasendpoints) {
01065          ast_cli(a->fd, "   << No Endpoints Defined >>     ");
01066       }
01067       mg = mg->next;
01068    }
01069    ast_mutex_unlock(&gatelock);
01070    return CLI_SUCCESS;
01071 }

static int handle_request ( struct mgcp_subchannel sub,
struct mgcp_request req,
struct sockaddr_in *  sin 
) [static]

Definition at line 3042 of file chan_mgcp.c.

References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_DOWN, AST_STATE_UP, ast_verb, ast_verbose(), attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmf_buf, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, f, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_CONF, MGCP_CX_MUTE, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_frame(), mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, transmit_audit_endpoint(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_response(), mgcp_request::verb, and mgcp_gateway::wcardep.

Referenced by mgcpsock_read().

03043 {
03044    char *ev, *s;
03045    struct ast_frame f = { 0, };
03046    struct mgcp_endpoint *p = sub->parent;
03047    struct mgcp_gateway *g = NULL;
03048    int res;
03049 
03050    if (mgcpdebug) {
03051       ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
03052    }
03053    /* Clear out potential response */
03054    if (!strcasecmp(req->verb, "RSIP")) {
03055       /* Test if this RSIP request is just a keepalive */
03056       if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03057          ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03058          transmit_response(sub, "200", req, "OK");
03059       } else {
03060          dump_queue(p->parent, p);
03061          dump_cmd_queues(p, NULL);
03062          
03063          if ((strcmp(p->name, p->parent->wcardep) != 0)) {
03064             ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
03065          }
03066          /* For RSIP on wildcard we reset all endpoints */
03067          if (!strcmp(p->name, p->parent->wcardep)) {
03068             /* Reset all endpoints */
03069             struct mgcp_endpoint *tmp_ep;
03070             
03071             g = p->parent;
03072             tmp_ep = g->endpoints;
03073             while (tmp_ep) {
03074                /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
03075                if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03076                   struct mgcp_subchannel *tmp_sub, *first_sub;
03077                   ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03078                   
03079                   first_sub = tmp_ep->sub;
03080                   tmp_sub = tmp_ep->sub;
03081                   while (tmp_sub) {
03082                      mgcp_queue_hangup(tmp_sub);
03083                      tmp_sub = tmp_sub->next;
03084                      if (tmp_sub == first_sub)
03085                         break;
03086                   }
03087                }
03088                tmp_ep = tmp_ep->next;
03089             }
03090          } else if (sub->owner) {
03091             mgcp_queue_hangup(sub);
03092          }
03093          transmit_response(sub, "200", req, "OK");
03094          /* We dont send NTFY or AUEP to wildcard ep */
03095          if (strcmp(p->name, p->parent->wcardep) != 0) {
03096             transmit_notify_request(sub, "");
03097             /* Audit endpoint. 
03098              Idea is to prevent lost lines due to race conditions 
03099             */
03100             transmit_audit_endpoint(p);
03101          }
03102       }
03103    } else if (!strcasecmp(req->verb, "NTFY")) {
03104       /* Acknowledge and be sure we keep looking for the same things */
03105       transmit_response(sub, "200", req, "OK");
03106       /* Notified of an event */
03107       ev = get_header(req, "O");
03108       s = strchr(ev, '/');
03109       if (s) ev = s + 1;
03110       ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03111       /* Keep looking for events unless this was a hangup */
03112       if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03113          transmit_notify_request(sub, p->curtone);
03114       }
03115       if (!strcasecmp(ev, "hd")) {
03116          p->hookstate = MGCP_OFFHOOK;
03117          sub->cxmode = MGCP_CX_SENDRECV;
03118          handle_hd_hf(sub, ev);
03119       } else if (!strcasecmp(ev, "hf")) {
03120          /* We can assume we are offhook if we received a hookflash */
03121          /* First let's just do call wait and ignore threeway */
03122          /* We're currently in charge */
03123          if (p->hookstate != MGCP_OFFHOOK) {
03124             /* Cisco c7940 sends hf even if the phone is onhook */
03125             /* Thanks to point on IRC for pointing this out */
03126             return -1;
03127          }
03128          /* do not let * conference two down channels */  
03129          if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03130             return -1;
03131 
03132          if (p->callwaiting || p->transfer || p->threewaycalling) {
03133             ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03134             p->sub = p->sub->next;
03135 
03136             /* transfer control to our next subchannel */
03137             if (!sub->next->owner) {
03138                /* plave the first call on hold and start up a new call */
03139                sub->cxmode = MGCP_CX_MUTE;
03140                ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03141                transmit_modify_request(sub);
03142                if (sub->owner && ast_bridged_channel(sub->owner))
03143                   ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03144                sub->next->cxmode = MGCP_CX_RECVONLY;
03145                handle_hd_hf(sub->next, ev);
03146             } else if (sub->owner && sub->next->owner) {
03147                /* We've got two active calls lets decide whether or not to conference or just flip flop */
03148                if ((!sub->outgoing) && (!sub->next->outgoing)) {
03149                   /* We made both calls lets conferenct */
03150                   ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
03151                         sub->id, sub->next->id, p->name, p->parent->name);
03152                   sub->cxmode = MGCP_CX_CONF;
03153                   sub->next->cxmode = MGCP_CX_CONF;
03154                   if (ast_bridged_channel(sub->next->owner))
03155                      ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
03156                   transmit_modify_request(sub);
03157                   transmit_modify_request(sub->next);
03158                } else {
03159                   /* Let's flipflop between calls */
03160                   /* XXX Need to check for state up ??? */
03161                   /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
03162                   ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03163                         sub->id, sub->next->id, p->name, p->parent->name);
03164                   sub->cxmode = MGCP_CX_MUTE;
03165                   ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03166                   transmit_modify_request(sub);
03167                   if (ast_bridged_channel(sub->owner))
03168                      ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03169                         
03170                   if (ast_bridged_channel(sub->next->owner)) 
03171                      ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
03172                         
03173                   handle_hd_hf(sub->next, ev);
03174                }
03175             } else {
03176                /* We've most likely lost one of our calls find an active call and bring it up */
03177                if (sub->owner) {
03178                   p->sub = sub;
03179                } else if (sub->next->owner) {
03180                   p->sub = sub->next;
03181                } else {
03182                   /* We seem to have lost both our calls */
03183                   /* XXX - What do we do now? */
03184                   return -1;
03185                }
03186                if (ast_bridged_channel(p->sub->owner))
03187                   ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
03188                p->sub->cxmode = MGCP_CX_SENDRECV;
03189                transmit_modify_request(p->sub);
03190             }
03191          } else {
03192             ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 
03193                p->name, p->parent->name);
03194          }
03195       } else if (!strcasecmp(ev, "hu")) {
03196          p->hookstate = MGCP_ONHOOK;
03197          sub->cxmode = MGCP_CX_RECVONLY;
03198          ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03199          /* Do we need to send MDCX before a DLCX ?
03200          if (sub->rtp) {
03201             transmit_modify_request(sub);
03202          }
03203          */
03204          if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03205             /* We're allowed to transfer, we have two avtive calls and */
03206             /* we made at least one of the calls.  Let's try and transfer */
03207             ast_mutex_lock(&p->sub->next->lock);
03208             res = attempt_transfer(p);
03209             if (res < 0) {
03210                if (p->sub->next->owner) {
03211                   sub->next->alreadygone = 1;
03212                   mgcp_queue_hangup(sub->next);
03213                }
03214             } else if (res) {
03215                ast_log(LOG_WARNING, "Transfer attempt failed\n");
03216                ast_mutex_unlock(&p->sub->next->lock);
03217                return -1;
03218             }
03219             ast_mutex_unlock(&p->sub->next->lock);
03220          } else {
03221             /* Hangup the current call */
03222             /* If there is another active call, mgcp_hangup will ring the phone with the other call */
03223             if (sub->owner) {
03224                sub->alreadygone = 1;
03225                mgcp_queue_hangup(sub);
03226             } else {
03227                ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03228                      p->name, p->parent->name, sub->id);
03229                /* Instruct the other side to remove the connection since it apparently *
03230                 * still thinks the channel is active. *
03231                 * For Cisco IAD2421 /BAK/ */
03232                transmit_connection_del(sub);
03233             }
03234          }
03235          if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03236             p->hidecallerid = 0;
03237             if (p->hascallwaiting && !p->callwaiting) {
03238                ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03239                p->callwaiting = -1;
03240             }
03241             if (has_voicemail(p)) {
03242                ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03243                transmit_notify_request(sub, "L/vmwi(+)");
03244             } else {
03245                ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03246                transmit_notify_request(sub, "L/vmwi(-)");
03247             }
03248          }
03249       } else if ((strlen(ev) == 1) && 
03250             (((ev[0] >= '0') && (ev[0] <= '9')) ||
03251              ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03252               (ev[0] == '*') || (ev[0] == '#'))) {
03253          if (sub && sub->owner && (sub->owner->_state >=  AST_STATE_UP)) {
03254             f.frametype = AST_FRAME_DTMF;
03255             f.subclass = ev[0];
03256             f.src = "mgcp";
03257             /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
03258             mgcp_queue_frame(sub, &f);
03259             ast_mutex_lock(&sub->next->lock);
03260             if (sub->next->owner)
03261                mgcp_queue_frame(sub->next, &f);
03262             ast_mutex_unlock(&sub->next->lock);
03263             if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
03264                memset(p->curtone, 0, sizeof(p->curtone));
03265             }
03266          } else {
03267             p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
03268             p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
03269          }
03270       } else if (!strcasecmp(ev, "T")) {
03271          /* Digit timeout -- unimportant */
03272       } else if (!strcasecmp(ev, "ping")) {
03273          /* ping -- unimportant */
03274       } else {
03275          ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03276       }
03277    } else {
03278       ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
03279       transmit_response(sub, "510", req, "Unknown verb");
03280    }
03281    return 0;
03282 }

static void handle_response ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
int  result,
unsigned int  ident,
struct mgcp_request resp 
) [static]

Definition at line 2475 of file chan_mgcp.c.

References ast_copy_string(), ast_free, ast_log(), ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, dump_cmd_queues(), find_command(), get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, len(), mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), and transmit_notify_request().

Referenced by handle_incoming(), mgcpsock_read(), and retrans_pkt().

02477 {
02478    char *c;
02479    struct mgcp_request *req;
02480    struct mgcp_gateway *gw = p->parent;
02481 
02482    if (result < 200) {
02483       /* provisional response */
02484       return;
02485    }
02486 
02487    if (p->slowsequence) 
02488       req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02489    else if (sub)
02490       req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02491    else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02492       req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02493 
02494    if (!req) {
02495       ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n",
02496             gw->name, ident);
02497       return;
02498    }
02499 
02500    if (p && (result >= 400) && (result <= 599)) {
02501       switch (result) {
02502       case 401:
02503          p->hookstate = MGCP_OFFHOOK;
02504          break;
02505       case 402:
02506          p->hookstate = MGCP_ONHOOK;
02507          break;
02508       case 406:
02509          ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02510          break;
02511       case 407:
02512          ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02513          break;
02514       }
02515       if (sub) {
02516          if (sub->owner) {
02517             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
02518                result, p->name, p->parent->name, sub ? sub->id:-1);
02519             mgcp_queue_hangup(sub);
02520          }
02521       } else {
02522          if (p->sub->next->owner) {
02523             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
02524                result, p->name, p->parent->name, sub ? sub->id:-1);
02525             mgcp_queue_hangup(p->sub);
02526          }
02527 
02528          if (p->sub->owner) {
02529             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
02530                result, p->name, p->parent->name, sub ? sub->id:-1);
02531             mgcp_queue_hangup(p->sub);
02532          }
02533 
02534          dump_cmd_queues(p, NULL);
02535       }
02536    }
02537 
02538    if (resp) {
02539       if (req->cmd == MGCP_CMD_CRCX) {
02540          if ((c = get_header(resp, "I"))) {
02541             if (!ast_strlen_zero(c) && sub) {
02542                /* if we are hanging up do not process this conn. */
02543                if (sub->owner) {
02544                   if (!ast_strlen_zero(sub->cxident)) {
02545                      if (strcasecmp(c, sub->cxident)) {
02546                         ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02547                      }
02548                   }
02549                   ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
02550                   if (sub->tmpdest.sin_addr.s_addr) {
02551                      transmit_modify_with_sdp(sub, NULL, 0);
02552                   }
02553                } else {
02554                   /* XXX delete this one
02555                      callid and conn id may already be lost. 
02556                      so the following del conn may have a side effect of 
02557                      cleaning up the next subchannel */
02558                   transmit_connection_del(sub);
02559                }
02560             }
02561          }
02562       }
02563 
02564       if (req->cmd == MGCP_CMD_AUEP) {
02565          /* check stale connection ids */
02566          if ((c = get_header(resp, "I"))) {
02567             char *v, *n;
02568             int len;
02569             while ((v = get_csv(c, &len, &n))) {
02570                if (len) {
02571                   if (strncasecmp(v, p->sub->cxident, len) &&
02572                       strncasecmp(v, p->sub->next->cxident, len)) {
02573                      /* connection id not found. delete it */
02574                      char cxident[80] = "";
02575 
02576                      if (len > (sizeof(cxident) - 1))
02577                         len = sizeof(cxident) - 1;
02578                      ast_copy_string(cxident, v, len);
02579                      ast_verb(3, "Non existing connection id %s on %s@%s \n",
02580                                cxident, p->name, gw->name);
02581                      transmit_connection_del_w_params(p, NULL, cxident);
02582                   }
02583                }
02584                c = n;
02585             }
02586          }
02587 
02588          /* Try to determine the hookstate returned from an audit endpoint command */
02589          if ((c = get_header(resp, "ES"))) {
02590             if (!ast_strlen_zero(c)) {
02591                if (strstr(c, "hu")) {
02592                   if (p->hookstate != MGCP_ONHOOK) {
02593                      /* XXX cleanup if we think we are offhook XXX */
02594                      if ((p->sub->owner || p->sub->next->owner ) && 
02595                          p->hookstate == MGCP_OFFHOOK)
02596                         mgcp_queue_hangup(sub);
02597                      p->hookstate = MGCP_ONHOOK;
02598 
02599                      /* update the requested events according to the new hookstate */
02600                      transmit_notify_request(p->sub, "");
02601 
02602                      ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02603                      }
02604                } else if (strstr(c, "hd")) {
02605                   if (p->hookstate != MGCP_OFFHOOK) {
02606                      p->hookstate = MGCP_OFFHOOK;
02607 
02608                      /* update the requested events according to the new hookstate */
02609                      transmit_notify_request(p->sub, "");
02610 
02611                      ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02612                      }
02613                   }
02614                }
02615             }
02616          }
02617 
02618       if (resp && resp->lines) {
02619          /* do not process sdp if we are hanging up. this may be a late response */
02620          if (sub && sub->owner) {
02621             if (!sub->rtp)
02622                start_rtp(sub);
02623             if (sub->rtp)
02624                process_sdp(sub, resp);
02625          }
02626       }
02627    }
02628 
02629    ast_free(req);
02630 }

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

Definition at line 457 of file chan_mgcp.c.

References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), mgcp_endpoint::mailbox, and strsep().

00458 {
00459    int new_msgs;
00460    struct ast_event *event;
00461    char *mailbox, *context;
00462 
00463    context = mailbox = ast_strdupa(p->mailbox);
00464    strsep(&context, "@");
00465    if (ast_strlen_zero(context))
00466       context = "default";
00467 
00468    event = ast_event_get_cached(AST_EVENT_MWI,
00469       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
00470       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
00471       AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
00472       AST_EVENT_IE_END);
00473 
00474    if (event) {
00475       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
00476       ast_event_destroy(event);
00477    } else
00478       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
00479 
00480    return new_msgs;
00481 }

static int init_req ( struct mgcp_endpoint p,
struct mgcp_request req,
char *  verb 
) [static]

Definition at line 2008 of file chan_mgcp.c.

References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_gateway::isnamedottedip, mgcp_request::len, LOG_WARNING, MGCP_MAX_HEADERS, mgcp_gateway::name, mgcp_endpoint::name, oseq, and mgcp_endpoint::parent.

Referenced by initreqprep(), reqprep(), and transmit_register().

02009 {
02010    /* Initialize a response */
02011    if (req->headers || req->len) {
02012       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02013       return -1;
02014    }
02015    req->header[req->headers] = req->data + req->len;
02016    /* check if we need brackets around the gw name */
02017    if (p->parent->isnamedottedip)
02018       snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
02019    else
02020       snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
02021    req->len += strlen(req->header[req->headers]);
02022    if (req->headers < MGCP_MAX_HEADERS)
02023       req->headers++;
02024    else
02025       ast_log(LOG_WARNING, "Out of header space\n");
02026    return 0;
02027 }

static int init_resp ( struct mgcp_request req,
char *  resp,
struct mgcp_request orig,
char *  resprest 
) [static]

Definition at line 1991 of file chan_mgcp.c.

References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, LOG_WARNING, and MGCP_MAX_HEADERS.

Referenced by respprep().

01992 {
01993    /* Initialize a response */
01994    if (req->headers || req->len) {
01995       ast_log(LOG_WARNING, "Request already initialized?!?\n");
01996       return -1;
01997    }
01998    req->header[req->headers] = req->data + req->len;
01999    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
02000    req->len += strlen(req->header[req->headers]);
02001    if (req->headers < MGCP_MAX_HEADERS)
02002       req->headers++;
02003    else
02004       ast_log(LOG_WARNING, "Out of header space\n");
02005    return 0;
02006 }

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

Definition at line 4270 of file chan_mgcp.c.

References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), cli_mgcp, io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, mgcp_rtp, mgcp_tech, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().

04271 {
04272    if (!(sched = sched_context_create())) {
04273       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04274       return AST_MODULE_LOAD_FAILURE;
04275    }
04276 
04277    if (!(io = io_context_create())) {
04278       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04279       sched_context_destroy(sched);
04280       return AST_MODULE_LOAD_FAILURE;
04281    }
04282 
04283    if (reload_config(0))
04284       return AST_MODULE_LOAD_DECLINE;
04285 
04286    /* Make sure we can register our mgcp channel type */
04287    if (ast_channel_register(&mgcp_tech)) {
04288       ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04289       io_context_destroy(io);
04290       sched_context_destroy(sched);
04291       return AST_MODULE_LOAD_FAILURE;
04292    }
04293 
04294    ast_rtp_proto_register(&mgcp_rtp);
04295    ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04296    
04297    /* And start the monitor for the first time */
04298    restart_monitor();
04299 
04300    return AST_MODULE_LOAD_SUCCESS;
04301 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

Definition at line 1199 of file chan_mgcp.c.

References ast_channel::_state, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verb, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_subchannel::lock, MGCP_CX_SENDRECV, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().

01200 {
01201    int res = 0;
01202    struct mgcp_subchannel *sub = ast->tech_pvt;
01203    struct mgcp_endpoint *p = sub->parent;
01204 
01205    ast_mutex_lock(&sub->lock);
01206    sub->cxmode = MGCP_CX_SENDRECV;
01207    if (!sub->rtp) {
01208       start_rtp(sub);
01209    } else {
01210       transmit_modify_request(sub);
01211    }
01212    ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
01213          ast->name, p->name, p->parent->name, sub->id);
01214    if (ast->_state != AST_STATE_UP) {
01215       ast_setstate(ast, AST_STATE_UP);
01216       ast_debug(1, "mgcp_answer(%s)\n", ast->name);
01217       transmit_notify_request(sub, "");
01218       transmit_modify_request(sub);
01219    }
01220    ast_mutex_unlock(&sub->lock);
01221    return res;
01222 }

static int mgcp_call ( struct ast_channel ast,
char *  dest,
int  timeout 
) [static]

Definition at line 839 of file chan_mgcp.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_copy_string(), AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_verb, mgcp_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcpdebug, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, and ast_channel::varshead.

00840 {
00841    int res;
00842    struct mgcp_endpoint *p;
00843    struct mgcp_subchannel *sub;
00844    char tone[50] = "";
00845    const char *distinctive_ring = NULL;
00846    struct varshead *headp;
00847    struct ast_var_t *current;
00848 
00849    if (mgcpdebug) {
00850       ast_verb(3, "MGCP mgcp_call(%s)\n", ast->name);
00851    }
00852    sub = ast->tech_pvt;
00853    p = sub->parent;
00854    headp = &ast->varshead;
00855    AST_LIST_TRAVERSE(headp,current,entries) {
00856       /* Check whether there is an ALERT_INFO variable */
00857       if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
00858          distinctive_ring = ast_var_value(current);
00859       }
00860    }
00861 
00862    ast_mutex_lock(&sub->lock);
00863    switch (p->hookstate) {
00864    case MGCP_OFFHOOK:
00865       if (!ast_strlen_zero(distinctive_ring)) {
00866          snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
00867          if (mgcpdebug) {
00868             ast_verb(3, "MGCP distinctive callwait %s\n", tone);
00869          }
00870       } else {
00871          ast_copy_string(tone, "L/wt", sizeof(tone));
00872          if (mgcpdebug) {
00873             ast_verb(3, "MGCP normal callwait %s\n", tone);
00874          }
00875       }
00876       break;
00877    case MGCP_ONHOOK:
00878    default:
00879       if (!ast_strlen_zero(distinctive_ring)) {
00880          snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
00881          if (mgcpdebug) {
00882             ast_verb(3, "MGCP distinctive ring %s\n", tone);
00883          }
00884       } else {
00885          ast_copy_string(tone, "L/rg", sizeof(tone));
00886          if (mgcpdebug) {
00887             ast_verb(3, "MGCP default ring\n");
00888          }
00889       }
00890       break;
00891    }
00892 
00893    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00894       ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
00895       ast_mutex_unlock(&sub->lock);
00896       return -1;
00897    }
00898 
00899    res = 0;
00900    sub->outgoing = 1;
00901    sub->cxmode = MGCP_CX_RECVONLY;
00902    if (p->type == TYPE_LINE) {
00903       if (!sub->rtp) {
00904          start_rtp(sub);
00905       } else {
00906          transmit_modify_request(sub);
00907       }
00908 
00909       if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00910          /* try to prevent a callwait from disturbing the other connection */
00911          sub->next->cxmode = MGCP_CX_RECVONLY;
00912          transmit_modify_request(sub->next);
00913       }
00914 
00915       transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
00916       ast_setstate(ast, AST_STATE_RINGING);
00917 
00918       if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00919          /* Put the connection back in sendrecv */
00920          sub->next->cxmode = MGCP_CX_SENDRECV;
00921          transmit_modify_request(sub->next);
00922       }
00923    } else {
00924       ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
00925       res = -1;
00926    }
00927    ast_mutex_unlock(&sub->lock);
00928    ast_queue_control(ast, AST_CONTROL_RINGING);
00929    return res;
00930 }

static int mgcp_devicestate ( void *  data  )  [static]

mgcp_devicestate: channel callback for device status monitoring

Parameters:
data tech/resource name of MGCP device to query
Callback for device state management in channel subsystem to obtain device status (up/down) of a specific MGCP endpoint

Returns:
device status result (from devicestate.h) AST_DEVICE_INVALID (not available) or AST_DEVICE_UNKNOWN (available but unknown state)

Definition at line 1368 of file chan_mgcp.c.

References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, and mgcp_gateway::next.

01369 {
01370    struct mgcp_gateway  *g;
01371    struct mgcp_endpoint *e = NULL;
01372    char *tmp, *endpt, *gw;
01373    int ret = AST_DEVICE_INVALID;
01374 
01375    endpt = ast_strdupa(data);
01376    if ((tmp = strchr(endpt, '@'))) {
01377       *tmp++ = '\0';
01378       gw = tmp;
01379    } else
01380       goto error;
01381 
01382    ast_mutex_lock(&gatelock);
01383    g = gateways;
01384    while (g) {
01385       if (strcasecmp(g->name, gw) == 0) {
01386          e = g->endpoints;
01387          break;
01388       }
01389       g = g->next;
01390    }
01391 
01392    if (!e)
01393       goto error;
01394 
01395    while (e) {
01396       if (strcasecmp(e->name, endpt) == 0)
01397          break;
01398       e = e->next;
01399    }
01400 
01401    if (!e)
01402       goto error;
01403 
01404    /*
01405     * As long as the gateway/endpoint is valid, we'll
01406     * assume that the device is available and its state
01407     * can be tracked.
01408     */
01409    ret = AST_DEVICE_UNKNOWN;
01410 
01411 error:
01412    ast_mutex_unlock(&gatelock);
01413    return ret;
01414 }

static int mgcp_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 1295 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, ast_channel::name, mgcp_subchannel::owner, and ast_channel::tech_pvt.

01296 {
01297    struct mgcp_subchannel *sub = newchan->tech_pvt;
01298 
01299    ast_mutex_lock(&sub->lock);
01300    ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01301    if (sub->owner != oldchan) {
01302       ast_mutex_unlock(&sub->lock);
01303       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01304       return -1;
01305    }
01306    sub->owner = newchan;
01307    ast_mutex_unlock(&sub->lock);
01308    return 0;
01309 }

static enum ast_rtp_get_result mgcp_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 3962 of file chan_mgcp.c.

References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, mgcp_endpoint::canreinvite, chan, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.

03963 {
03964    struct mgcp_subchannel *sub = NULL;
03965 
03966    if (!(sub = chan->tech_pvt) || !(sub->rtp))
03967       return AST_RTP_GET_FAILED;
03968 
03969    *rtp = sub->rtp;
03970 
03971    if (sub->parent->canreinvite)
03972       return AST_RTP_TRY_NATIVE;
03973    else
03974       return AST_RTP_TRY_PARTIAL;
03975 }

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 932 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_debug, ast_dsp_free(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

00933 {
00934    struct mgcp_subchannel *sub = ast->tech_pvt;
00935    struct mgcp_endpoint *p = sub->parent;
00936 
00937    ast_debug(1, "mgcp_hangup(%s)\n", ast->name);
00938    if (!ast->tech_pvt) {
00939       ast_debug(1, "Asked to hangup channel not connected\n");
00940       return 0;
00941    }
00942    if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00943       ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
00944       return 0;
00945    }
00946    ast_mutex_lock(&sub->lock);
00947    if (mgcpdebug) {
00948       ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00949    }
00950 
00951    if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00952       /* check whether other channel is active. */
00953       if (!sub->next->owner) {
00954          if (p->dtmfmode & MGCP_DTMF_HYBRID)
00955             p->dtmfmode &= ~MGCP_DTMF_INBAND;
00956          if (mgcpdebug) {
00957             ast_verb(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00958          }
00959          ast_dsp_free(p->dsp);
00960          p->dsp = NULL;
00961       }
00962    }
00963 
00964    sub->owner = NULL;
00965    if (!ast_strlen_zero(sub->cxident)) {
00966       transmit_connection_del(sub);
00967    }
00968    sub->cxident[0] = '\0';
00969    if ((sub == p->sub) && sub->next->owner) {
00970       if (p->hookstate == MGCP_OFFHOOK) {
00971          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00972             transmit_notify_request_with_callerid(p->sub, "L/wt", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
00973          }
00974       } else {
00975          /* set our other connection as the primary and swith over to it */
00976          p->sub = sub->next;
00977          p->sub->cxmode = MGCP_CX_RECVONLY;
00978          transmit_modify_request(p->sub);
00979          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00980             transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
00981          }
00982       }
00983 
00984    } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00985       transmit_notify_request(sub, "L/v");
00986    } else if (p->hookstate == MGCP_OFFHOOK) {
00987       transmit_notify_request(sub, "L/ro");
00988    } else {
00989       transmit_notify_request(sub, "");
00990    }
00991 
00992    ast->tech_pvt = NULL;
00993    sub->alreadygone = 0;
00994    sub->outgoing = 0;
00995    sub->cxmode = MGCP_CX_INACTIVE;
00996    sub->callid[0] = '\0';
00997    if (p) {
00998       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
00999    }
01000    /* Reset temporary destination */
01001    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
01002    if (sub->rtp) {
01003       ast_rtp_destroy(sub->rtp);
01004       sub->rtp = NULL;
01005    }
01006 
01007    ast_module_unref(ast_module_info->self);
01008 
01009    if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
01010       p->hidecallerid = 0;
01011       if (p->hascallwaiting && !p->callwaiting) {
01012          ast_verb(3, "Enabling call waiting on %s\n", ast->name);
01013          p->callwaiting = -1;
01014       }
01015       if (has_voicemail(p)) {
01016          if (mgcpdebug) {
01017             ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
01018                ast->name, p->name, p->parent->name);
01019          }
01020          transmit_notify_request(sub, "L/vmwi(+)");
01021       } else {
01022          if (mgcpdebug) {
01023             ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
01024                ast->name, p->name, p->parent->name);
01025          }
01026          transmit_notify_request(sub, "L/vmwi(-)");
01027       }
01028    }
01029    ast_mutex_unlock(&sub->lock);
01030    return 0;
01031 }

static int mgcp_indicate ( struct ast_channel ast,
int  ind,
const void *  data,
size_t  datalen 
) [static]

Definition at line 1448 of file chan_mgcp.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_new_source(), ast_verb, control2str(), mgcp_subchannel::lock, LOG_WARNING, mgcpdebug, ast_channel::name, ast_channel::tech_pvt, and transmit_notify_request().

01449 {
01450    struct mgcp_subchannel *sub = ast->tech_pvt;
01451    int res = 0;
01452 
01453    if (mgcpdebug) {
01454       ast_verb(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
01455          ind, control2str(ind), ast->name);
01456    }
01457    ast_mutex_lock(&sub->lock);
01458    switch(ind) {
01459    case AST_CONTROL_RINGING:
01460 #ifdef DLINK_BUGGY_FIRMWARE   
01461       transmit_notify_request(sub, "rt");
01462 #else
01463       transmit_notify_request(sub, "G/rt");
01464 #endif      
01465       break;
01466    case AST_CONTROL_BUSY:
01467       transmit_notify_request(sub, "L/bz");
01468       break;
01469    case AST_CONTROL_CONGESTION:
01470       transmit_notify_request(sub, "G/cg");
01471       break;
01472    case AST_CONTROL_HOLD:
01473       ast_moh_start(ast, data, NULL);
01474       break;
01475    case AST_CONTROL_UNHOLD:
01476       ast_moh_stop(ast);
01477       break;
01478    case AST_CONTROL_SRCUPDATE:
01479       ast_rtp_new_source(sub->rtp);
01480       break;
01481    case -1:
01482       transmit_notify_request(sub, "");
01483       break;
01484    default:
01485       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01486       res = -1;
01487    }
01488    ast_mutex_unlock(&sub->lock);
01489    return res;
01490 }

static struct ast_channel* mgcp_new ( struct mgcp_subchannel sub,
int  state 
) [static]

Definition at line 1492 of file chan_mgcp.c.

References accountcode, mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DTMF_DETECT, mgcp_endpoint::dtmfmode, ast_channel::exten, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, language, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_tech, ast_channel::name, name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by handle_hd_hf(), and mgcp_request().

01493 {
01494    struct ast_channel *tmp;
01495    struct mgcp_endpoint *i = sub->parent;
01496    int fmt;
01497 
01498    tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01499    if (tmp) {
01500       tmp->tech = &mgcp_tech;
01501       tmp->nativeformats = i->capability;
01502       if (!tmp->nativeformats)
01503          tmp->nativeformats = capability;
01504       fmt = ast_best_codec(tmp->nativeformats);
01505       ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01506       if (sub->rtp)
01507          ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
01508       if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01509          i->dsp = ast_dsp_new();
01510          ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
01511          /* this is to prevent clipping of dtmf tones during dsp processing */
01512          ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01513       } else {
01514          i->dsp = NULL;
01515       }
01516       if (state == AST_STATE_RING)
01517          tmp->rings = 1;
01518       tmp->writeformat = fmt;
01519       tmp->rawwriteformat = fmt;
01520       tmp->readformat = fmt;
01521       tmp->rawreadformat = fmt;
01522       tmp->tech_pvt = sub;
01523       if (!ast_strlen_zero(i->language))
01524          ast_string_field_set(tmp, language, i->language);
01525       if (!ast_strlen_zero(i->accountcode))
01526          ast_string_field_set(tmp, accountcode, i->accountcode);
01527       if (i->amaflags)
01528          tmp->amaflags = i->amaflags;
01529       sub->owner = tmp;
01530       ast_module_ref(ast_module_info->self);
01531       tmp->callgroup = i->callgroup;
01532       tmp->pickupgroup = i->pickupgroup;
01533       ast_string_field_set(tmp, call_forward, i->call_forward);
01534       ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
01535       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01536 
01537       /* Don't use ast_set_callerid() here because it will
01538        * generate a needless NewCallerID event */
01539       tmp->cid.cid_ani = ast_strdup(i->cid_num);
01540       
01541       if (!i->adsi)
01542          tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01543       tmp->priority = 1;
01544       if (sub->rtp)
01545          ast_jb_configure(tmp, &global_jbconf);
01546       if (state != AST_STATE_DOWN) {
01547          if (ast_pbx_start(tmp)) {
01548             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01549             ast_hangup(tmp);
01550             tmp = NULL;
01551          }
01552       }
01553       ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
01554             tmp->name, ast_state2str(state));
01555    } else {
01556       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01557    }
01558    return tmp;
01559 }

static int mgcp_postrequest ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
char *  data,
int  len,
unsigned int  seqno 
) [static]

Definition at line 689 of file chan_mgcp.c.

References __mgcp_xmit(), ast_free, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_tvnow(), DEFAULT_RETRANS, msg, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, mgcp_endpoint::next, mgcp_endpoint::parent, retrans_pkt(), and mgcp_gateway::retransid.

Referenced by find_command(), and send_request().

00691 {
00692    struct mgcp_message *msg;
00693    struct mgcp_message *cur;
00694    struct mgcp_gateway *gw;
00695    struct timeval tv;
00696 
00697    msg = ast_malloc(sizeof(*msg) + len);
00698    if (!msg) {
00699       return -1;
00700    }
00701    gw = ((p && p->parent) ? p->parent : NULL);
00702    if (!gw) {
00703       ast_free(msg);
00704       return -1;
00705    }
00706 /* SC
00707    time(&t);
00708    if (gw->messagepending && (gw->lastouttime + 20 < t)) {
00709       ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
00710          gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
00711       dump_queue(sub->parent);
00712    }
00713 */
00714    msg->owner_sub = sub;
00715    msg->owner_ep = p;
00716    msg->seqno = seqno;
00717    msg->next = NULL;
00718    msg->len = len;
00719    msg->retrans = 0;
00720    memcpy(msg->buf, data, msg->len);
00721 
00722    ast_mutex_lock(&gw->msgs_lock);
00723    cur = gw->msgs;
00724    if (cur) {
00725       while(cur->next)
00726          cur = cur->next;
00727       cur->next = msg;
00728    } else {
00729       gw->msgs = msg;
00730    }
00731 
00732    tv = ast_tvnow();
00733    msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
00734 
00735    if (gw->retransid == -1)
00736       gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00737    ast_mutex_unlock(&gw->msgs_lock);
00738 /* SC
00739    if (!gw->messagepending) {
00740       gw->messagepending = 1;
00741       gw->lastout = seqno;
00742       gw->lastouttime = t;
00743 */
00744    __mgcp_xmit(gw, msg->buf, msg->len);
00745       /* XXX Should schedule retransmission XXX */
00746 /* SC
00747    } else
00748       ast_debug(1, "Deferring transmission of transaction %d\n", seqno);
00749 */
00750    return 0;
00751 }

static void mgcp_queue_control ( struct mgcp_subchannel sub,
int  control 
) [static]

Definition at line 620 of file chan_mgcp.c.

References AST_FRAME_CONTROL, f, and mgcp_queue_frame().

Referenced by handle_hd_hf().

00621 {
00622    struct ast_frame f = { AST_FRAME_CONTROL, };
00623    f.subclass = control;
00624    return mgcp_queue_frame(sub, &f);
00625 }

static void mgcp_queue_frame ( struct mgcp_subchannel sub,
struct ast_frame f 
) [static]

Definition at line 588 of file chan_mgcp.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, mgcp_subchannel::lock, and mgcp_subchannel::owner.

Referenced by handle_request(), and mgcp_queue_control().

00589 {
00590    for(;;) {
00591       if (sub->owner) {
00592          if (!ast_channel_trylock(sub->owner)) {
00593             ast_queue_frame(sub->owner, f);
00594             ast_channel_unlock(sub->owner);
00595             break;
00596          } else {
00597             DEADLOCK_AVOIDANCE(&sub->lock);
00598          }
00599       } else
00600          break;
00601    }
00602 }

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

Definition at line 604 of file chan_mgcp.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.

Referenced by attempt_transfer(), handle_request(), and handle_response().

00605 {
00606    for(;;) {
00607       if (sub->owner) {
00608          if (!ast_channel_trylock(sub->owner)) {
00609             ast_queue_hangup(sub->owner);
00610             ast_channel_unlock(sub->owner);
00611             break;
00612          } else {
00613             DEADLOCK_AVOIDANCE(&sub->lock);
00614          }
00615       } else
00616          break;
00617    }
00618 }

static struct ast_frame * mgcp_read ( struct ast_channel ast  )  [static]

Definition at line 1255 of file chan_mgcp.c.

References ast_mutex_lock(), ast_mutex_unlock(), f, mgcp_subchannel::lock, mgcp_rtp_read(), and ast_channel::tech_pvt.

01256 {
01257    struct ast_frame *f;
01258    struct mgcp_subchannel *sub = ast->tech_pvt;
01259    ast_mutex_lock(&sub->lock);
01260    f = mgcp_rtp_read(sub);
01261    ast_mutex_unlock(&sub->lock);
01262    return f;
01263 }

static char * mgcp_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4303 of file chan_mgcp.c.

References ast_cli_args::argc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, LOG_WARNING, mgcp_reload_lock, mgcp_reloading, restart_monitor(), and ast_cli_entry::usage.

Referenced by reload(), and unload_module().

04304 {
04305    static int deprecated = 0;
04306 
04307    if (e) {
04308       switch (cmd) {
04309       case CLI_INIT:
04310          e->command = "mgcp reload";
04311          e->usage =
04312             "Usage: mgcp reload\n"
04313             "       'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n";
04314          return NULL;
04315       case CLI_GENERATE:
04316          return NULL;
04317       }
04318    }
04319 
04320    if (!deprecated && a && a->argc > 0) {
04321       ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
04322       deprecated = 1;
04323    }
04324 
04325    ast_mutex_lock(&mgcp_reload_lock);
04326    if (mgcp_reloading) {
04327       ast_verbose("Previous mgcp reload not yet done\n");
04328    } else
04329       mgcp_reloading = 1;
04330    ast_mutex_unlock(&mgcp_reload_lock);
04331    restart_monitor();
04332    return CLI_SUCCESS;
04333 }

static struct ast_channel * mgcp_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 3520 of file chan_mgcp.c.

References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, capability, mgcp_endpoint::dnd, find_subchannel_and_lock(), has_voicemail(), mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), MGCP_ONHOOK, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), and transmit_notify_request().

03521 {
03522    int oldformat;
03523    struct mgcp_subchannel *sub;
03524    struct ast_channel *tmpc = NULL;
03525    char tmp[256];
03526    char *dest = data;
03527 
03528    oldformat = format;
03529    format &= capability;
03530    if (!format) {
03531       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03532       return NULL;
03533    }
03534    ast_copy_string(tmp, dest, sizeof(tmp));
03535    if (ast_strlen_zero(tmp)) {
03536       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03537       return NULL;
03538    }
03539    sub = find_subchannel_and_lock(tmp, 0, NULL);
03540    if (!sub) {
03541       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03542       *cause = AST_CAUSE_UNREGISTERED;
03543       return NULL;
03544    }
03545    
03546    ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
03547    ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03548          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03549    /* Must be busy */
03550    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03551       ((!sub->parent->callwaiting) && (sub->owner)) ||
03552        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03553       if (sub->parent->hookstate == MGCP_ONHOOK) {
03554          if (has_voicemail(sub->parent)) {
03555             transmit_notify_request(sub,"L/vmwi(+)");
03556          } else {
03557             transmit_notify_request(sub,"L/vmwi(-)");
03558          }
03559       }
03560       *cause = AST_CAUSE_BUSY;
03561       ast_mutex_unlock(&sub->lock);
03562       return NULL;
03563    }
03564    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03565    ast_mutex_unlock(&sub->lock);
03566    if (!tmpc)
03567       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03568    restart_monitor();
03569    return tmpc;
03570 }

static struct ast_frame* mgcp_rtp_read ( struct mgcp_subchannel sub  )  [static]

Definition at line 1224 of file chan_mgcp.c.

References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, f, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, and ast_channel::writeformat.

Referenced by mgcp_read().

01225 {
01226    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
01227    struct ast_frame *f;
01228 
01229    f = ast_rtp_read(sub->rtp);
01230    /* Don't send RFC2833 if we're not supposed to */
01231    if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01232       return &ast_null_frame;
01233    if (sub->owner) {
01234       /* We already hold the channel lock */
01235       if (f->frametype == AST_FRAME_VOICE) {
01236          if (f->subclass != sub->owner->nativeformats) {
01237             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
01238             sub->owner->nativeformats = f->subclass;
01239             ast_set_read_format(sub->owner, sub->owner->readformat);
01240             ast_set_write_format(sub->owner, sub->owner->writeformat);
01241          }
01242          /* Courtesy fearnor aka alex@pilosoft.com */
01243          if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01244 #if 0
01245             ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01246 #endif
01247             f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01248          }
01249       }
01250    }
01251    return f;
01252 }

static int mgcp_senddigit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 1311 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, and ast_channel::tech_pvt.

01312 {
01313    struct mgcp_subchannel *sub = ast->tech_pvt;
01314    struct mgcp_endpoint *p = sub->parent;
01315    int res = 0;
01316 
01317    ast_mutex_lock(&sub->lock);
01318    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01319       ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
01320       res = -1; /* Let asterisk play inband indications */
01321    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01322       ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
01323       ast_rtp_senddigit_begin(sub->rtp, digit);
01324    } else {
01325       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01326    }
01327    ast_mutex_unlock(&sub->lock);
01328 
01329    return res;
01330 }

static int mgcp_senddigit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 1332 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_end(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, and transmit_notify_request().

01333 {
01334    struct mgcp_subchannel *sub = ast->tech_pvt;
01335    struct mgcp_endpoint *p = sub->parent;
01336    int res = 0;
01337    char tmp[4];
01338 
01339    ast_mutex_lock(&sub->lock);
01340    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01341       ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
01342       res = -1; /* Tell Asterisk to stop inband indications */
01343    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01344       ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
01345       tmp[0] = 'D';
01346       tmp[1] = '/';
01347       tmp[2] = digit;
01348       tmp[3] = '\0';
01349       transmit_notify_request(sub, tmp);
01350                 ast_rtp_senddigit_end(sub->rtp, digit);
01351    } else {
01352       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01353    }
01354    ast_mutex_unlock(&sub->lock);
01355 
01356    return res;
01357 }

static int mgcp_set_rtp_peer ( struct ast_channel chan,
struct ast_rtp rtp,
struct ast_rtp vrtp,
struct ast_rtp trtp,
int  codecs,
int  nat_active 
) [static]

Definition at line 3977 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, chan, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_modify_with_sdp().

03978 {
03979    /* XXX Is there such thing as video support with MGCP? XXX */
03980    struct mgcp_subchannel *sub;
03981    sub = chan->tech_pvt;
03982    if (sub && !sub->alreadygone) {
03983       transmit_modify_with_sdp(sub, rtp, codecs);
03984       return 0;
03985    }
03986    return -1;
03987 }

static void* mgcp_ss ( void *  data  )  [static]

Definition at line 2659 of file chan_mgcp.c.

References ast_bridged_channel(), ast_canmatch_extension(), ast_copy_string(), ast_db_put(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strlen_zero(), ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, chan, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, and transmit_notify_request().

Referenced by handle_hd_hf().

02660 {
02661    struct ast_channel *chan = data;
02662    struct mgcp_subchannel *sub = chan->tech_pvt;
02663    struct mgcp_endpoint *p = sub->parent;
02664    /* char exten[AST_MAX_EXTENSION] = ""; */
02665    int len = 0;
02666    int timeout = firstdigittimeout;
02667    int res= 0;
02668    int getforward = 0;
02669    int loop_pause = 100;
02670 
02671    len = strlen(p->dtmf_buf);
02672 
02673    while(len < AST_MAX_EXTENSION-1) {
02674       res = 1;  /* Assume that we will get a digit */
02675       while (strlen(p->dtmf_buf) == len){
02676          ast_safe_sleep(chan, loop_pause);
02677          timeout -= loop_pause;
02678          if (timeout <= 0){
02679             res = 0;
02680             break;
02681          }
02682          res = 1;
02683       }
02684 
02685       timeout = 0;
02686       len = strlen(p->dtmf_buf);
02687 
02688       if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) {
02689          /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02690          ast_indicate(chan, -1);
02691       } else {
02692          /* XXX Redundant?  We should already be playing dialtone */
02693          /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
02694          transmit_notify_request(sub, "L/dl");
02695       }
02696       if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02697          if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02698             if (getforward) {
02699                /* Record this as the forwarding extension */
02700                ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 
02701                ast_verb(3, "Setting call forward to '%s' on channel %s\n",
02702                      p->call_forward, chan->name);
02703                /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02704                transmit_notify_request(sub, "L/sl");
02705                if (res)
02706                   break;
02707                usleep(500000);
02708                /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02709                ast_indicate(chan, -1);
02710                sleep(1);
02711                memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02712                /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
02713                transmit_notify_request(sub, "L/dl");
02714                len = 0;
02715                getforward = 0;
02716             } else {
02717                /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02718                ast_indicate(chan, -1);
02719                ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
02720                memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02721                ast_set_callerid(chan,
02722                   p->hidecallerid ? "" : p->cid_num,
02723                   p->hidecallerid ? "" : p->cid_name,
02724                   chan->cid.cid_ani ? NULL : p->cid_num);
02725                ast_setstate(chan, AST_STATE_RING);
02726                /*dahdi_enable_ec(p);*/
02727                if (p->dtmfmode & MGCP_DTMF_HYBRID) {
02728                   p->dtmfmode |= MGCP_DTMF_INBAND;
02729                   ast_indicate(chan, -1);
02730                }
02731                res = ast_pbx_run(chan);
02732                if (res) {
02733                   ast_log(LOG_WARNING, "PBX exited non-zero\n");
02734                   /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
02735                   /*transmit_notify_request(p, "nbz", 1);*/
02736                   transmit_notify_request(sub, "G/cg");
02737                }
02738                return NULL;
02739             }
02740          } else {
02741             /* It's a match, but they just typed a digit, and there is an ambiguous match,
02742                so just set the timeout to matchdigittimeout and wait some more */
02743             timeout = matchdigittimeout;
02744          }
02745       } else if (res == 0) {
02746          ast_debug(1, "not enough digits (and no ambiguous match)...\n");
02747          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
02748          transmit_notify_request(sub, "G/cg");
02749          /*dahdi_wait_event(p->subs[index].zfd);*/
02750          ast_hangup(chan);
02751          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02752          return NULL;
02753       } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
02754          ast_verb(3, "Disabling call waiting on %s\n", chan->name);
02755          /* Disable call waiting if enabled */
02756          p->callwaiting = 0;
02757          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02758          transmit_notify_request(sub, "L/sl");
02759          len = 0;
02760          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02761          timeout = firstdigittimeout;
02762       } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
02763          /* Scan all channels and see if any there
02764           * ringing channqels with that have call groups
02765           * that equal this channels pickup group  
02766           */
02767          if (ast_pickup_call(chan)) {
02768             ast_log(LOG_WARNING, "No call pickup possible...\n");
02769             /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
02770             transmit_notify_request(sub, "G/cg");
02771          }
02772          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02773          ast_hangup(chan);
02774          return NULL;
02775       } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
02776          ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
02777          /* Disable Caller*ID if enabled */
02778          p->hidecallerid = 1;
02779          ast_set_callerid(chan, "", "", NULL);
02780          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02781          transmit_notify_request(sub, "L/sl");
02782          len = 0;
02783          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02784          timeout = firstdigittimeout;
02785       } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
02786          res = 0;
02787          if (!ast_strlen_zero(p->lastcallerid)) {
02788             res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
02789          }
02790          if (!res)
02791             /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02792             transmit_notify_request(sub, "L/sl");
02793          break;
02794       } else if (!strcmp(p->dtmf_buf, "*78")) {
02795          /* Do not disturb */
02796          ast_verb(3, "Enabled DND on channel %s\n", chan->name);
02797          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02798          transmit_notify_request(sub, "L/sl");
02799          p->dnd = 1;
02800          getforward = 0;
02801          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02802          len = 0;
02803       } else if (!strcmp(p->dtmf_buf, "*79")) {
02804          /* Do not disturb */
02805          ast_verb(3, "Disabled DND on channel %s\n", chan->name);
02806          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02807          transmit_notify_request(sub, "L/sl");
02808          p->dnd = 0;
02809          getforward = 0;
02810          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02811          len = 0;
02812       } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
02813          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02814          transmit_notify_request(sub, "L/sl");
02815          getforward = 1;
02816          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02817          len = 0;
02818       } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
02819          ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name);
02820          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02821          transmit_notify_request(sub, "L/sl");
02822          memset(p->call_forward, 0, sizeof(p->call_forward));
02823          getforward = 0;
02824          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02825          len = 0;
02826       } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) && 
02827          sub->next->owner && ast_bridged_channel(sub->next->owner)) {
02828          /* This is a three way call, the main call being a real channel, 
02829             and we're parking the first call. */
02830          ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
02831          ast_verb(3, "Parking call to '%s'\n", chan->name);
02832          break;
02833       } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
02834          ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
02835          res = ast_db_put("blacklist", p->lastcallerid, "1");
02836          if (!res) {
02837             /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02838             transmit_notify_request(sub, "L/sl");
02839             memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02840             len = 0;
02841          }
02842       } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
02843          ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
02844          /* Enable Caller*ID if enabled */
02845          p->hidecallerid = 0;
02846          ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
02847          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02848          transmit_notify_request(sub, "L/sl");
02849          len = 0;
02850          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02851          timeout = firstdigittimeout;
02852       } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) &&
02853             ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
02854          ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
02855          break;
02856       }
02857       if (!timeout)
02858          timeout = gendigittimeout;
02859       if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf))
02860          /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
02861          ast_indicate(chan, -1);
02862    }
02863 #if 0
02864    for (;;) {
02865       res = ast_waitfordigit(chan, to);
02866       if (!res) {
02867          ast_debug(1, "Timeout...\n");
02868          break;
02869       }
02870       if (res < 0) {
02871          ast_debug(1, "Got hangup...\n");
02872          ast_hangup(chan);
02873          break;
02874       }
02875       exten[pos++] = res;
02876       if (!ast_ignore_pattern(chan->context, exten))
02877          ast_indicate(chan, -1);
02878       if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
02879          if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
02880             to = 3000;
02881          else
02882             to = 8000;
02883       } else
02884          break;
02885    }
02886    if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
02887       ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
02888       if (!p->rtp) {
02889          start_rtp(p);
02890       }
02891       ast_setstate(chan, AST_STATE_RING);
02892       chan->rings = 1;
02893       if (ast_pbx_run(chan)) {
02894          ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
02895       } else {
02896          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02897          return NULL;
02898       }
02899    }
02900 #endif
02901    ast_hangup(chan);
02902    memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02903    return NULL;
02904 }

static int mgcp_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 1265 of file chan_mgcp.c.

References AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.

01266 {
01267    struct mgcp_subchannel *sub = ast->tech_pvt;
01268    int res = 0;
01269    if (frame->frametype != AST_FRAME_VOICE) {
01270       if (frame->frametype == AST_FRAME_IMAGE)
01271          return 0;
01272       else {
01273          ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01274          return 0;
01275       }
01276    } else {
01277       if (!(frame->subclass & ast->nativeformats)) {
01278          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01279             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01280          return -1;
01281       }
01282    }
01283    if (sub) {
01284       ast_mutex_lock(&sub->lock);
01285       if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01286          if (sub->rtp) {
01287             res =  ast_rtp_write(sub->rtp, frame);
01288          }
01289       }
01290       ast_mutex_unlock(&sub->lock);
01291    }
01292    return res;
01293 }

static int mgcpsock_read ( int *  id,
int  fd,
short  events,
void *  ignore 
) [static]

Definition at line 3316 of file chan_mgcp.c.

References ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, ast_strlen_zero(), ast_verbose(), errno, find_and_retrans(), find_subchannel_and_lock(), handle_request(), handle_response(), len(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_subchannel::parent, parse(), mgcp_gateway::retransid, and mgcp_message::seqno.

Referenced by do_monitor().

03317 {
03318    struct mgcp_request req;
03319    struct sockaddr_in sin;
03320    struct mgcp_subchannel *sub;
03321    int res;
03322    socklen_t len;
03323    int result;
03324    int ident;
03325    len = sizeof(sin);
03326    memset(&req, 0, sizeof(req));
03327    res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03328    if (res < 0) {
03329       if (errno != ECONNREFUSED)
03330          ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03331       return 1;
03332    }
03333    req.data[res] = '\0';
03334    req.len = res;
03335    if (mgcpdebug) {
03336       ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03337    }
03338    parse(&req);
03339    if (req.headers < 1) {
03340       /* Must have at least one header */
03341       return 1;
03342    }
03343    if (ast_strlen_zero(req.identifier)) {
03344       ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03345       return 1;
03346    }
03347 
03348    if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
03349       /* Try to find who this message is for, if it's important */
03350       sub = find_subchannel_and_lock(NULL, ident, &sin);
03351       if (sub) {
03352          struct mgcp_gateway *gw = sub->parent->parent;
03353          struct mgcp_message *cur, *prev;
03354 
03355          ast_mutex_unlock(&sub->lock);
03356          ast_mutex_lock(&gw->msgs_lock);
03357          for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03358             if (cur->seqno == ident) {
03359                ast_debug(1, "Got response back on transaction %d\n", ident);
03360                if (prev)
03361                   prev->next = cur->next;
03362                else
03363                   gw->msgs = cur->next;
03364                break;
03365             }
03366          }
03367 
03368          /* stop retrans timer if the queue is empty */
03369          if (!gw->msgs) {
03370             AST_SCHED_DEL(sched, gw->retransid);
03371          }
03372 
03373          ast_mutex_unlock(&gw->msgs_lock);
03374          if (cur) {
03375             handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03376             ast_free(cur);
03377             return 1;
03378          }
03379 
03380          ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 
03381             gw->name, ident);
03382       }
03383    } else {
03384       if (ast_strlen_zero(req.endpoint) || 
03385             ast_strlen_zero(req.version) || 
03386          ast_strlen_zero(req.verb)) {
03387          ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03388          return 1;
03389       }
03390       /* Process request, with iflock held */
03391       sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03392       if (sub) {
03393          /* look first to find a matching response in the queue */
03394          if (!find_and_retrans(sub, &req))
03395             /* pass the request off to the currently mastering subchannel */
03396             handle_request(sub, &req, &sin);
03397          ast_mutex_unlock(&sub->lock);
03398       }
03399    }
03400    return 1;
03401 }

static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 449 of file chan_mgcp.c.

00450 {
00451    /* This module does not handle MWI in an event-based manner.  However, it
00452     * subscribes to MWI for each mailbox that is configured so that the core
00453     * knows that we care about it.  Then, chan_mgcp will get the MWI from the
00454     * event cache instead of checking the mailbox directly. */
00455 }

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1759 of file chan_mgcp.c.

References ast_log(), ast_strlen_zero(), ast_verbose(), mgcp_request::data, mgcp_request::endpoint, f, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::line, mgcp_request::lines, LOG_WARNING, MGCP_MAX_HEADERS, MGCP_MAX_LINES, mgcpdebug, mgcp_request::verb, and mgcp_request::version.

Referenced by acf_channel_read(), add_agent(), app_exec(), aqm_exec(), ast_parse_allow_disallow(), astman_get_variables(), conf_run(), cut_internal(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), enum_query_read(), enum_result_read(), execif_exec(), find_conf(), function_agent(), get_in_brackets(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), mgcpsock_read(), misdn_check_l2l1(), misdn_facility_exec(), misdn_set_opt_exec(), mixmonitor_exec(), oss_call(), oss_request(), pbx_builtin_background(), pbx_builtin_waitexten(), play_moh_exec(), pqm_exec(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), rcvfax_exec(), record_exec(), reload_agents(), reload_queues(), retrydial_exec(), rqm_exec(), sayunixtime_exec(), sendtext_exec(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), start_moh_exec(), start_monitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), and zapateller_exec().

01760 {
01761    /* Divide fields by NULL's */
01762    char *c;
01763    int f = 0;
01764    c = req->data;
01765 
01766    /* First header starts immediately */
01767    req->header[f] = c;
01768    while(*c) {
01769       if (*c == '\n') {
01770          /* We've got a new header */
01771          *c = 0;
01772 #if 0
01773          printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01774 #endif         
01775          if (ast_strlen_zero(req->header[f])) {
01776             /* Line by itself means we're now in content */
01777             c++;
01778             break;
01779          }
01780          if (f >= MGCP_MAX_HEADERS - 1) {
01781             ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01782          } else
01783             f++;
01784          req->header[f] = c + 1;
01785       } else if (*c == '\r') {
01786          /* Ignore but eliminate \r's */
01787          *c = 0;
01788       }
01789       c++;
01790    }
01791    /* Check for last header */
01792    if (!ast_strlen_zero(req->header[f])) 
01793       f++;
01794    req->headers = f;
01795    /* Now we process any mime content */
01796    f = 0;
01797    req->line[f] = c;
01798    while(*c) {
01799       if (*c == '\n') {
01800          /* We've got a new line */
01801          *c = 0;
01802 #if 0
01803          printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01804 #endif         
01805          if (f >= MGCP_MAX_LINES - 1) {
01806             ast_log(LOG_WARNING, "Too many SDP lines...\n");
01807          } else
01808             f++;
01809          req->line[f] = c + 1;
01810       } else if (*c == '\r') {
01811          /* Ignore and eliminate \r's */
01812          *c = 0;
01813       }
01814       c++;
01815    }
01816    /* Check for last line */
01817    if (!ast_strlen_zero(req->line[f])) 
01818       f++;
01819    req->lines = f;
01820    /* Parse up the initial header */
01821    c = req->header[0];
01822    while(*c && *c < 33) c++;
01823    /* First the verb */
01824    req->verb = c;
01825    while(*c && (*c > 32)) c++;
01826    if (*c) {
01827       *c = '\0';
01828       c++;
01829       while(*c && (*c < 33)) c++;
01830       req->identifier = c;
01831       while(*c && (*c > 32)) c++;
01832       if (*c) {
01833          *c = '\0';
01834          c++;
01835          while(*c && (*c < 33)) c++;
01836          req->endpoint = c;
01837          while(*c && (*c > 32)) c++;
01838          if (*c) {
01839             *c = '\0';
01840             c++;
01841             while(*c && (*c < 33)) c++;
01842             req->version = c;
01843             while(*c && (*c > 32)) c++;
01844             while(*c && (*c < 33)) c++;
01845             while(*c && (*c > 32)) c++;
01846             *c = '\0';
01847          }
01848       }
01849    }
01850       
01851    if (mgcpdebug) {
01852       ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01853          req->verb, req->identifier, req->endpoint, req->version);
01854       ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01855    }
01856    if (*c) 
01857       ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01858 }

static int process_sdp ( struct mgcp_subchannel sub,
struct mgcp_request req 
) [static]

Definition at line 1860 of file chan_mgcp.c.

References ahp, ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_get_current_formats(), ast_rtp_pt_clear(), ast_rtp_set_m_type(), ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_strdupa, ast_strlen_zero(), ast_verbose(), capability, mgcp_endpoint::capability, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, mgcpdebug, mgcp_endpoint::nonCodecCapability, nonCodecCapability, mgcp_subchannel::parent, mgcp_subchannel::rtp, sdpLineNum_iterator_init(), and mgcp_endpoint::sub.

Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().

01861 {
01862    char *m;
01863    char *c;
01864    char *a;
01865    char host[258];
01866    int len;
01867    int portno;
01868    int peercapability, peerNonCodecCapability;
01869    struct sockaddr_in sin;
01870    char *codecs;
01871    struct ast_hostent ahp; struct hostent *hp;
01872    int codec, codec_count=0;
01873    int iterator;
01874    struct mgcp_endpoint *p = sub->parent;
01875 
01876    /* Get codec and RTP info from SDP */
01877    m = get_sdp(req, "m");
01878    c = get_sdp(req, "c");
01879    if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01880       ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01881       return -1;
01882    }
01883    if (sscanf(c, "IN IP4 %256s", host) != 1) {
01884       ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01885       return -1;
01886    }
01887    /* XXX This could block for a long time, and block the main thread! XXX */
01888    hp = ast_gethostbyname(host, &ahp);
01889    if (!hp) {
01890       ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01891       return -1;
01892    }
01893    if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
01894       ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
01895       return -1;
01896    }
01897    sin.sin_family = AF_INET;
01898    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01899    sin.sin_port = htons(portno);
01900    ast_rtp_set_peer(sub->rtp, &sin);
01901 #if 0
01902    printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01903 #endif   
01904    /* Scan through the RTP payload types specified in a "m=" line: */
01905    ast_rtp_pt_clear(sub->rtp);
01906    codecs = ast_strdupa(m + len);
01907    while (!ast_strlen_zero(codecs)) {
01908       if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
01909          if (codec_count)
01910             break;
01911          ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01912          return -1;
01913       }
01914       ast_rtp_set_m_type(sub->rtp, codec);
01915       codec_count++;
01916       codecs += len;
01917    }
01918 
01919    /* Next, scan through each "a=rtpmap:" line, noting each */
01920    /* specified RTP payload type (with corresponding MIME subtype): */
01921    sdpLineNum_iterator_init(&iterator);
01922    while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01923       char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
01924       if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
01925          continue;
01926       /* Note: should really look at the 'freq' and '#chans' params too */
01927       ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
01928    }
01929 
01930    /* Now gather all of the codecs that were asked for: */
01931    ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
01932    p->capability = capability & peercapability;
01933    if (mgcpdebug) {
01934       ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01935          capability, peercapability, p->capability);
01936       ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01937          nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01938    }
01939    if (!p->capability) {
01940       ast_log(LOG_WARNING, "No compatible codecs!\n");
01941       return -1;
01942    }
01943    return 0;
01944 }

static void prune_gateways ( void   )  [static]

Definition at line 4051 of file chan_mgcp.c.

References ast_mutex_lock(), mgcp_gateway::delme, mgcp_endpoint::delme, destroy_endpoint(), mgcp_gateway::endpoints, gatelock, gateways, and mgcp_endpoint::next.

Referenced by reload_config(), and unload_module().

04052 {
04053    struct mgcp_gateway *g, *z, *r;
04054    struct mgcp_endpoint *e, *p, *t;
04055 
04056    ast_mutex_lock(&gatelock);
04057 
04058    /* prune gateways */
04059    for (z = NULL, g = gateways; g;) {
04060       /* prune endpoints */
04061       for (p = NULL, e = g->endpoints; e; ) {
04062          if (e->delme || g->delme) {
04063             t = e;
04064             e = e->next;
04065             if (!p)
04066                g->endpoints = e;
04067             else
04068                p->next = e;
04069             destroy_endpoint(t);
04070          } else {
04071             p = e;
04072             e = e->next;
04073          }
04074       }
04075 
04076       if (g->delme) {
04077          r = g;
04078          g = g->next;
04079          if (!z)
04080             gateways = g;
04081          else
04082             z->next = g;
04083 
04084          destroy_gateway(r);
04085       } else {
04086          z = g;
04087          g = g->next;
04088       }
04089    }
04090 
04091    ast_mutex_unlock(&gatelock);
04092 }

static int reload ( void   )  [static]

Definition at line 4335 of file chan_mgcp.c.

References mgcp_reload().

04336 {
04337    mgcp_reload(NULL, 0, NULL);
04338    return 0;
04339 }

static int reload_config ( int  reload  )  [static]

Definition at line 4094 of file chan_mgcp.c.

References __ourip, ahp, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_jb_read_conf(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_set_qos(), ast_sched_runq(), ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_gateway(), capability, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, cos, cos_audio, default_jbconf, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, dtmfmode, mgcp_gateway::endpoints, errno, format, gatelock, gateways, global_jbconf, hp, io, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcpsock_read_id, monitor_thread, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, netlock, mgcp_gateway::next, mgcp_endpoint::next, ast_variable::next, ourhost, ourport, prune_gateways(), tos, tos_audio, transmit_audit_endpoint(), and ast_variable::value.

04095 {
04096    struct ast_config *cfg;
04097    struct ast_variable *v;
04098    struct mgcp_gateway *g;
04099    struct mgcp_endpoint *e;
04100    char *cat;
04101    struct ast_hostent ahp;
04102    struct hostent *hp;
04103    int format;
04104    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04105    
04106    if (gethostname(ourhost, sizeof(ourhost)-1)) {
04107       ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04108       return 0;
04109    }
04110    cfg = ast_config_load(config, config_flags);
04111 
04112    /* We *must* have a config file otherwise stop immediately */
04113    if (!cfg) {
04114       ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04115       return 0;
04116    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
04117       return 0;
04118 
04119    memset(&bindaddr, 0, sizeof(bindaddr));
04120    dtmfmode = 0;
04121 
04122    /* Copy the default jb config over global_jbconf */
04123    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04124 
04125    v = ast_variable_browse(cfg, "general");
04126    while (v) {
04127       /* handle jb conf */
04128       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04129          v = v->next;
04130          continue;
04131       }
04132 
04133       /* Create the interface list */
04134       if (!strcasecmp(v->name, "bindaddr")) {
04135          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04136             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04137          } else {
04138             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04139          }
04140       } else if (!strcasecmp(v->name, "allow")) {
04141          format = ast_getformatbyname(v->value);
04142          if (format < 1) 
04143             ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04144          else
04145             capability |= format;
04146       } else if (!strcasecmp(v->name, "disallow")) {
04147          format = ast_getformatbyname(v->value);
04148          if (format < 1) 
04149             ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04150          else
04151             capability &= ~format;
04152       } else if (!strcasecmp(v->name, "tos")) {
04153          if (ast_str2tos(v->value, &tos))
04154              ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
04155       } else if (!strcasecmp(v->name, "tos_audio")) {
04156          if (ast_str2tos(v->value, &tos_audio))
04157              ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04158       } else if (!strcasecmp(v->name, "cos")) {          
04159          if (ast_str2cos(v->value, &cos))
04160              ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
04161       } else if (!strcasecmp(v->name, "cos_audio")) {          
04162          if (ast_str2cos(v->value, &cos_audio))
04163              ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04164       } else if (!strcasecmp(v->name, "port")) {
04165          if (sscanf(v->value, "%d", &ourport) == 1) {
04166             bindaddr.sin_port = htons(ourport);
04167          } else {
04168             ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04169          }
04170       }
04171       v = v->next;
04172    }
04173 
04174    /* mark existing entries for deletion */
04175    ast_mutex_lock(&gatelock);
04176    g = gateways;
04177    while (g) {
04178       g->delme = 1;
04179       e = g->endpoints;
04180       while (e) {
04181          e->delme = 1;
04182          e = e->next;
04183       }
04184       g = g->next;
04185    }
04186    ast_mutex_unlock(&gatelock);
04187    
04188    cat = ast_category_browse(cfg, NULL);
04189    while(cat) {
04190       if (strcasecmp(cat, "general")) {
04191          ast_mutex_lock(&gatelock);
04192          g = build_gateway(cat, ast_variable_browse(cfg, cat));
04193          if (g) {
04194             ast_verb(3, "Added gateway '%s'\n", g->name);
04195             g->next = gateways;
04196             gateways = g;
04197          }
04198          ast_mutex_unlock(&gatelock);
04199 
04200          /* FS: process queue and IO */
04201          if (monitor_thread == pthread_self()) {
04202             if (sched) ast_sched_runq(sched);
04203             if (io) ast_io_wait(io, 10);
04204          }
04205       }
04206       cat = ast_category_browse(cfg, cat);
04207    }
04208 
04209       /* prune deleted entries etc. */
04210       prune_gateways();
04211 
04212    if (ntohl(bindaddr.sin_addr.s_addr)) {
04213       memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04214    } else {
04215       hp = ast_gethostbyname(ourhost, &ahp);
04216       if (!hp) {
04217          ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04218          ast_config_destroy(cfg);
04219          return 0;
04220       }
04221       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04222    }
04223    if (!ntohs(bindaddr.sin_port))
04224       bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04225    bindaddr.sin_family = AF_INET;
04226    ast_mutex_lock(&netlock);
04227    if (mgcpsock > -1)
04228       close(mgcpsock);
04229 
04230    if (mgcpsock_read_id != NULL)
04231       ast_io_remove(io, mgcpsock_read_id);
04232    mgcpsock_read_id = NULL;
04233 
04234    mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04235    if (mgcpsock < 0) {
04236       ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04237    } else {
04238       if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04239          ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04240             ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04241                strerror(errno));
04242          close(mgcpsock);
04243          mgcpsock = -1;
04244       } else {
04245          ast_verb(2, "MGCP Listening on %s:%d\n",
04246                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04247          ast_netsock_set_qos(mgcpsock, tos, cos, "MGCP");
04248       }
04249    }
04250    ast_mutex_unlock(&netlock);
04251    ast_config_destroy(cfg);
04252 
04253    /* send audit only to the new endpoints */
04254    g = gateways;
04255    while (g) {
04256       e = g->endpoints;
04257       while (e && e->needaudit) {
04258          e->needaudit = 0;
04259          transmit_audit_endpoint(e);
04260          ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04261          e = e->next;
04262       }
04263       g = g->next;
04264    }
04265 
04266    return 0;
04267 }

static int reqprep ( struct mgcp_request req,
struct mgcp_endpoint p,
char *  verb 
) [static]

Definition at line 2037 of file chan_mgcp.c.

References init_req(), and oseq.

Referenced by transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), and transmit_state_notify().

02038 {
02039    memset(req, 0, sizeof(struct mgcp_request));
02040    oseq++;
02041    if (oseq > 999999999)
02042       oseq = 1;
02043    init_req(p, req, verb);
02044    return 0;
02045 }

static int resend_response ( struct mgcp_subchannel sub,
struct mgcp_response resp 
) [static]

Definition at line 524 of file chan_mgcp.c.

References __mgcp_xmit(), mgcp_gateway::addr, ast_inet_ntoa(), ast_verbose(), mgcp_response::buf, mgcp_response::len, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by find_and_retrans().

00525 {
00526    struct mgcp_endpoint *p = sub->parent;
00527    int res;
00528    if (mgcpdebug) {
00529       ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00530    }
00531    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00532    if (res > 0)
00533       res = 0;
00534    return res;
00535 }

static int respprep ( struct mgcp_request resp,
struct mgcp_endpoint p,
char *  msg,
struct mgcp_request req,
char *  msgrest 
) [static]

Definition at line 2030 of file chan_mgcp.c.

References init_resp().

Referenced by __transmit_response(), transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().

02031 {
02032    memset(resp, 0, sizeof(*resp));
02033    init_resp(resp, msg, req, msgrest);
02034    return 0;
02035 }

static int restart_monitor ( void   )  [static]

Definition at line 3491 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, and monlock.

03492 {
03493    /* If we're supposed to be stopped -- stay stopped */
03494    if (monitor_thread == AST_PTHREADT_STOP)
03495       return 0;
03496    if (ast_mutex_lock(&monlock)) {
03497       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03498       return -1;
03499    }
03500    if (monitor_thread == pthread_self()) {
03501       ast_mutex_unlock(&monlock);
03502       ast_log(LOG_WARNING, "Cannot kill myself\n");
03503       return -1;
03504    }
03505    if (monitor_thread != AST_PTHREADT_NULL) {
03506       /* Wake up the thread */
03507       pthread_kill(monitor_thread, SIGURG);
03508    } else {
03509       /* Start a new monitor */
03510       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03511          ast_mutex_unlock(&monlock);
03512          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03513          return -1;
03514       }
03515    }
03516    ast_mutex_unlock(&monlock);
03517    return 0;
03518 }

static int retrans_pkt ( const void *  data  )  [static]

Definition at line 627 of file chan_mgcp.c.

References __mgcp_xmit(), ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), handle_response(), LOG_WARNING, MAX_RETRANS, mgcpdebug, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::retrans, and mgcp_gateway::retransid.

Referenced by __sip_reliable_xmit(), and mgcp_postrequest().

00628 {
00629    struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00630    struct mgcp_message *cur, *exq = NULL, *w, *prev;
00631    int res = 0;
00632 
00633    /* find out expired msgs */
00634    ast_mutex_lock(&gw->msgs_lock);
00635 
00636    prev = NULL, cur = gw->msgs;
00637    while (cur) {
00638       if (cur->retrans < MAX_RETRANS) {
00639          cur->retrans++;
00640          if (mgcpdebug) {
00641             ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00642                cur->retrans, cur->seqno, gw->name);
00643          }
00644          __mgcp_xmit(gw, cur->buf, cur->len);
00645 
00646          prev = cur;
00647          cur = cur->next;
00648       } else {
00649          if (prev)
00650             prev->next = cur->next;
00651          else
00652             gw->msgs = cur->next;
00653 
00654          ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00655             cur->seqno, gw->name);
00656 
00657          w = cur;
00658          cur = cur->next;
00659 
00660          if (exq) {
00661             w->next = exq;
00662          } else {
00663             w->next = NULL;
00664          }
00665          exq = w;
00666       }
00667    }
00668 
00669    if (!gw->msgs) {
00670       gw->retransid = -1;
00671       res = 0;
00672    } else {
00673       res = 1;
00674    }
00675    ast_mutex_unlock(&gw->msgs_lock);
00676 
00677    while (exq) {
00678       cur = exq;
00679       /* time-out transaction */
00680       handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
00681       exq = exq->next;
00682       ast_free(cur);
00683    }
00684 
00685    return res;
00686 }

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1584 of file chan_mgcp.c.

Referenced by process_sdp().

01585 {
01586    *iterator = 0;
01587 }

static int send_request ( struct mgcp_endpoint p,
struct mgcp_subchannel sub,
struct mgcp_request req,
unsigned int  seqno 
) [static]

Definition at line 754 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::data, mgcp_request::len, LOG_WARNING, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcpdebug, mgcp_request::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.

Referenced by transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_sip_request(), and transmit_state_notify().

00756 {
00757    int res = 0;
00758    struct mgcp_request **queue, *q, *r, *t;
00759    ast_mutex_t *l;
00760 
00761    ast_debug(1, "Slow sequence is %d\n", p->slowsequence);
00762    if (p->slowsequence) {
00763       queue = &p->cmd_queue;
00764       l = &p->cmd_queue_lock;
00765       ast_mutex_lock(l);
00766    } else {
00767       switch (req->cmd) {
00768       case MGCP_CMD_DLCX:
00769          queue = &sub->cx_queue;
00770          l = &sub->cx_queue_lock;
00771          ast_mutex_lock(l);
00772          q = sub->cx_queue;
00773          /* delete pending cx cmds */
00774          while (q) {
00775             r = q->next;
00776             ast_free(q);
00777             q = r;
00778          }
00779          *queue = NULL;
00780          break;
00781 
00782       case MGCP_CMD_CRCX:
00783       case MGCP_CMD_MDCX:
00784          queue = &sub->cx_queue;
00785          l = &sub->cx_queue_lock;
00786          ast_mutex_lock(l);
00787          break;
00788 
00789       case MGCP_CMD_RQNT:
00790          queue = &p->rqnt_queue;
00791          l = &p->rqnt_queue_lock;
00792          ast_mutex_lock(l);
00793          break;
00794 
00795       default:
00796          queue = &p->cmd_queue;
00797          l = &p->cmd_queue_lock;
00798          ast_mutex_lock(l);
00799          break;
00800       }
00801    }
00802 
00803    r = ast_malloc(sizeof(*r));
00804    if (!r) {
00805       ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00806       ast_mutex_unlock(l);
00807       return -1;
00808    }
00809    memcpy(r, req, sizeof(*r));
00810 
00811    if (!(*queue)) {
00812       if (mgcpdebug) {
00813          ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
00814             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00815       }
00816 
00817       res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00818    } else {
00819       if (mgcpdebug) {
00820          ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
00821             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00822       }
00823    }
00824 
00825    /* XXX find tail. We could also keep tail in the data struct for faster access */
00826    for (t = *queue; t && t->next; t = t->next);
00827 
00828    r->next = NULL;
00829    if (t)
00830       t->next = r;
00831    else
00832       *queue = r;
00833 
00834    ast_mutex_unlock(l);
00835 
00836    return res;
00837 }

static int send_response ( struct mgcp_subchannel sub,
struct mgcp_request req 
) [static]

Definition at line 537 of file chan_mgcp.c.

References __mgcp_xmit(), mgcp_gateway::addr, ast_inet_ntoa(), ast_verbose(), mgcp_request::data, mgcp_request::len, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by __transmit_response(), transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().

00538 {
00539    struct mgcp_endpoint *p = sub->parent;
00540    int res;
00541    if (mgcpdebug) {
00542       ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00543    }
00544    res = __mgcp_xmit(p->parent, req->data, req->len);
00545    if (res > 0)
00546       res = 0;
00547    return res;
00548 }

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2632 of file chan_mgcp.c.

References ast_channel_set_fd(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_destroy(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_callback(), ast_rtp_set_data(), ast_rtp_setnat(), ast_rtp_setqos(), bindaddr, mgcp_subchannel::callid, cos_audio, io, mgcp_subchannel::lock, mgcp_subchannel::nat, mgcp_subchannel::owner, mgcp_subchannel::rtp, tos_audio, transmit_connect_with_sdp(), and mgcp_subchannel::txident.

Referenced by handle_hd_hf(), handle_offhook_message(), handle_response(), handle_soft_key_event_message(), handle_stimulus_message(), HandleCallIncoming(), HandleCallOutgoing(), mgcp_answer(), mgcp_call(), mgcp_ss(), skinny_answer(), skinny_newcall(), and unistim_answer().

02633 {
02634    ast_mutex_lock(&sub->lock);
02635    /* check again to be on the safe side */
02636    if (sub->rtp) {
02637       ast_rtp_destroy(sub->rtp);
02638       sub->rtp = NULL;
02639    }
02640    /* Allocate the RTP now */
02641    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02642    if (sub->rtp && sub->owner)
02643       ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
02644    if (sub->rtp) {
02645       ast_rtp_setqos(sub->rtp, tos_audio, cos_audio, "MGCP RTP");
02646       ast_rtp_setnat(sub->rtp, sub->nat);
02647    }
02648 #if 0
02649    ast_rtp_set_callback(p->rtp, rtpready);
02650    ast_rtp_set_data(p->rtp, p);
02651 #endif      
02652    /* Make a call*ID */
02653         snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02654    /* Transmit the connection create */
02655    transmit_connect_with_sdp(sub, NULL);
02656    ast_mutex_unlock(&sub->lock);
02657 }

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

Definition at line 2351 of file chan_mgcp.c.

References add_header(), mgcp_request::cmd, MGCP_CMD_AUEP, oseq, reqprep(), send_request(), and mgcp_request::trid.

Referenced by handle_mgcp_audit_endpoint(), handle_request(), and reload_config().

02352 {
02353    struct mgcp_request resp;
02354    reqprep(&resp, p, "AUEP");
02355    /* removed unknown param VS */
02356    /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
02357    add_header(&resp, "F", "A");
02358    /* fill in new fields */
02359    resp.cmd = MGCP_CMD_AUEP;
02360    resp.trid = oseq;
02361    return send_request(p, NULL, &resp, oseq);  /* SC */
02362 }

static int transmit_connect_with_sdp ( struct mgcp_subchannel sub,
struct ast_rtp rtp 
) [static]

Definition at line 2198 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype(), mgcp_endpoint::capability, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by start_rtp().

02199 {
02200    struct mgcp_request resp;
02201    char local[256];
02202    char tmp[80];
02203    int x;
02204    struct mgcp_endpoint *p = sub->parent;
02205 
02206    ast_copy_string(local, "p:20", sizeof(local));
02207    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02208       if (p->capability & x) {
02209          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02210          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02211       }
02212    }
02213    if (mgcpdebug) {
02214       ast_verb(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02215          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02216    }
02217    reqprep(&resp, p, "CRCX");
02218    add_header(&resp, "C", sub->callid);
02219    add_header(&resp, "L", local);
02220    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02221    /* X header should not be sent. kept for compatibility */
02222    add_header(&resp, "X", sub->txident);
02223    /*add_header(&resp, "S", "");*/
02224    add_sdp(&resp, sub, rtp);
02225    /* fill in new fields */
02226    resp.cmd = MGCP_CMD_CRCX;
02227    resp.trid = oseq;
02228    return send_request(p, sub, &resp, oseq);  /* SC */
02229 }

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

Definition at line 2364 of file chan_mgcp.c.

References add_header(), ast_verb, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_DLCX, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_endpoint::sub, mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by destroy_endpoint(), handle_request(), handle_response(), mgcp_hangup(), and unalloc_sub().

02365 {
02366    struct mgcp_endpoint *p = sub->parent;
02367    struct mgcp_request resp;
02368 
02369    if (mgcpdebug) {
02370       ast_verb(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02371          sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02372    }
02373    reqprep(&resp, p, "DLCX");
02374    /* check if call id is avail */
02375    if (sub->callid[0])
02376       add_header(&resp, "C", sub->callid);
02377    /* X header should not be sent. kept for compatibility */
02378    add_header(&resp, "X", sub->txident);
02379    /* check if cxident is avail */
02380    if (sub->cxident[0])
02381       add_header(&resp, "I", sub->cxident);
02382    /* fill in new fields */
02383    resp.cmd = MGCP_CMD_DLCX;
02384    resp.trid = oseq;
02385    return send_request(p, sub, &resp, oseq);  /* SC */
02386 }

static int transmit_connection_del_w_params ( struct mgcp_endpoint p,
char *  callid,
char *  cxident 
) [static]

Definition at line 2388 of file chan_mgcp.c.

References add_header(), ast_verb, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, reqprep(), send_request(), and mgcp_endpoint::sub.

Referenced by handle_response().

02389 {
02390    struct mgcp_request resp;
02391 
02392    if (mgcpdebug) {
02393       ast_verb(3, "Delete connection %s %s@%s on callid: %s\n",
02394          cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02395    }
02396    reqprep(&resp, p, "DLCX");
02397    /* check if call id is avail */
02398    if (callid && *callid)
02399       add_header(&resp, "C", callid);
02400    /* check if cxident is avail */
02401    if (cxident && *cxident)
02402       add_header(&resp, "I", cxident);
02403    /* fill in new fields */
02404    resp.cmd = MGCP_CMD_DLCX;
02405    resp.trid = oseq;
02406    return send_request(p, p->sub, &resp, oseq);
02407 }

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2306 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_endpoint::sub, mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), mgcp_call(), and mgcp_hangup().

02307 {
02308    struct mgcp_request resp;
02309    struct mgcp_endpoint *p = sub->parent;
02310 
02311    if (ast_strlen_zero(sub->cxident)) {
02312       /* We don't have a CXident yet, store the destination and
02313          wait a bit */
02314       return 0;
02315    }
02316    if (mgcpdebug) {
02317       ast_verb(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02318          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02319    }
02320    reqprep(&resp, p, "MDCX");
02321    add_header(&resp, "C", sub->callid);
02322    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02323    /* X header should not be sent. kept for compatibility */
02324    add_header(&resp, "X", sub->txident);
02325    add_header(&resp, "I", sub->cxident);
02326    switch (sub->parent->hookstate) {
02327    case MGCP_ONHOOK:
02328       add_header(&resp, "R", "L/hd(N)");
02329       break;
02330    case MGCP_OFFHOOK:
02331       add_header_offhook(sub, &resp);
02332       break;
02333    }
02334    /* fill in new fields */
02335    resp.cmd = MGCP_CMD_MDCX;
02336    resp.trid = oseq;
02337    return send_request(p, sub, &resp, oseq); /* SC */
02338 }

static int transmit_modify_with_sdp ( struct mgcp_subchannel sub,
struct ast_rtp rtp,
int  codecs 
) [static]

Definition at line 2162 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_get_peer(), ast_rtp_lookup_mime_subtype(), ast_strlen_zero(), mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::parent, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.

Referenced by handle_response(), and mgcp_set_rtp_peer().

02163 {
02164    struct mgcp_request resp;
02165    char local[256];
02166    char tmp[80];
02167    int x;
02168    struct mgcp_endpoint *p = sub->parent;
02169 
02170    if (ast_strlen_zero(sub->cxident) && rtp) {
02171       /* We don't have a CXident yet, store the destination and
02172          wait a bit */
02173       ast_rtp_get_peer(rtp, &sub->tmpdest);
02174       return 0;
02175    }
02176    ast_copy_string(local, "p:20", sizeof(local));
02177    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02178       if (p->capability & x) {
02179          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02180          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02181       }
02182    }
02183    reqprep(&resp, p, "MDCX");
02184    add_header(&resp, "C", sub->callid);
02185    add_header(&resp, "L", local);
02186    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02187    /* X header should not be sent. kept for compatibility */
02188    add_header(&resp, "X", sub->txident);
02189    add_header(&resp, "I", sub->cxident);
02190    /*add_header(&resp, "S", "");*/
02191    add_sdp(&resp, sub, rtp);
02192    /* fill in new fields */
02193    resp.cmd = MGCP_CMD_MDCX;
02194    resp.trid = oseq;
02195    return send_request(p, sub, &resp, oseq); /* SC */
02196 }

static int transmit_notify_request ( struct mgcp_subchannel sub,
char *  tone 
) [static]

Definition at line 2231 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), mgcp_endpoint::sub, and mgcp_request::trid.

Referenced by do_monitor(), handle_hd_hf(), handle_request(), handle_response(), mgcp_answer(), mgcp_hangup(), mgcp_indicate(), mgcp_request(), mgcp_senddigit_end(), and mgcp_ss().

02232 {
02233    struct mgcp_request resp;
02234    struct mgcp_endpoint *p = sub->parent;
02235 
02236    if (mgcpdebug) {
02237       ast_verb(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
02238          tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02239    }
02240    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02241    reqprep(&resp, p, "RQNT");
02242    add_header(&resp, "X", p->rqnt_ident); /* SC */
02243    switch (p->hookstate) {
02244    case MGCP_ONHOOK:
02245       add_header(&resp, "R", "L/hd(N)");
02246       break;
02247    case MGCP_OFFHOOK:
02248       add_header_offhook(sub, &resp);
02249       break;
02250    }
02251    if (!ast_strlen_zero(tone)) {
02252       add_header(&resp, "S", tone);
02253    }
02254    /* fill in new fields */
02255    resp.cmd = MGCP_CMD_RQNT;
02256    resp.trid = oseq;
02257    return send_request(p, NULL, &resp, oseq); /* SC */
02258 }

static int transmit_notify_request_with_callerid ( struct mgcp_subchannel sub,
char *  tone,
char *  callernum,
char *  callername 
) [static]

Definition at line 2260 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_verb, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::lastcallerid, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), mgcp_endpoint::sub, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and mgcp_request::trid.

Referenced by mgcp_call(), and mgcp_hangup().

02261 {
02262    struct mgcp_request resp;
02263    char tone2[256];
02264    char *l, *n;
02265    struct timeval t = ast_tvnow();
02266    struct ast_tm tm;
02267    struct mgcp_endpoint *p = sub->parent;
02268    
02269    ast_localtime(&t, &tm, NULL);
02270    n = callername;
02271    l = callernum;
02272    if (!n)
02273       n = "";
02274    if (!l)
02275       l = "";
02276 
02277    /* Keep track of last callerid for blacklist and callreturn */
02278    ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02279 
02280    snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
02281       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02282    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02283    reqprep(&resp, p, "RQNT");
02284    add_header(&resp, "X", p->rqnt_ident); /* SC */
02285    switch (p->hookstate) {
02286    case MGCP_ONHOOK:
02287       add_header(&resp, "R", "L/hd(N)");
02288       break;
02289    case MGCP_OFFHOOK:
02290       add_header_offhook(sub, &resp);
02291       break;
02292    }
02293    if (!ast_strlen_zero(tone2)) {
02294       add_header(&resp, "S", tone2);
02295    }
02296    if (mgcpdebug) {
02297       ast_verb(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
02298          tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02299    }
02300    /* fill in new fields */
02301    resp.cmd = MGCP_CMD_RQNT;
02302    resp.trid = oseq;
02303    return send_request(p, NULL, &resp, oseq);  /* SC */
02304 }

static int transmit_response ( struct mgcp_subchannel sub,
char *  msg,
struct mgcp_request req,
char *  msgrest 
) [static]

Definition at line 2047 of file chan_mgcp.c.

References ast_calloc, mgcp_request::data, mgcp_request::identifier, mgcp_request::len, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_gateway::responses, respprep(), send_response(), and mgcp_endpoint::sub.

Referenced by handle_incoming(), handle_invite_replaces(), handle_keep_alive_message(), handle_line_state_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_request(), handle_request_bye(), handle_request_cancel(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), handle_server_request_message(), handle_skinny_reset(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), handle_version_req_message(), local_attended_transfer(), receive_message(), register_verify(), sip_indicate(), sip_park_thread(), sip_sendhtml(), skinny_hold(), skinny_set_rtp_peer(), skinny_unhold(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

02048 {
02049    struct mgcp_request resp;
02050    struct mgcp_endpoint *p = sub->parent;
02051    struct mgcp_response *mgr;
02052 
02053    respprep(&resp, p, msg, req, msgrest);
02054    mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1);
02055    if (mgr) {
02056       /* Store MGCP response in case we have to retransmit */
02057       sscanf(req->identifier, "%d", &mgr->seqno);
02058       time(&mgr->whensent);
02059       mgr->len = resp.len;
02060       memcpy(mgr->buf, resp.data, resp.len);
02061       mgr->buf[resp.len] = '\0';
02062       mgr->next = p->parent->responses;
02063       p->parent->responses = mgr;
02064    }
02065    return send_response(sub, &resp);
02066 }

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

Definition at line 483 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_WARNING, MGCP_CX_INACTIVE, mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_subchannel::tmpdest, and transmit_connection_del().

00484 {
00485    struct mgcp_endpoint *p = sub->parent;
00486    if (p->sub == sub) {
00487       ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00488       return -1;
00489    }
00490    ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00491 
00492    sub->owner = NULL;
00493    if (!ast_strlen_zero(sub->cxident)) {
00494       transmit_connection_del(sub);
00495    }
00496    sub->cxident[0] = '\0';
00497    sub->callid[0] = '\0';
00498    sub->cxmode = MGCP_CX_INACTIVE;
00499    sub->outgoing = 0;
00500    sub->alreadygone = 0;
00501    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00502    if (sub->rtp) {
00503       ast_rtp_destroy(sub->rtp);
00504       sub->rtp = NULL;
00505    }
00506    dump_cmd_queues(NULL, sub); /* SC */
00507    return 0;
00508 }

static int unload_module ( void   )  [static]

Definition at line 4341 of file chan_mgcp.c.

References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), cli_mgcp, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, LOG_WARNING, mgcp_reload(), mgcp_reload_lock, mgcp_reloading, mgcp_rtp, mgcp_tech, mgcpsock, monitor_thread, monlock, mgcp_endpoint::next, mgcp_gateway::next, prune_gateways(), and sched_context_destroy().

04342 {
04343    struct mgcp_endpoint *e;
04344    struct mgcp_gateway *g;
04345 
04346    /* Check to see if we're reloading */
04347    if (ast_mutex_trylock(&mgcp_reload_lock)) {
04348       ast_log(LOG_WARNING, "MGCP is currently reloading.  Unable to remove module.\n");
04349       return -1;
04350    } else {
04351       mgcp_reloading = 1;
04352       ast_mutex_unlock(&mgcp_reload_lock);
04353    }
04354 
04355    /* First, take us out of the channel loop */
04356    ast_channel_unregister(&mgcp_tech);
04357 
04358    /* Shut down the monitoring thread */
04359    if (!ast_mutex_lock(&monlock)) {
04360       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04361          pthread_cancel(monitor_thread);
04362          pthread_kill(monitor_thread, SIGURG);
04363          pthread_join(monitor_thread, NULL);
04364       }
04365       monitor_thread = AST_PTHREADT_STOP;
04366       ast_mutex_unlock(&monlock);
04367    } else {
04368       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04369       /* We always want to leave this in a consistent state */
04370       ast_channel_register(&mgcp_tech);
04371       mgcp_reloading = 0;
04372       mgcp_reload(NULL, 0, NULL);
04373       return -1;
04374    }
04375 
04376    if (!ast_mutex_lock(&gatelock)) {
04377       for (g = gateways; g; g = g->next) {
04378          g->delme = 1;
04379          for (e = g->endpoints; e; e = e->next)
04380             e->delme = 1;
04381       }
04382 
04383       prune_gateways();
04384       ast_mutex_unlock(&gatelock);
04385    } else {
04386       ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04387       /* We always want to leave this in a consistent state */
04388       ast_channel_register(&mgcp_tech);
04389       /* Allow the monitor to restart */
04390       monitor_thread = AST_PTHREADT_NULL;
04391       mgcp_reloading = 0;
04392       mgcp_reload(NULL, 0, NULL);
04393       return -1;
04394    }
04395 
04396    close(mgcpsock);
04397    ast_rtp_proto_unregister(&mgcp_rtp);
04398    ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04399    sched_context_destroy(sched);
04400 
04401    return 0;
04402 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 4408 of file chan_mgcp.c.

struct in_addr __ourip [static]

Definition at line 214 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 179 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 185 of file chan_mgcp.c.

int amaflags = 0 [static]

Definition at line 183 of file chan_mgcp.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4408 of file chan_mgcp.c.

struct sockaddr_in bindaddr [static]

Definition at line 400 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 164 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int callwaiting = 0 [static]

Definition at line 162 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int cancallforward = 0 [static]

Definition at line 173 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int canreinvite = CANREINVITE [static]

Definition at line 177 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int capability = AST_FORMAT_ULAW [static]

Definition at line 210 of file chan_mgcp.c.

Referenced by build_gateway(), build_setup(), iax2_call(), mgcp_new(), mgcp_request(), parse_setup(), process_sdp(), reload_config(), set_config(), and set_local_capabilities().

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 147 of file chan_mgcp.c.

Referenced by __oh323_new(), build_device(), build_gateway(), build_peer(), build_user(), check_access(), dahdi_handle_event(), dial_trunk(), misdn_new(), set_pvt_defaults(), sla_ring_station(), and store_callerid().

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 146 of file chan_mgcp.c.

Referenced by __oh323_new(), build_device(), build_gateway(), build_peer(), build_user(), check_access(), dahdi_handle_event(), dial_trunk(), misdn_new(), set_pvt_defaults(), sla_ring_station(), socket_process(), and store_callerid().

struct ast_cli_entry cli_mgcp[] [static]

Definition at line 1192 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_mgcp_set_debug_deprecated = { .handler = handle_mgcp_set_debug_deprecated , .summary = "Enable/Disable MGCP debugging" ,__VA_ARGS__ } [static]

Definition at line 1191 of file chan_mgcp.c.

const char config[] = "mgcp.conf" [static]

Definition at line 100 of file chan_mgcp.c.

char context[AST_MAX_EXTENSION] = "default" [static]

Definition at line 142 of file chan_mgcp.c.

unsigned int cos = 0 [static]

Definition at line 157 of file chan_mgcp.c.

unsigned int cos_audio = 0 [static]

Definition at line 158 of file chan_mgcp.c.

Referenced by reload_config(), and start_rtp().

ast_group_t cur_callergroup = 0 [static]

Definition at line 152 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 153 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 90 of file chan_mgcp.c.

int dtmfmode = 0 [static]

Definition at line 149 of file chan_mgcp.c.

Referenced by build_gateway(), reload_config(), and set_local_capabilities().

int firstdigittimeout = 16000 [static]

Wait up to 16 seconds for first digit (FXO logic)

Definition at line 190 of file chan_mgcp.c.

ast_mutex_t gatelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

gatelock: mutex for gateway/endpoint lists

Definition at line 396 of file chan_mgcp.c.

Referenced by find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), reload_config(), and unload_module().

struct mgcp_gateway * gateways [static]

Referenced by build_gateway(), do_monitor(), find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), reload_config(), and unload_module().

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic)

Definition at line 193 of file chan_mgcp.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 97 of file chan_mgcp.c.

int immediate = 0 [static]

Definition at line 160 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

struct io_context* io [static]

Definition at line 220 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 144 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 181 of file chan_mgcp.c.

Referenced by action_mailboxcount(), action_mailboxstatus(), add_peer_mailboxes(), add_peer_mwi_subs(), append_mailbox_mapping(), build_device(), build_gateway(), build_peer(), clear_peer_mailboxes(), destroy_mailbox(), disa_exec(), get_cached_mwi(), has_voicemail(), notify_message(), peer_mailboxes_to_str(), realtime_directory(), unistim_send_mwi_to_peer(), and update_registry().

int matchdigittimeout = 3000 [static]

How long to wait for an extra digit, if there is an ambiguous match

Definition at line 196 of file chan_mgcp.c.

char* mgcp_cxmodes[] [static]

}

Definition at line 122 of file chan_mgcp.c.

Referenced by transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

ast_mutex_t mgcp_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 392 of file chan_mgcp.c.

Referenced by do_monitor(), mgcp_reload(), and unload_module().

int mgcp_reloading = 0 [static]

Definition at line 393 of file chan_mgcp.c.

Referenced by do_monitor(), mgcp_reload(), and unload_module().

struct ast_rtp_protocol mgcp_rtp [static]

Initial value:

 {
   .type = "MGCP",
   .get_rtp_info = mgcp_get_rtp_peer,
   .set_rtp_peer = mgcp_set_rtp_peer,
}

Definition at line 3989 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 430 of file chan_mgcp.c.

Referenced by load_module(), mgcp_new(), and unload_module().

int mgcpdebug = 0 [static]

Definition at line 217 of file chan_mgcp.c.

Referenced by add_sdp(), handle_mgcp_audit_endpoint(), handle_mgcp_set_debug(), handle_mgcp_set_debug_deprecated(), mgcp_call(), mgcp_hangup(), mgcp_indicate(), parse(), process_sdp(), retrans_pkt(), and send_request().

int mgcpsock = -1 [static]

Definition at line 398 of file chan_mgcp.c.

Referenced by do_monitor(), mgcpsock_read(), reload_config(), and unload_module().

int* mgcpsock_read_id = NULL [static]

Definition at line 3403 of file chan_mgcp.c.

Referenced by reload_config().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 206 of file chan_mgcp.c.

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 202 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

Definition at line 145 of file chan_mgcp.c.

Referenced by ast_do_masquerade(), begin_dial_channel(), build_gateway(), dial_exec_full(), func_channel_write(), gtalk_new(), jingle_new(), local_call(), monitor_dial(), and set_moh_exec().

int nat = 0 [static]

Definition at line 150 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

Definition at line 200 of file chan_mgcp.c.

Referenced by do_monitor(), handle_request_do(), reload_config(), and unload_module().

int nonCodecCapability = AST_RTP_DTMF [static]

Definition at line 211 of file chan_mgcp.c.

Referenced by process_sdp().

unsigned int oseq [static]

Definition at line 187 of file chan_mgcp.c.

Referenced by init_req(), reqprep(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

char ourhost[MAXHOSTNAMELEN] [static]

Definition at line 213 of file chan_mgcp.c.

Referenced by ast_find_ourip(), handle_server_request_message(), and reload_config().

int ourport [static]

Definition at line 215 of file chan_mgcp.c.

Referenced by build_contact(), handle_server_request_message(), initreqprep(), reload_config(), and transmit_notify_with_mwi().

struct sched_context* sched [static]

Definition at line 219 of file chan_mgcp.c.

int singlepath = 0 [static]

Definition at line 175 of file chan_mgcp.c.

Referenced by build_gateway().

int slowsequence = 0 [static]

Definition at line 166 of file chan_mgcp.c.

Referenced by build_gateway().

const char tdesc[] = "Media Gateway Control Protocol (MGCP)" [static]

Definition at line 99 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 168 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

unsigned int tos = 0 [static]

Definition at line 155 of file chan_mgcp.c.

unsigned int tos_audio = 0 [static]

Definition at line 156 of file chan_mgcp.c.

Referenced by reload_config(), and start_rtp().

int transfer = 0 [static]

This is for flashhook transfers

Definition at line 171 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().


Generated on Thu Jul 9 13:41:01 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7