Sat Aug 6 00:39:46 2011

Asterisk developer's documentation


chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.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/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.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 IPTOS_MINCOST   0x02
#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 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_audit_endpoint (int fd, int argc, char *argv[])
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_do_debug (int fd, int argc, char *argv[])
static int mgcp_do_reload (void)
 mgcp_do_reload: Reload module
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_no_debug (int fd, int argc, char *argv[])
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 int mgcp_reload (int fd, int argc, char *argv[])
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, int codecs, int nat_active)
static int mgcp_show_endpoints (int fd, int argc, char *argv[])
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 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 (void)
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 | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 char audit_endpoint_usage []
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 const char config [] = "mgcp.conf"
static char context [AST_MAX_EXTENSION] = "default"
static ast_group_t cur_callergroup = 0
static ast_group_t cur_pickupgroup = 0
static char debug_usage []
static struct ast_jb_conf default_jbconf
static int dtmfmode = 0
static int firstdigittimeout = 16000
static ast_mutex_t gatelock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 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_MUTEX_INITIALIZER )
static char mgcp_reload_usage []
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_MUTEX_INITIALIZER )
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char no_debug_usage []
static int nonCodecCapability = AST_RTP_DTMF
static unsigned int oseq
static char ourhost [MAXHOSTNAMELEN]
static int ourport
static struct sched_contextsched
static char show_endpoints_usage []
static int singlepath = 0
static int slowsequence = 0
static const char tdesc [] = "Media Gateway Control Protocol (MGCP)"
static int threewaycalling = 0
static int tos = 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 96 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_EXPIRY   120

Definition at line 94 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 120 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 119 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 122 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 99 of file chan_mgcp.c.

Referenced by build_gateway().

#define IPTOS_MINCOST   0x02

Definition at line 84 of file chan_mgcp.c.

#define MAX_EXPIRY   3600

Definition at line 95 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 123 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 275 of file chan_mgcp.c.

Referenced by build_gateway(), and destroy_endpoint().

#define MGCP_CX_CONF   3

Definition at line 129 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 130 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 132 of file chan_mgcp.c.

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

#define MGCP_CX_MUTE   4

Definition at line 131 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

Definition at line 127 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 126 of file chan_mgcp.c.

#define MGCP_CX_SENDRECV   2

Definition at line 128 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 117 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 116 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 115 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 234 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

Definition at line 235 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 121 of file chan_mgcp.c.

#define MGCP_OFFHOOK   2

Definition at line 309 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 308 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 286 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 93 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 265 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 278 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 277 of file chan_mgcp.c.

#define TYPE_LINE   2

Definition at line 312 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 311 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 143 of file chan_mgcp.c.

00143      {
00144    MGCP_CMD_EPCF,
00145    MGCP_CMD_CRCX,
00146    MGCP_CMD_MDCX,
00147    MGCP_CMD_DLCX,
00148    MGCP_CMD_RQNT,
00149    MGCP_CMD_NTFY,
00150    MGCP_CMD_AUEP,
00151    MGCP_CMD_AUCX,
00152    MGCP_CMD_RSIP
00153 };


Function Documentation

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

Definition at line 1572 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(), handle_request(), handle_request_subscribe(), handle_response_register(), and parse_register_contact().

01573 {
01574    int x;
01575    int len = strlen(name);
01576    char *r;
01577    for (x=*start;x<req->headers;x++) {
01578       if (!strncasecmp(req->header[x], name, len) && 
01579           (req->header[x][len] == ':')) {
01580          r = req->header[x] + len + 1;
01581          while(*r && (*r < 33))
01582             r++;
01583          *start = x+1;
01584          return r;
01585       }
01586    }
01587    /* Don't return NULL, so get_header is always a valid pointer */
01588    return "";
01589 }

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

Definition at line 491 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().

00492 {
00493    int res;
00494    if (gw->addr.sin_addr.s_addr)
00495       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00496    else 
00497       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00498    if (res != len) {
00499       ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00500    }
00501    return res;
00502 }

static void __reg_module ( void   )  [static]

Definition at line 4433 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

Definition at line 4433 of file chan_mgcp.c.

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

Definition at line 1922 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_offhook(), add_route(), add_sdp(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), finalize_content(), 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_reinvite_with_t38_sdp(), transmit_request_with_auth(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_unsupported(), and transmit_state_notify().

01923 {
01924    if (req->len >= sizeof(req->data) - 4) {
01925       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01926       return -1;
01927    }
01928    if (req->lines) {
01929       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01930       return -1;
01931    }
01932    req->header[req->headers] = req->data + req->len;
01933    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01934    req->len += strlen(req->header[req->headers]);
01935    if (req->headers < MGCP_MAX_HEADERS)
01936       req->headers++;
01937    else {
01938       ast_log(LOG_WARNING, "Out of header space\n");
01939       return -1;
01940    }
01941    return 0;   
01942 }

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

Definition at line 2323 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().

02324 {
02325    struct mgcp_endpoint *p = sub->parent;
02326 
02327    if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
02328       add_header(resp, "R", "L/hu(N),L/hf(N)");
02329    else
02330       add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
02331 }

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

Definition at line 1944 of file chan_mgcp.c.

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

01945 {
01946    if (req->len >= sizeof(req->data) - 4) {
01947       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01948       return -1;
01949    }
01950    if (!req->lines) {
01951       /* Add extra empty return */
01952       snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
01953       req->len += strlen(req->data + req->len);
01954    }
01955    req->line[req->lines] = req->data + req->len;
01956    snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01957    req->len += strlen(req->line[req->lines]);
01958    if (req->lines < MGCP_MAX_LINES)
01959       req->lines++;
01960    else {
01961       ast_log(LOG_WARNING, "Out of line space\n");
01962       return -1;
01963    }
01964    return 0;   
01965 }

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

Definition at line 2046 of file chan_mgcp.c.

References AST_FORMAT_MAX_AUDIO, 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, t, and mgcp_subchannel::tmpdest.

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

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

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

Definition at line 2915 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_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verbose(), mgcp_subchannel::id, LOG_DEBUG, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, option_verbose, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, unalloc_sub(), and VERBOSE_PREFIX_3.

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

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 3612 of file chan_mgcp.c.

References __ourip, mgcp_endpoint::accountcode, accountcode, mgcp_gateway::addr, mgcp_endpoint::adsi, adsi, mgcp_endpoint::amaflags, amaflags, ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_strlen_zero(), ast_true(), ast_verbose(), 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::context, context, cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::dtmfmode, dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, free, gateways, mgcp_gateway::ha, 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, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, mailbox, malloc, MAX_SUBS, MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::msgs_lock, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, musicclass, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, nat, ast_variable::next, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_gateway::ourip, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::pickupgroup, mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, singlepath, mgcp_endpoint::slowsequence, slowsequence, mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, threewaycalling, mgcp_endpoint::transfer, transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, VERBOSE_PREFIX_3, and mgcp_gateway::wcardep.

Referenced by reload_config().

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

static char* control2str ( int  ind  )  [static]

Definition at line 1382 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(), and skinny_indicate().

01382                                   {
01383    switch (ind) {
01384    case AST_CONTROL_HANGUP:
01385       return "Other end has hungup";
01386    case AST_CONTROL_RING:
01387       return "Local ring";
01388    case AST_CONTROL_RINGING:
01389       return "Remote end is ringing";
01390    case AST_CONTROL_ANSWER:
01391       return "Remote end has answered";
01392    case AST_CONTROL_BUSY:
01393       return "Remote end is busy";
01394    case AST_CONTROL_TAKEOFFHOOK:
01395       return "Make it go off hook";
01396    case AST_CONTROL_OFFHOOK:
01397       return "Line is off hook";
01398    case AST_CONTROL_CONGESTION:
01399       return "Congestion (circuits busy)";
01400    case AST_CONTROL_FLASH:
01401       return "Flash hook";
01402    case AST_CONTROL_WINK:
01403       return "Wink";
01404    case AST_CONTROL_OPTION:
01405       return "Set a low-level option";
01406    case AST_CONTROL_RADIO_KEY:
01407       return "Key Radio";
01408    case AST_CONTROL_RADIO_UNKEY:
01409       return "Un-Key Radio";
01410    }
01411    return "UNKNOWN";
01412 }

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

Definition at line 4025 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().

04026 {
04027    struct mgcp_subchannel *sub = e->sub->next, *s;
04028    int i;
04029 
04030    for (i = 0; i < MAX_SUBS; i++) {
04031       ast_mutex_lock(&sub->lock);
04032       if (!ast_strlen_zero(sub->cxident)) {
04033          transmit_connection_del(sub);
04034       }
04035       if (sub->rtp) {
04036          ast_rtp_destroy(sub->rtp);
04037          sub->rtp = NULL;
04038       }
04039       memset(sub->magic, 0, sizeof(sub->magic));
04040       mgcp_queue_hangup(sub);
04041       dump_cmd_queues(NULL, sub);
04042       ast_mutex_unlock(&sub->lock);
04043       sub = sub->next;
04044    }
04045 
04046    if (e->dsp) {
04047       ast_dsp_free(e->dsp);
04048    }
04049 
04050    dump_queue(e->parent, e);
04051    dump_cmd_queues(e, NULL);
04052 
04053    sub = e->sub;
04054    for (i = 0; (i < MAX_SUBS) && sub; i++) {
04055       s = sub;
04056       sub = sub->next;
04057       ast_mutex_destroy(&s->lock);
04058       ast_mutex_destroy(&s->cx_queue_lock);
04059       free(s);
04060    }
04061    ast_mutex_destroy(&e->lock);
04062    ast_mutex_destroy(&e->rqnt_queue_lock);
04063    ast_mutex_destroy(&e->cmd_queue_lock);
04064    free(e);
04065 }

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4067 of file chan_mgcp.c.

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

04068 {
04069    if (g->ha)
04070       ast_free_ha(g->ha);
04071 
04072    dump_queue(g, NULL);
04073 
04074    free (g);
04075 }

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

Definition at line 3441 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_verbose(), mgcp_gateway::endpoints, gateways, has_voicemail(), io, mgcp_do_reload(), MGCP_ONHOOK, mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), monlock, netlock, option_verbose, transmit_notify_request(), TYPE_LINE, and VERBOSE_PREFIX_1.

03442 {
03443    int res;
03444    int reloading;
03445    /*struct mgcp_gateway *g;*/
03446    /*struct mgcp_endpoint *e;*/
03447    /*time_t thispass = 0, lastpass = 0;*/
03448 
03449    /* Add an I/O event to our UDP socket */
03450    if (mgcpsock > -1) 
03451       mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03452    
03453    /* This thread monitors all the frame relay interfaces which are not yet in use
03454       (and thus do not have a separate thread) indefinitely */
03455    /* From here on out, we die whenever asked */
03456    for(;;) {
03457       /* Check for a reload request */
03458       ast_mutex_lock(&mgcp_reload_lock);
03459       reloading = mgcp_reloading;
03460       mgcp_reloading = 0;
03461       ast_mutex_unlock(&mgcp_reload_lock);
03462       if (reloading) {
03463          if (option_verbose > 0)
03464             ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
03465          mgcp_do_reload();
03466          /* Add an I/O event to our UDP socket */
03467          if (mgcpsock > -1) 
03468             mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03469       }
03470 
03471       /* Check for interfaces needing to be killed */
03472       /* Don't let anybody kill us right away.  Nobody should lock the interface list
03473          and wait for the monitor list, but the other way around is okay. */
03474       ast_mutex_lock(&monlock);
03475       /* Lock the network interface */
03476       ast_mutex_lock(&netlock);
03477 
03478 #if 0
03479       /* XXX THIS IS COMPLETELY HOSED */
03480       /* The gateway goes into a state of panic */
03481       /* If the vmwi indicator is sent while it is reseting interfaces */
03482       lastpass = thispass;
03483       thispass = time(NULL);
03484       g = gateways;
03485       while(g) {
03486          if (thispass != lastpass) {
03487             e = g->endpoints;
03488             while(e) {
03489                if (e->type == TYPE_LINE) {
03490                   res = has_voicemail(e);
03491                   if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03492                      if (res) {
03493                         transmit_notify_request(e, "L/vmwi(+)");
03494                      } else {
03495                         transmit_notify_request(e, "L/vmwi(-)");
03496                      }
03497                      e->msgstate = res;
03498                      e->onhooktime = thispass;
03499                   }
03500                }
03501                e = e->next;
03502             }
03503          }
03504          g = g->next;
03505       }
03506 #endif
03507       /* Okay, now that we know what to do, release the network lock */
03508       ast_mutex_unlock(&netlock);
03509       /* And from now on, we're okay to be killed, so release the monitor lock as well */
03510       ast_mutex_unlock(&monlock);
03511       pthread_testcancel();
03512       /* Wait for sched or io */
03513       res = ast_sched_wait(sched);
03514       /* copied from chan_sip.c */
03515       if ((res < 0) || (res > 1000))
03516          res = 1000;
03517       res = ast_io_wait(io, res);
03518       ast_mutex_lock(&monlock);
03519       if (res >= 0) 
03520          ast_sched_runq(sched);
03521       ast_mutex_unlock(&monlock);
03522    }
03523    /* Never reached */
03524    return NULL;
03525 }

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

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2392 of file chan_mgcp.c.

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

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

02393 {
02394    struct mgcp_request *t, *q;
02395 
02396    if (p) {
02397       ast_mutex_lock(&p->rqnt_queue_lock);
02398       for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
02399       p->rqnt_queue = NULL;
02400       ast_mutex_unlock(&p->rqnt_queue_lock);
02401 
02402       ast_mutex_lock(&p->cmd_queue_lock);
02403       for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
02404       p->cmd_queue = NULL;
02405       ast_mutex_unlock(&p->cmd_queue_lock);
02406 
02407       ast_mutex_lock(&p->sub->cx_queue_lock);
02408       for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
02409       p->sub->cx_queue = NULL;
02410       ast_mutex_unlock(&p->sub->cx_queue_lock);
02411 
02412       ast_mutex_lock(&p->sub->next->cx_queue_lock);
02413       for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
02414       p->sub->next->cx_queue = NULL;
02415       ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02416    } else if (sub) {
02417       ast_mutex_lock(&sub->cx_queue_lock);
02418       for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
02419       sub->cx_queue = NULL;
02420       ast_mutex_unlock(&sub->cx_queue_lock);
02421    }
02422 }

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

Definition at line 531 of file chan_mgcp.c.

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

Referenced by destroy_gateway(), and handle_request().

00532 {
00533    struct mgcp_message *cur, *q = NULL, *w, *prev;
00534 
00535    ast_mutex_lock(&gw->msgs_lock);
00536    prev = NULL, cur = gw->msgs;
00537    while (cur) {
00538       if (!p || cur->owner_ep == p) {
00539          if (prev)
00540             prev->next = cur->next;
00541          else
00542             gw->msgs = cur->next;
00543 
00544          ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 
00545             gw->name, cur->seqno);
00546 
00547          w = cur;
00548          cur = cur->next;
00549          if (q) {
00550             w->next = q;
00551          } else {
00552             w->next = NULL;
00553          }
00554          q = w;
00555       } else {
00556          prev = cur, cur=cur->next;
00557       }
00558    }
00559    ast_mutex_unlock(&gw->msgs_lock);
00560 
00561    while (q) {
00562       cur = q;
00563       q = q->next;
00564       free(cur);
00565    }
00566 }

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

Definition at line 3320 of file chan_mgcp.c.

References answer, 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().

03321 {
03322    int seqno=0;
03323    time_t now;
03324    struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03325    time(&now);
03326    if (sscanf(req->identifier, "%30d", &seqno) != 1) 
03327       seqno = 0;
03328    cur = sub->parent->parent->responses;
03329    while(cur) {
03330       next = cur->next;
03331       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03332          /* Delete this entry */
03333          if (prev)
03334             prev->next = next;
03335          else
03336             sub->parent->parent->responses = next;
03337          free(cur);
03338       } else {
03339          if (seqno == cur->seqno)
03340             answer = cur;
03341          prev = cur;
03342       }
03343       cur = next;
03344    }
03345    if (answer) {
03346       resend_response(sub, answer);
03347       return 1;
03348    }
03349    return 0;
03350 }

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 2426 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(), handle_response(), and handle_showagi().

02428 {
02429    struct mgcp_request *prev, *req;
02430 
02431    ast_mutex_lock(l);
02432    for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02433       if (req->trid == ident) {
02434          /* remove from queue */
02435          if (!prev)
02436             *queue = req->next;
02437          else
02438             prev->next = req->next;
02439 
02440          /* send next pending command */
02441          if (*queue) {
02442             if (mgcpdebug) {
02443                ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 
02444                   ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02445             }
02446 
02447             mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02448          }
02449          break;
02450       }
02451    }
02452    ast_mutex_unlock(l);
02453    return req;
02454 }

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

Definition at line 1619 of file chan_mgcp.c.

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

Referenced by mgcp_request(), and mgcpsock_read().

01620 {
01621    struct mgcp_endpoint *p = NULL;
01622    struct mgcp_subchannel *sub = NULL;
01623    struct mgcp_gateway *g;
01624    char tmp[256] = "";
01625    char *at = NULL, *c;
01626    int found = 0;
01627    if (name) {
01628       ast_copy_string(tmp, name, sizeof(tmp));
01629       at = strchr(tmp, '@');
01630       if (!at) {
01631          ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01632          return NULL;
01633       }
01634       *at++ = '\0';
01635    }
01636    ast_mutex_lock(&gatelock);
01637    if (at && (at[0] == '[')) {
01638       at++;
01639       c = strrchr(at, ']');
01640       if (c)
01641          *c = '\0';
01642    }
01643    g = gateways;
01644    while(g) {
01645       if ((!name || !strcasecmp(g->name, at)) && 
01646           (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01647          /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
01648          if (sin && g->dynamic && name) {
01649             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01650                (g->addr.sin_port != sin->sin_port)) {
01651                memcpy(&g->addr, sin, sizeof(g->addr));
01652                if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01653                   memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01654                if (option_verbose > 2)
01655                   ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
01656             }
01657          }
01658          /* not dynamic, check if the name matches */
01659          else if (name) {
01660             if (strcasecmp(g->name, at)) {
01661                g = g->next;
01662                continue;
01663             }
01664          }
01665          /* not dynamic, no name, check if the addr matches */
01666          else if (!name && sin) {
01667             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01668                 (g->addr.sin_port != sin->sin_port)) {
01669                g = g->next;
01670                continue;
01671             }
01672          } else {
01673             g = g->next;
01674             continue;
01675          }
01676          /* SC */
01677          p = g->endpoints;
01678          while(p) {
01679             if (option_debug)
01680                ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
01681                   p->name, g->name);
01682             if (msgid) {
01683 #if 0 /* new transport mech */
01684                sub = p->sub;
01685                do {
01686                   if (option_debug)
01687                      ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01688                         p->name, g->name, sub->id, msgid);
01689                   if (sub->lastout == msgid) {
01690                      if (option_debug)
01691                         ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01692                            sub->id, msgid, sub->lastout);
01693                      found = 1;
01694                      break;
01695                   }
01696                   sub = sub->next;
01697                } while (sub != p->sub);
01698                if (found) {
01699                   break;
01700                }
01701 #endif
01702                /* SC */
01703                sub = p->sub;
01704                found = 1;
01705                /* SC */
01706                break;
01707             } else if (name && !strcasecmp(p->name, tmp)) {
01708                ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
01709                   p->name, g->name, p->sub->id);
01710                sub = p->sub;
01711                found = 1;
01712                break;
01713             }
01714             p = p->next;
01715          }
01716          if (sub && found) {
01717             ast_mutex_lock(&sub->lock);
01718             break;
01719          }
01720       }
01721       g = g->next;
01722    }
01723    ast_mutex_unlock(&gatelock);
01724    if (!sub) {
01725       if (name) {
01726          if (g)
01727             ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01728          else
01729             ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01730       } 
01731    }
01732    return sub;
01733 }

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

get_csv: (SC:) get comma separated value

Definition at line 1598 of file chan_mgcp.c.

References s.

Referenced by handle_response().

01599 {
01600    char *s;
01601 
01602    *next = NULL, *len = 0;
01603    if (!c) return NULL;
01604 
01605    while (*c && (*c < 33 || *c == ','))
01606       c++;
01607 
01608    s = c;
01609    while (*c && (*c >= 33 && *c != ','))
01610       c++, (*len)++;
01611    *next = c;
01612 
01613    if (*len == 0)
01614       s = NULL, *next = NULL;
01615 
01616    return s;
01617 }

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

Definition at line 1591 of file chan_mgcp.c.

References __get_header().

Referenced by __transmit_response(), build_route(), check_auth(), check_user_full(), check_via(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), gettag(), handle_request(), handle_request_bye(), 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(), process_via(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_sipredirect(), sipsock_read(), transmit_fake_auth_response(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_state_notify().

01592 {
01593    int start = 0;
01594    return __get_header(req, name, &start);
01595 }

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

Definition at line 1543 of file chan_mgcp.c.

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

Referenced by process_sdp().

01544 {
01545    int x;
01546    int len = strlen(name);
01547    char *r;
01548 
01549    for (x=0; x<req->lines; x++) {
01550       r = get_sdp_by_line(req->line[x], name, len);
01551       if (r[0] != '\0') return r;
01552    }
01553    return "";
01554 }

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

Definition at line 1533 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01534 {
01535    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01536       char* r = line + nameLen + 1;
01537       while (*r && (*r < 33)) ++r;
01538       return r;
01539    }
01540    return "";
01541 }

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

Definition at line 1561 of file chan_mgcp.c.

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

Referenced by get_ip_and_port_from_sdp(), and process_sdp().

01562 {
01563    int len = strlen(name);
01564    char *r;
01565    while (*iterator < req->lines) {
01566       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01567       if (r[0] != '\0') return r;
01568    }
01569    return "";
01570 }

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

Definition at line 2971 of file chan_mgcp.c.

References ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_UNHOLD, ast_hangup(), ast_log(), ast_pthread_create, 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, t, transmit_modify_request(), and transmit_notify_request().

Referenced by handle_request().

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

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

Definition at line 3057 of file chan_mgcp.c.

References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_DOWN, AST_STATE_UP, 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_DEBUG, 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, option_verbose, 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, VERBOSE_PREFIX_3, and mgcp_gateway::wcardep.

Referenced by mgcpsock_read(), process_request_queue(), and sipsock_read().

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

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 2457 of file chan_mgcp.c.

References ast_copy_string(), ast_log(), ast_strlen_zero(), ast_verbose(), 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(), free, 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, option_verbose, 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(), transmit_notify_request(), and VERBOSE_PREFIX_3.

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

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

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

Definition at line 458 of file chan_mgcp.c.

References ast_app_has_voicemail(), and mgcp_endpoint::mailbox.

00459 {
00460    return ast_app_has_voicemail(p->mailbox, NULL);
00461 }

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

Definition at line 1984 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().

01985 {
01986    /* Initialize a response */
01987    if (req->headers || req->len) {
01988       ast_log(LOG_WARNING, "Request already initialized?!?\n");
01989       return -1;
01990    }
01991    req->header[req->headers] = req->data + req->len;
01992    /* check if we need brackets around the gw name */
01993    if (p->parent->isnamedottedip)
01994       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);
01995    else
01996       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);
01997    req->len += strlen(req->header[req->headers]);
01998    if (req->headers < MGCP_MAX_HEADERS)
01999       req->headers++;
02000    else
02001       ast_log(LOG_WARNING, "Out of header space\n");
02002    return 0;
02003 }

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

Definition at line 1967 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().

01968 {
01969    /* Initialize a response */
01970    if (req->headers || req->len) {
01971       ast_log(LOG_WARNING, "Request already initialized?!?\n");
01972       return -1;
01973    }
01974    req->header[req->headers] = req->data + req->len;
01975    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
01976    req->len += strlen(req->header[req->headers]);
01977    if (req->headers < MGCP_MAX_HEADERS)
01978       req->headers++;
01979    else
01980       ast_log(LOG_WARNING, "Out of header space\n");
01981    return 0;
01982 }

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

Definition at line 4302 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().

04303 {
04304    if (!(sched = sched_context_create())) {
04305       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04306       return AST_MODULE_LOAD_FAILURE;
04307    }
04308 
04309    if (!(io = io_context_create())) {
04310       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04311       sched_context_destroy(sched);
04312       return AST_MODULE_LOAD_FAILURE;
04313    }
04314 
04315    if (reload_config())
04316       return AST_MODULE_LOAD_DECLINE;
04317 
04318    /* Make sure we can register our mgcp channel type */
04319    if (ast_channel_register(&mgcp_tech)) {
04320       ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04321       io_context_destroy(io);
04322       sched_context_destroy(sched);
04323       return AST_MODULE_LOAD_FAILURE;
04324    }
04325 
04326    ast_rtp_proto_register(&mgcp_rtp);
04327    ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04328    
04329    /* And start the monitor for the first time */
04330    restart_monitor();
04331 
04332    return AST_MODULE_LOAD_SUCCESS;
04333 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

Definition at line 1161 of file chan_mgcp.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verbose(), mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_DEBUG, MGCP_CX_SENDRECV, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, option_debug, option_verbose, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request(), and VERBOSE_PREFIX_3.

01162 {
01163    int res = 0;
01164    struct mgcp_subchannel *sub = ast->tech_pvt;
01165    struct mgcp_endpoint *p = sub->parent;
01166 
01167    ast_mutex_lock(&sub->lock);
01168    sub->cxmode = MGCP_CX_SENDRECV;
01169    if (!sub->rtp) {
01170       start_rtp(sub);
01171    } else {
01172       transmit_modify_request(sub);
01173    }
01174    /* verbose level check */
01175    if (option_verbose > 2) {
01176       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n", 
01177          ast->name, p->name, p->parent->name, sub->id);
01178    }
01179    if (ast->_state != AST_STATE_UP) {
01180       ast_setstate(ast, AST_STATE_UP);
01181       if (option_debug)
01182          ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
01183       transmit_notify_request(sub, "");
01184       transmit_modify_request(sub);
01185    }
01186    ast_mutex_unlock(&sub->lock);
01187    return res;
01188 }

static int mgcp_audit_endpoint ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1068 of file chan_mgcp.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_gateway::endpoints, gatelock, gateways, mgcpdebug, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, and transmit_audit_endpoint().

01069 {
01070    struct mgcp_gateway  *g;
01071    struct mgcp_endpoint *e;
01072    int found = 0;
01073    char *ename,*gname, *c;
01074 
01075    if (!mgcpdebug) {
01076       return RESULT_SHOWUSAGE;
01077    }
01078    if (argc != 4) 
01079       return RESULT_SHOWUSAGE;
01080    /* split the name into parts by null */
01081    ename = argv[3];
01082    gname = ename;
01083    while (*gname) {
01084       if (*gname == '@') {
01085          *gname = 0;
01086          gname++;
01087          break;
01088       }
01089       gname++;
01090    }
01091    if (gname[0] == '[')
01092       gname++;
01093    if ((c = strrchr(gname, ']')))
01094       *c = '\0';
01095    ast_mutex_lock(&gatelock);
01096    g = gateways;
01097    while(g) {
01098       if (!strcasecmp(g->name, gname)) {
01099          e = g->endpoints;
01100          while(e) {
01101             if (!strcasecmp(e->name, ename)) {
01102                found = 1;
01103                transmit_audit_endpoint(e);
01104                break;
01105             }
01106             e = e->next;
01107          }
01108          if (found) {
01109             break;
01110          }
01111       }
01112       g = g->next;
01113    }
01114    if (!found) {
01115       ast_cli(fd, "   << Could not find endpoint >>     ");
01116    }
01117    ast_mutex_unlock(&gatelock);
01118    return RESULT_SUCCESS;
01119 }

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

Definition at line 820 of file chan_mgcp.c.

References ast_channel::_state, AST_CONTROL_RINGING, 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_verbose(), 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, ast_channel::varshead, and VERBOSE_PREFIX_3.

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

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 1334 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.

01335 {
01336    struct mgcp_gateway  *g;
01337    struct mgcp_endpoint *e = NULL;
01338    char *tmp, *endpt, *gw;
01339    int ret = AST_DEVICE_INVALID;
01340 
01341    endpt = ast_strdupa(data);
01342    if ((tmp = strchr(endpt, '@'))) {
01343       *tmp++ = '\0';
01344       gw = tmp;
01345    } else
01346       goto error;
01347 
01348    ast_mutex_lock(&gatelock);
01349    g = gateways;
01350    while (g) {
01351       if (strcasecmp(g->name, gw) == 0) {
01352          e = g->endpoints;
01353          break;
01354       }
01355       g = g->next;
01356    }
01357 
01358    if (!e)
01359       goto error;
01360 
01361    while (e) {
01362       if (strcasecmp(e->name, endpt) == 0)
01363          break;
01364       e = e->next;
01365    }
01366 
01367    if (!e)
01368       goto error;
01369 
01370    /*
01371     * As long as the gateway/endpoint is valid, we'll
01372     * assume that the device is available and its state
01373     * can be tracked.
01374     */
01375    ret = AST_DEVICE_UNKNOWN;
01376 
01377 error:
01378    ast_mutex_unlock(&gatelock);
01379    return ret;
01380 }

static int mgcp_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1121 of file chan_mgcp.c.

References ast_cli(), mgcpdebug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01122 {
01123    if (argc != 3)
01124       return RESULT_SHOWUSAGE;
01125    mgcpdebug = 1;
01126    ast_cli(fd, "MGCP Debugging Enabled\n");
01127    return RESULT_SUCCESS;
01128 }

static int mgcp_do_reload ( void   )  [static]

mgcp_do_reload: Reload module

Definition at line 4336 of file chan_mgcp.c.

References reload_config().

Referenced by do_monitor().

04337 {
04338    reload_config();
04339    return 0;
04340 }

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

Definition at line 1261 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.

01262 {
01263    struct mgcp_subchannel *sub = newchan->tech_pvt;
01264 
01265    ast_mutex_lock(&sub->lock);
01266    ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01267    if (sub->owner != oldchan) {
01268       ast_mutex_unlock(&sub->lock);
01269       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01270       return -1;
01271    }
01272    sub->owner = newchan;
01273    ast_mutex_unlock(&sub->lock);
01274    return 0;
01275 }

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

Definition at line 3992 of file chan_mgcp.c.

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

03993 {
03994    struct mgcp_subchannel *sub = NULL;
03995 
03996    if (!(sub = chan->tech_pvt) || !(sub->rtp))
03997       return AST_RTP_GET_FAILED;
03998 
03999    *rtp = sub->rtp;
04000 
04001    if (sub->parent->canreinvite)
04002       return AST_RTP_TRY_NATIVE;
04003    else
04004       return AST_RTP_TRY_PARTIAL;
04005 }

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 913 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_dsp_free(), ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_verbose(), 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, LOG_DEBUG, 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, option_debug, option_verbose, 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(), transmit_notify_request_with_callerid(), VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

00914 {
00915    struct mgcp_subchannel *sub = ast->tech_pvt;
00916    struct mgcp_endpoint *p = sub->parent;
00917 
00918    if (option_debug) {
00919       ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
00920    }
00921    if (!ast->tech_pvt) {
00922       ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
00923       return 0;
00924    }
00925    if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00926       ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
00927       return 0;
00928    }
00929    ast_mutex_lock(&sub->lock);
00930    if (mgcpdebug) {
00931       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00932    }
00933 
00934    if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00935       /* check whether other channel is active. */
00936       if (!sub->next->owner) {
00937          if (p->dtmfmode & MGCP_DTMF_HYBRID)
00938             p->dtmfmode &= ~MGCP_DTMF_INBAND;
00939          if (mgcpdebug) {
00940             ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00941          }
00942          ast_dsp_free(p->dsp);
00943          p->dsp = NULL;
00944       }
00945    }
00946 
00947    sub->owner = NULL;
00948    if (!ast_strlen_zero(sub->cxident)) {
00949       transmit_connection_del(sub);
00950    }
00951    sub->cxident[0] = '\0';
00952    if ((sub == p->sub) && sub->next->owner) {
00953       if (p->hookstate == MGCP_OFFHOOK) {
00954          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00955             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);
00956          }
00957       } else {
00958          /* set our other connection as the primary and swith over to it */
00959          p->sub = sub->next;
00960          p->sub->cxmode = MGCP_CX_RECVONLY;
00961          transmit_modify_request(p->sub);
00962          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00963             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);
00964          }
00965       }
00966 
00967    } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00968       transmit_notify_request(sub, "L/v");
00969    } else if (p->hookstate == MGCP_OFFHOOK) {
00970       transmit_notify_request(sub, "L/ro");
00971    } else {
00972       transmit_notify_request(sub, "");
00973    }
00974 
00975    ast->tech_pvt = NULL;
00976    sub->alreadygone = 0;
00977    sub->outgoing = 0;
00978    sub->cxmode = MGCP_CX_INACTIVE;
00979    sub->callid[0] = '\0';
00980    if (p) {
00981       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
00982    }
00983    /* Reset temporary destination */
00984    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00985    if (sub->rtp) {
00986       ast_rtp_destroy(sub->rtp);
00987       sub->rtp = NULL;
00988    }
00989 
00990    ast_module_unref(ast_module_info->self);
00991 
00992    if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
00993       p->hidecallerid = 0;
00994       if (p->hascallwaiting && !p->callwaiting) {
00995          if (option_verbose > 2)
00996             ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
00997          p->callwaiting = -1;
00998       }
00999       if (has_voicemail(p)) {
01000          if (mgcpdebug) {
01001             ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 
01002                ast->name, p->name, p->parent->name);
01003          }
01004          transmit_notify_request(sub, "L/vmwi(+)");
01005       } else {
01006          if (mgcpdebug) {
01007             ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 
01008                ast->name, p->name, p->parent->name);
01009          }
01010          transmit_notify_request(sub, "L/vmwi(-)");
01011       }
01012    }
01013    ast_mutex_unlock(&sub->lock);
01014    return 0;
01015 }

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

Definition at line 1414 of file chan_mgcp.c.

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

01415 {
01416    struct mgcp_subchannel *sub = ast->tech_pvt;
01417    int res = 0;
01418 
01419    if (mgcpdebug) {
01420       ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
01421          ind, control2str(ind), ast->name);
01422    }
01423    ast_mutex_lock(&sub->lock);
01424    switch(ind) {
01425    case AST_CONTROL_RINGING:
01426 #ifdef DLINK_BUGGY_FIRMWARE   
01427       transmit_notify_request(sub, "rt");
01428 #else
01429       transmit_notify_request(sub, "G/rt");
01430 #endif      
01431       break;
01432    case AST_CONTROL_BUSY:
01433       transmit_notify_request(sub, "L/bz");
01434       break;
01435    case AST_CONTROL_CONGESTION:
01436       transmit_notify_request(sub, "G/cg");
01437       break;
01438    case AST_CONTROL_HOLD:
01439       ast_moh_start(ast, data, NULL);
01440       break;
01441    case AST_CONTROL_UNHOLD:
01442       ast_moh_stop(ast);
01443       break;
01444    case AST_CONTROL_SRCUPDATE:
01445       ast_rtp_new_source(sub->rtp);
01446       break;
01447    case AST_CONTROL_SRCCHANGE:
01448       ast_rtp_change_source(sub->rtp);
01449       break;
01450    case -1:
01451       transmit_notify_request(sub, "");
01452       break;
01453    default:
01454       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01455       res = -1;
01456    }
01457    ast_mutex_unlock(&sub->lock);
01458    return res;
01459 }

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

Definition at line 1461 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_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_verbose(), 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, ast_channel::fds, 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, option_verbose, 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, VERBOSE_PREFIX_3, and ast_channel::writeformat.

Referenced by handle_hd_hf(), and mgcp_request().

01462 {
01463    struct ast_channel *tmp;
01464    struct mgcp_endpoint *i = sub->parent;
01465    int fmt;
01466 
01467    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);
01468    if (tmp) {
01469       tmp->tech = &mgcp_tech;
01470       tmp->nativeformats = i->capability;
01471       if (!tmp->nativeformats)
01472          tmp->nativeformats = capability;
01473       fmt = ast_best_codec(tmp->nativeformats);
01474       ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01475       if (sub->rtp)
01476          tmp->fds[0] = ast_rtp_fd(sub->rtp);
01477       if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01478          i->dsp = ast_dsp_new();
01479          ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
01480          /* this is to prevent clipping of dtmf tones during dsp processing */
01481          ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01482       } else {
01483          i->dsp = NULL;
01484       }
01485       if (state == AST_STATE_RING)
01486          tmp->rings = 1;
01487       tmp->writeformat = fmt;
01488       tmp->rawwriteformat = fmt;
01489       tmp->readformat = fmt;
01490       tmp->rawreadformat = fmt;
01491       tmp->tech_pvt = sub;
01492       if (!ast_strlen_zero(i->language))
01493          ast_string_field_set(tmp, language, i->language);
01494       if (!ast_strlen_zero(i->accountcode))
01495          ast_string_field_set(tmp, accountcode, i->accountcode);
01496       if (i->amaflags)
01497          tmp->amaflags = i->amaflags;
01498       sub->owner = tmp;
01499       ast_module_ref(ast_module_info->self);
01500       tmp->callgroup = i->callgroup;
01501       tmp->pickupgroup = i->pickupgroup;
01502       ast_string_field_set(tmp, call_forward, i->call_forward);
01503       ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
01504       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01505 
01506       /* Don't use ast_set_callerid() here because it will
01507        * generate a needless NewCallerID event */
01508       tmp->cid.cid_ani = ast_strdup(i->cid_num);
01509       
01510       if (!i->adsi)
01511          tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01512       tmp->priority = 1;
01513       if (sub->rtp)
01514          ast_jb_configure(tmp, &global_jbconf);
01515       if (state != AST_STATE_DOWN) {
01516          if (ast_pbx_start(tmp)) {
01517             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01518             ast_hangup(tmp);
01519             tmp = NULL;
01520          }
01521       }
01522       /* verbose level check */
01523       if (option_verbose > 2) {
01524          ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01525             tmp->name, ast_state2str(state));
01526       }
01527    } else {
01528       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01529    }
01530    return tmp;
01531 }

static int mgcp_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1130 of file chan_mgcp.c.

References ast_cli(), mgcpdebug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01131 {
01132    if (argc != 4)
01133       return RESULT_SHOWUSAGE;
01134    mgcpdebug = 0;
01135    ast_cli(fd, "MGCP Debugging Disabled\n");
01136    return RESULT_SUCCESS;
01137 }

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

Definition at line 669 of file chan_mgcp.c.

References __mgcp_xmit(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), mgcp_message::buf, DEFAULT_RETRANS, mgcp_message::expire, mgcp_message::len, LOG_NOTICE, malloc, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_message::retrans, retrans_pkt(), mgcp_gateway::retransid, and mgcp_message::seqno.

Referenced by find_command(), and send_request().

00671 {
00672    struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
00673    struct mgcp_message *cur;
00674    struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
00675    struct timeval tv;
00676 
00677    if (!msg) {
00678       return -1;
00679    }
00680    if (!gw) {
00681       return -1;
00682    }
00683 /* SC
00684    time(&t);
00685    if (gw->messagepending && (gw->lastouttime + 20 < t)) {
00686       ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
00687          gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
00688       dump_queue(sub->parent);
00689    }
00690 */
00691    msg->owner_sub = sub;
00692    msg->owner_ep = p;
00693    msg->seqno = seqno;
00694    msg->next = NULL;
00695    msg->len = len;
00696    msg->retrans = 0;
00697    memcpy(msg->buf, data, msg->len);
00698 
00699    ast_mutex_lock(&gw->msgs_lock);
00700    cur = gw->msgs;
00701    if (cur) {
00702       while(cur->next)
00703          cur = cur->next;
00704       cur->next = msg;
00705    } else {
00706       gw->msgs = msg;
00707    }
00708 
00709    if (gettimeofday(&tv, NULL) < 0) {
00710       /* This shouldn't ever happen, but let's be sure */
00711       ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
00712    } else {
00713       msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
00714 
00715       if (gw->retransid == -1)
00716          gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00717    }
00718    ast_mutex_unlock(&gw->msgs_lock);
00719 /* SC
00720    if (!gw->messagepending) {
00721       gw->messagepending = 1;
00722       gw->lastout = seqno;
00723       gw->lastouttime = t;
00724 */
00725    __mgcp_xmit(gw, msg->buf, msg->len);
00726       /* XXX Should schedule retransmission XXX */
00727 /* SC
00728    } else
00729       ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
00730 */
00731    return 0;
00732 }

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

Definition at line 600 of file chan_mgcp.c.

References AST_FRAME_CONTROL, f, and mgcp_queue_frame().

Referenced by handle_hd_hf().

00601 {
00602    struct ast_frame f = { AST_FRAME_CONTROL, };
00603    f.subclass = control;
00604    return mgcp_queue_frame(sub, &f);
00605 }

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

Definition at line 568 of file chan_mgcp.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, mgcp_subchannel::lock, ast_channel::lock, and mgcp_subchannel::owner.

Referenced by handle_request(), and mgcp_queue_control().

00569 {
00570    for(;;) {
00571       if (sub->owner) {
00572          if (!ast_mutex_trylock(&sub->owner->lock)) {
00573             ast_queue_frame(sub->owner, f);
00574             ast_mutex_unlock(&sub->owner->lock);
00575             break;
00576          } else {
00577             DEADLOCK_AVOIDANCE(&sub->lock);
00578          }
00579       } else
00580          break;
00581    }
00582 }

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

Definition at line 584 of file chan_mgcp.c.

References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_hangup(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, ast_channel::lock, and mgcp_subchannel::owner.

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

00585 {
00586    for(;;) {
00587       if (sub->owner) {
00588          if (!ast_mutex_trylock(&sub->owner->lock)) {
00589             ast_queue_hangup(sub->owner);
00590             ast_mutex_unlock(&sub->owner->lock);
00591             break;
00592          } else {
00593             DEADLOCK_AVOIDANCE(&sub->lock);
00594          }
00595       } else
00596          break;
00597    }
00598 }

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

Definition at line 1221 of file chan_mgcp.c.

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

01222 {
01223    struct ast_frame *f;
01224    struct mgcp_subchannel *sub = ast->tech_pvt;
01225    ast_mutex_lock(&sub->lock);
01226    f = mgcp_rtp_read(sub);
01227    ast_mutex_unlock(&sub->lock);
01228    return f;
01229 }

static int mgcp_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 4342 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), LOG_WARNING, mgcp_reload_lock, mgcp_reloading, and restart_monitor().

Referenced by reload(), and unload_module().

04343 {
04344    static int deprecated = 0;
04345    if (!deprecated && argc > 0) {
04346       ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
04347       deprecated = 1;
04348    }
04349 
04350    ast_mutex_lock(&mgcp_reload_lock);
04351    if (mgcp_reloading) {
04352       ast_verbose("Previous mgcp reload not yet done\n");
04353    } else
04354       mgcp_reloading = 1;
04355    ast_mutex_unlock(&mgcp_reload_lock);
04356    restart_monitor();
04357    return 0;
04358 }

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

Definition at line 3556 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_verbose(), 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, option_verbose, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), transmit_notify_request(), and VERBOSE_PREFIX_3.

03557 {
03558    int oldformat;
03559    struct mgcp_subchannel *sub;
03560    struct ast_channel *tmpc = NULL;
03561    char tmp[256];
03562    char *dest = data;
03563 
03564    oldformat = format;
03565    format &= capability;
03566    if (!format) {
03567       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03568       return NULL;
03569    }
03570    ast_copy_string(tmp, dest, sizeof(tmp));
03571    if (ast_strlen_zero(tmp)) {
03572       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03573       return NULL;
03574    }
03575    sub = find_subchannel_and_lock(tmp, 0, NULL);
03576    if (!sub) {
03577       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03578       *cause = AST_CAUSE_UNREGISTERED;
03579       return NULL;
03580    }
03581    
03582    if (option_verbose > 2) {
03583       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
03584       ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 
03585          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03586    }
03587    /* Must be busy */
03588    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03589       ((!sub->parent->callwaiting) && (sub->owner)) ||
03590        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03591       if (sub->parent->hookstate == MGCP_ONHOOK) {
03592          if (has_voicemail(sub->parent)) {
03593             transmit_notify_request(sub,"L/vmwi(+)");
03594          } else {
03595             transmit_notify_request(sub,"L/vmwi(-)");
03596          }
03597       }
03598       *cause = AST_CAUSE_BUSY;
03599       ast_mutex_unlock(&sub->lock);
03600       return NULL;
03601    }
03602    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03603    ast_mutex_unlock(&sub->lock);
03604    if (!tmpc)
03605       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03606    restart_monitor();
03607    return tmpc;
03608 }

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

Definition at line 1190 of file chan_mgcp.c.

References 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_DEBUG, 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().

01191 {
01192    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
01193    struct ast_frame *f;
01194 
01195    f = ast_rtp_read(sub->rtp);
01196    /* Don't send RFC2833 if we're not supposed to */
01197    if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01198       return &ast_null_frame;
01199    if (sub->owner) {
01200       /* We already hold the channel lock */
01201       if (f->frametype == AST_FRAME_VOICE) {
01202          if (f->subclass != sub->owner->nativeformats) {
01203             ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01204             sub->owner->nativeformats = f->subclass;
01205             ast_set_read_format(sub->owner, sub->owner->readformat);
01206             ast_set_write_format(sub->owner, sub->owner->writeformat);
01207          }
01208          /* Courtesy fearnor aka alex@pilosoft.com */
01209          if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01210 #if 0
01211             ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01212 #endif
01213             f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01214          }
01215       }
01216    }
01217    return f;
01218 }

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

Definition at line 1277 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.

01278 {
01279    struct mgcp_subchannel *sub = ast->tech_pvt;
01280    struct mgcp_endpoint *p = sub->parent;
01281    int res = 0;
01282 
01283    ast_mutex_lock(&sub->lock);
01284    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01285       ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
01286       res = -1; /* Let asterisk play inband indications */
01287    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01288       ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
01289       ast_rtp_senddigit_begin(sub->rtp, digit);
01290    } else {
01291       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01292    }
01293    ast_mutex_unlock(&sub->lock);
01294 
01295    return res;
01296 }

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

Definition at line 1298 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().

01299 {
01300    struct mgcp_subchannel *sub = ast->tech_pvt;
01301    struct mgcp_endpoint *p = sub->parent;
01302    int res = 0;
01303    char tmp[4];
01304 
01305    ast_mutex_lock(&sub->lock);
01306    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01307       ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
01308       res = -1; /* Tell Asterisk to stop inband indications */
01309    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01310       ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
01311       tmp[0] = 'D';
01312       tmp[1] = '/';
01313       tmp[2] = digit;
01314       tmp[3] = '\0';
01315       transmit_notify_request(sub, tmp);
01316                 ast_rtp_senddigit_end(sub->rtp, digit);
01317    } else {
01318       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01319    }
01320    ast_mutex_unlock(&sub->lock);
01321 
01322    return res;
01323 }

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

Definition at line 4007 of file chan_mgcp.c.

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

04008 {
04009    /* XXX Is there such thing as video support with MGCP? XXX */
04010    struct mgcp_subchannel *sub;
04011    sub = chan->tech_pvt;
04012    if (sub && !sub->alreadygone) {
04013       transmit_modify_with_sdp(sub, rtp, codecs);
04014       return 0;
04015    }
04016    return -1;
04017 }

static int mgcp_show_endpoints ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1017 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_endpoint::context, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, mgcp_subchannel::owner, RESULT_SHOWUSAGE, RESULT_SUCCESS, mgcp_endpoint::sub, and mgcp_gateway::wcardep.

01018 {
01019    struct mgcp_gateway  *g;
01020    struct mgcp_endpoint *e;
01021    int hasendpoints = 0;
01022 
01023    if (argc != 3) 
01024       return RESULT_SHOWUSAGE;
01025    ast_mutex_lock(&gatelock);
01026    g = gateways;
01027    while(g) {
01028       e = g->endpoints;
01029       ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? ast_inet_ntoa(g->addr.sin_addr) : ast_inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
01030       while(e) {
01031          /* Don't show wilcard endpoint */
01032          if (strcmp(e->name, g->wcardep) !=0)
01033             ast_cli(fd, "   -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
01034          hasendpoints = 1;
01035          e = e->next;
01036       }
01037       if (!hasendpoints) {
01038          ast_cli(fd, "   << No Endpoints Defined >>     ");
01039       }
01040       g = g->next;
01041    }
01042    ast_mutex_unlock(&gatelock);
01043    return RESULT_SUCCESS;
01044 }

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

Definition at line 2649 of file chan_mgcp.c.

References ast_bridged_channel(), ast_canmatch_extension(), ast_copy_string(), ast_db_put(), 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_verbose(), ast_waitfordigit(), mgcp_endpoint::call_forward, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, 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_DEBUG, LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_subchannel::next, option_debug, option_verbose, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_notify_request(), and VERBOSE_PREFIX_3.

Referenced by handle_hd_hf().

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

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

Definition at line 1231 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.

01232 {
01233    struct mgcp_subchannel *sub = ast->tech_pvt;
01234    int res = 0;
01235    if (frame->frametype != AST_FRAME_VOICE) {
01236       if (frame->frametype == AST_FRAME_IMAGE)
01237          return 0;
01238       else {
01239          ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01240          return 0;
01241       }
01242    } else {
01243       if (!(frame->subclass & ast->nativeformats)) {
01244          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01245             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01246          return -1;
01247       }
01248    }
01249    if (sub) {
01250       ast_mutex_lock(&sub->lock);
01251       if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01252          if (sub->rtp) {
01253             res =  ast_rtp_write(sub->rtp, frame);
01254          }
01255       }
01256       ast_mutex_unlock(&sub->lock);
01257    }
01258    return res;
01259 }

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

Definition at line 3352 of file chan_mgcp.c.

References 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(), free, handle_request(), handle_response(), len(), mgcp_subchannel::lock, LOG_DEBUG, 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().

03353 {
03354    struct mgcp_request req;
03355    struct sockaddr_in sin;
03356    struct mgcp_subchannel *sub;
03357    int res;
03358    socklen_t len;
03359    int result;
03360    int ident;
03361    len = sizeof(sin);
03362    memset(&req, 0, sizeof(req));
03363    res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03364    if (res < 0) {
03365       if (errno != ECONNREFUSED)
03366          ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03367       return 1;
03368    }
03369    req.data[res] = '\0';
03370    req.len = res;
03371    if (mgcpdebug) {
03372       ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03373    }
03374    parse(&req);
03375    if (req.headers < 1) {
03376       /* Must have at least one header */
03377       return 1;
03378    }
03379    if (ast_strlen_zero(req.identifier)) {
03380       ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03381       return 1;
03382    }
03383 
03384    if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
03385       /* Try to find who this message is for, if it's important */
03386       sub = find_subchannel_and_lock(NULL, ident, &sin);
03387       if (sub) {
03388          struct mgcp_gateway *gw = sub->parent->parent;
03389          struct mgcp_message *cur, *prev;
03390 
03391          ast_mutex_unlock(&sub->lock);
03392          ast_mutex_lock(&gw->msgs_lock);
03393          for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03394             if (cur->seqno == ident) {
03395                ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
03396                if (prev)
03397                   prev->next = cur->next;
03398                else
03399                   gw->msgs = cur->next;
03400                break;
03401             }
03402          }
03403 
03404          /* stop retrans timer if the queue is empty */
03405          if (!gw->msgs) {
03406             AST_SCHED_DEL(sched, gw->retransid);
03407          }
03408 
03409          ast_mutex_unlock(&gw->msgs_lock);
03410          if (cur) {
03411             handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03412             free(cur);
03413             return 1;
03414          }
03415 
03416          ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 
03417             gw->name, ident);
03418       }
03419    } else {
03420       if (ast_strlen_zero(req.endpoint) || 
03421             ast_strlen_zero(req.version) || 
03422          ast_strlen_zero(req.verb)) {
03423          ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03424          return 1;
03425       }
03426       /* Process request, with iflock held */
03427       sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03428       if (sub) {
03429          /* look first to find a matching response in the queue */
03430          if (!find_and_retrans(sub, &req))
03431             /* pass the request off to the currently mastering subchannel */
03432             handle_request(sub, &req, &sin);
03433          ast_mutex_unlock(&sub->lock);
03434       }
03435    }
03436    return 1;
03437 }

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1735 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 __login_exec(), acf_channel_read(), add_agent(), app_exec(), aqm_exec(), ast_hint_state_changed(), ast_parse_allow_disallow(), astman_get_variables(), conf_exec(), cut_internal(), dahdi_accept_r2_call_exec(), dictate_exec(), directory_exec(), find_conf(), function_agent(), get_in_brackets(), isAnsweringMachine(), mgcpsock_read(), mixmonitor_exec(), pbx_builtin_background(), pbx_builtin_saydate(), pbx_builtin_saytime(), pbx_builtin_waitexten(), pqm_exec(), privacy_exec(), ql_exec(), queue_exec(), reload_agents(), reload_queues(), rqm_exec(), sayunixtime_exec(), sendimage_exec(), sendtext_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), transfer_exec(), upqm_exec(), userevent_exec(), and vm_execmain().

01736 {
01737    /* Divide fields by NULL's */
01738    char *c;
01739    int f = 0;
01740    c = req->data;
01741 
01742    /* First header starts immediately */
01743    req->header[f] = c;
01744    while(*c) {
01745       if (*c == '\n') {
01746          /* We've got a new header */
01747          *c = 0;
01748 #if 0
01749          printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01750 #endif         
01751          if (ast_strlen_zero(req->header[f])) {
01752             /* Line by itself means we're now in content */
01753             c++;
01754             break;
01755          }
01756          if (f >= MGCP_MAX_HEADERS - 1) {
01757             ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01758          } else
01759             f++;
01760          req->header[f] = c + 1;
01761       } else if (*c == '\r') {
01762          /* Ignore but eliminate \r's */
01763          *c = 0;
01764       }
01765       c++;
01766    }
01767    /* Check for last header */
01768    if (!ast_strlen_zero(req->header[f])) 
01769       f++;
01770    req->headers = f;
01771    /* Now we process any mime content */
01772    f = 0;
01773    req->line[f] = c;
01774    while(*c) {
01775       if (*c == '\n') {
01776          /* We've got a new line */
01777          *c = 0;
01778 #if 0
01779          printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01780 #endif         
01781          if (f >= MGCP_MAX_LINES - 1) {
01782             ast_log(LOG_WARNING, "Too many SDP lines...\n");
01783          } else
01784             f++;
01785          req->line[f] = c + 1;
01786       } else if (*c == '\r') {
01787          /* Ignore and eliminate \r's */
01788          *c = 0;
01789       }
01790       c++;
01791    }
01792    /* Check for last line */
01793    if (!ast_strlen_zero(req->line[f])) 
01794       f++;
01795    req->lines = f;
01796    /* Parse up the initial header */
01797    c = req->header[0];
01798    while(*c && *c < 33) c++;
01799    /* First the verb */
01800    req->verb = c;
01801    while(*c && (*c > 32)) c++;
01802    if (*c) {
01803       *c = '\0';
01804       c++;
01805       while(*c && (*c < 33)) c++;
01806       req->identifier = c;
01807       while(*c && (*c > 32)) c++;
01808       if (*c) {
01809          *c = '\0';
01810          c++;
01811          while(*c && (*c < 33)) c++;
01812          req->endpoint = c;
01813          while(*c && (*c > 32)) c++;
01814          if (*c) {
01815             *c = '\0';
01816             c++;
01817             while(*c && (*c < 33)) c++;
01818             req->version = c;
01819             while(*c && (*c > 32)) c++;
01820             while(*c && (*c < 33)) c++;
01821             while(*c && (*c > 32)) c++;
01822             *c = '\0';
01823          }
01824       }
01825    }
01826       
01827    if (mgcpdebug) {
01828       ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01829          req->verb, req->identifier, req->endpoint, req->version);
01830       ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01831    }
01832    if (*c) 
01833       ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01834 }

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

Definition at line 1836 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, portno, mgcp_subchannel::rtp, sdpLineNum_iterator_init(), and mgcp_endpoint::sub.

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

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

static void prune_gateways ( void   )  [static]

Definition at line 4077 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

04078 {
04079    struct mgcp_gateway *g, *z, *r;
04080    struct mgcp_endpoint *e, *p, *t;
04081 
04082    ast_mutex_lock(&gatelock);
04083 
04084    /* prune gateways */
04085    for (z = NULL, g = gateways; g;) {
04086       /* prune endpoints */
04087       for (p = NULL, e = g->endpoints; e; ) {
04088          if (e->delme || g->delme) {
04089             t = e;
04090             e = e->next;
04091             if (!p)
04092                g->endpoints = e;
04093             else
04094                p->next = e;
04095             destroy_endpoint(t);
04096          } else {
04097             p = e;
04098             e = e->next;
04099          }
04100       }
04101 
04102       if (g->delme) {
04103          r = g;
04104          g = g->next;
04105          if (!z)
04106             gateways = g;
04107          else
04108             z->next = g;
04109 
04110          destroy_gateway(r);
04111       } else {
04112          z = g;
04113          g = g->next;
04114       }
04115    }
04116 
04117    ast_mutex_unlock(&gatelock);
04118 }

static int reload ( void   )  [static]

Definition at line 4360 of file chan_mgcp.c.

References mgcp_reload().

04361 {
04362    mgcp_reload(0, 0, NULL);
04363    return 0;
04364 }

static int reload_config ( void   )  [static]

Definition at line 4120 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_sched_runq(), ast_variable_browse(), ast_verbose(), bindaddr, build_gateway(), capability, config, default_jbconf, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, dtmfmode, mgcp_gateway::endpoints, errno, format, gatelock, gateways, global_jbconf, hp, io, IPTOS_MINCOST, 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, option_verbose, ourhost, ourport, prune_gateways(), tos, transmit_audit_endpoint(), ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

04121 {
04122    struct ast_config *cfg;
04123    struct ast_variable *v;
04124    struct mgcp_gateway *g;
04125    struct mgcp_endpoint *e;
04126    char *cat;
04127    struct ast_hostent ahp;
04128    struct hostent *hp;
04129    int format;
04130    
04131    if (gethostname(ourhost, sizeof(ourhost)-1)) {
04132       ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04133       return 0;
04134    }
04135    cfg = ast_config_load(config);
04136 
04137    /* We *must* have a config file otherwise stop immediately */
04138    if (!cfg) {
04139       ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04140       return 0;
04141    }
04142    memset(&bindaddr, 0, sizeof(bindaddr));
04143    dtmfmode = 0;
04144 
04145    /* Copy the default jb config over global_jbconf */
04146    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04147 
04148    v = ast_variable_browse(cfg, "general");
04149    while (v) {
04150       /* handle jb conf */
04151       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04152          v = v->next;
04153          continue;
04154       }
04155 
04156       /* Create the interface list */
04157       if (!strcasecmp(v->name, "bindaddr")) {
04158          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04159             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04160          } else {
04161             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04162          }
04163       } else if (!strcasecmp(v->name, "allow")) {
04164          format = ast_getformatbyname(v->value);
04165          if (format < 1) 
04166             ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04167          else
04168             capability |= format;
04169       } else if (!strcasecmp(v->name, "disallow")) {
04170          format = ast_getformatbyname(v->value);
04171          if (format < 1) 
04172             ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04173          else
04174             capability &= ~format;
04175       } else if (!strcasecmp(v->name, "tos")) {
04176          if (sscanf(v->value, "%30d", &format) == 1)
04177             tos = format & 0xff;
04178          else if (!strcasecmp(v->value, "lowdelay"))
04179             tos = IPTOS_LOWDELAY;
04180          else if (!strcasecmp(v->value, "throughput"))
04181             tos = IPTOS_THROUGHPUT;
04182          else if (!strcasecmp(v->value, "reliability"))
04183             tos = IPTOS_RELIABILITY;
04184          else if (!strcasecmp(v->value, "mincost"))
04185             tos = IPTOS_MINCOST;
04186          else if (!strcasecmp(v->value, "none"))
04187             tos = 0;
04188          else
04189             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04190       } else if (!strcasecmp(v->name, "port")) {
04191          if (sscanf(v->value, "%30d", &ourport) == 1) {
04192             bindaddr.sin_port = htons(ourport);
04193          } else {
04194             ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04195          }
04196       }
04197       v = v->next;
04198    }
04199 
04200    /* mark existing entries for deletion */
04201    ast_mutex_lock(&gatelock);
04202    g = gateways;
04203    while (g) {
04204       g->delme = 1;
04205       e = g->endpoints;
04206       while (e) {
04207          e->delme = 1;
04208          e = e->next;
04209       }
04210       g = g->next;
04211    }
04212    ast_mutex_unlock(&gatelock);
04213    
04214    cat = ast_category_browse(cfg, NULL);
04215    while(cat) {
04216       if (strcasecmp(cat, "general")) {
04217          ast_mutex_lock(&gatelock);
04218          g = build_gateway(cat, ast_variable_browse(cfg, cat));
04219          if (g) {
04220             if (option_verbose > 2) {
04221                ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
04222             }
04223             g->next = gateways;
04224             gateways = g;
04225          }
04226          ast_mutex_unlock(&gatelock);
04227 
04228          /* FS: process queue and IO */
04229          if (monitor_thread == pthread_self()) {
04230             if (sched) ast_sched_runq(sched);
04231             if (io) ast_io_wait(io, 10);
04232          }
04233       }
04234       cat = ast_category_browse(cfg, cat);
04235    }
04236 
04237       /* prune deleted entries etc. */
04238       prune_gateways();
04239 
04240    if (ntohl(bindaddr.sin_addr.s_addr)) {
04241       memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04242    } else {
04243       hp = ast_gethostbyname(ourhost, &ahp);
04244       if (!hp) {
04245          ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04246          ast_config_destroy(cfg);
04247          return 0;
04248       }
04249       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04250    }
04251    if (!ntohs(bindaddr.sin_port))
04252       bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04253    bindaddr.sin_family = AF_INET;
04254    ast_mutex_lock(&netlock);
04255    if (mgcpsock > -1)
04256       close(mgcpsock);
04257 
04258    if (mgcpsock_read_id != NULL)
04259       ast_io_remove(io, mgcpsock_read_id);
04260    mgcpsock_read_id = NULL;
04261 
04262    mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04263    if (mgcpsock < 0) {
04264       ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04265    } else {
04266       if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04267          ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04268             ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04269                strerror(errno));
04270          close(mgcpsock);
04271          mgcpsock = -1;
04272       } else {
04273          if (option_verbose > 1) {
04274             ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n", 
04275                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04276             ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04277          }
04278          if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
04279             ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04280       }
04281    }
04282    ast_mutex_unlock(&netlock);
04283    ast_config_destroy(cfg);
04284 
04285    /* send audit only to the new endpoints */
04286    g = gateways;
04287    while (g) {
04288       e = g->endpoints;
04289       while (e && e->needaudit) {
04290          e->needaudit = 0;
04291          transmit_audit_endpoint(e);
04292          ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04293          e = e->next;
04294       }
04295       g = g->next;
04296    }
04297 
04298    return 0;
04299 }

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

Definition at line 2013 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_reinvite_with_t38_sdp(), transmit_request(), transmit_request_with_auth(), and transmit_state_notify().

02014 {
02015    memset(req, 0, sizeof(struct mgcp_request));
02016    oseq++;
02017    if (oseq > 999999999)
02018       oseq = 1;
02019    init_req(p, req, verb);
02020    return 0;
02021 }

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

Definition at line 504 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().

00505 {
00506    struct mgcp_endpoint *p = sub->parent;
00507    int res;
00508    if (mgcpdebug) {
00509       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));
00510    }
00511    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00512    if (res > 0)
00513       res = 0;
00514    return res;
00515 }

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

Definition at line 2006 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_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().

02007 {
02008    memset(resp, 0, sizeof(*resp));
02009    init_resp(resp, msg, req, msgrest);
02010    return 0;
02011 }

static int restart_monitor ( void   )  [static]

Definition at line 3527 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.

03528 {
03529    /* If we're supposed to be stopped -- stay stopped */
03530    if (monitor_thread == AST_PTHREADT_STOP)
03531       return 0;
03532    if (ast_mutex_lock(&monlock)) {
03533       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03534       return -1;
03535    }
03536    if (monitor_thread == pthread_self()) {
03537       ast_mutex_unlock(&monlock);
03538       ast_log(LOG_WARNING, "Cannot kill myself\n");
03539       return -1;
03540    }
03541    if (monitor_thread != AST_PTHREADT_NULL) {
03542       /* Wake up the thread */
03543       pthread_kill(monitor_thread, SIGURG);
03544    } else {
03545       /* Start a new monitor */
03546       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03547          ast_mutex_unlock(&monlock);
03548          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03549          return -1;
03550       }
03551    }
03552    ast_mutex_unlock(&monlock);
03553    return 0;
03554 }

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

Definition at line 607 of file chan_mgcp.c.

References __mgcp_xmit(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, 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().

00608 {
00609    struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00610    struct mgcp_message *cur, *exq = NULL, *w, *prev;
00611    int res = 0;
00612 
00613    /* find out expired msgs */
00614    ast_mutex_lock(&gw->msgs_lock);
00615 
00616    prev = NULL, cur = gw->msgs;
00617    while (cur) {
00618       if (cur->retrans < MAX_RETRANS) {
00619          cur->retrans++;
00620          if (mgcpdebug) {
00621             ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00622                cur->retrans, cur->seqno, gw->name);
00623          }
00624          __mgcp_xmit(gw, cur->buf, cur->len);
00625 
00626          prev = cur;
00627          cur = cur->next;
00628       } else {
00629          if (prev)
00630             prev->next = cur->next;
00631          else
00632             gw->msgs = cur->next;
00633 
00634          ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00635             cur->seqno, gw->name);
00636 
00637          w = cur;
00638          cur = cur->next;
00639 
00640          if (exq) {
00641             w->next = exq;
00642          } else {
00643             w->next = NULL;
00644          }
00645          exq = w;
00646       }
00647    }
00648 
00649    if (!gw->msgs) {
00650       gw->retransid = -1;
00651       res = 0;
00652    } else {
00653       res = 1;
00654    }
00655    ast_mutex_unlock(&gw->msgs_lock);
00656 
00657    while (exq) {
00658       cur = exq;
00659       /* time-out transaction */
00660       handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
00661       exq = exq->next;
00662       free(cur);
00663    }
00664 
00665    return res;
00666 }

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1556 of file chan_mgcp.c.

Referenced by process_sdp().

01557 {
01558    *iterator = 0;
01559 }

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

Definition at line 735 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_inet_ntoa(), ast_log(), 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, free, mgcp_request::len, LOG_DEBUG, LOG_WARNING, malloc, 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, mgcp_endpoint::slowsequence, and t.

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_reinvite_with_t38_sdp(), transmit_request(), transmit_request_with_auth(), transmit_sip_request(), and transmit_state_notify().

00737 {
00738    int res = 0;
00739    struct mgcp_request **queue, *q, *r, *t;
00740    ast_mutex_t *l;
00741 
00742    ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
00743    if (p->slowsequence) {
00744       queue = &p->cmd_queue;
00745       l = &p->cmd_queue_lock;
00746       ast_mutex_lock(l);
00747    } else {
00748       switch (req->cmd) {
00749       case MGCP_CMD_DLCX:
00750          queue = &sub->cx_queue;
00751          l = &sub->cx_queue_lock;
00752          ast_mutex_lock(l);
00753          q = sub->cx_queue;
00754          /* delete pending cx cmds */
00755          while (q) {
00756             r = q->next;
00757             free(q);
00758             q = r;
00759          }
00760          *queue = NULL;
00761          break;
00762 
00763       case MGCP_CMD_CRCX:
00764       case MGCP_CMD_MDCX:
00765          queue = &sub->cx_queue;
00766          l = &sub->cx_queue_lock;
00767          ast_mutex_lock(l);
00768          break;
00769 
00770       case MGCP_CMD_RQNT:
00771          queue = &p->rqnt_queue;
00772          l = &p->rqnt_queue_lock;
00773          ast_mutex_lock(l);
00774          break;
00775 
00776       default:
00777          queue = &p->cmd_queue;
00778          l = &p->cmd_queue_lock;
00779          ast_mutex_lock(l);
00780          break;
00781       }
00782    }
00783 
00784    r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
00785    if (!r) {
00786       ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00787       ast_mutex_unlock(l);
00788       return -1;
00789    }
00790    memcpy(r, req, sizeof(struct mgcp_request));
00791 
00792    if (!(*queue)) {
00793       if (mgcpdebug) {
00794          ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
00795             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00796       }
00797 
00798       res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00799    } else {
00800       if (mgcpdebug) {
00801          ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
00802             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00803       }
00804    }
00805 
00806    /* XXX find tail. We could also keep tail in the data struct for faster access */
00807    for (t = *queue; t && t->next; t = t->next);
00808 
00809    r->next = NULL;
00810    if (t)
00811       t->next = r;
00812    else
00813       *queue = r;
00814 
00815    ast_mutex_unlock(l);
00816 
00817    return res;
00818 }

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

Definition at line 517 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_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().

00518 {
00519    struct mgcp_endpoint *p = sub->parent;
00520    int res;
00521    if (mgcpdebug) {
00522       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));
00523    }
00524    res = __mgcp_xmit(p->parent, req->data, req->len);
00525    if (res > 0)
00526       res = 0;
00527    return res;
00528 }

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2624 of file chan_mgcp.c.

References 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(), bindaddr, mgcp_subchannel::callid, ast_channel::fds, io, mgcp_subchannel::lock, mgcp_subchannel::nat, mgcp_subchannel::owner, mgcp_subchannel::rtp, 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(), mgcp_answer(), mgcp_call(), mgcp_ss(), skinny_answer(), and skinny_newcall().

02625 {
02626    ast_mutex_lock(&sub->lock);
02627    /* check again to be on the safe side */
02628    if (sub->rtp) {
02629       ast_rtp_destroy(sub->rtp);
02630       sub->rtp = NULL;
02631    }
02632    /* Allocate the RTP now */
02633    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02634    if (sub->rtp && sub->owner)
02635       sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
02636    if (sub->rtp)
02637       ast_rtp_setnat(sub->rtp, sub->nat);
02638 #if 0
02639    ast_rtp_set_callback(p->rtp, rtpready);
02640    ast_rtp_set_data(p->rtp, p);
02641 #endif      
02642    /* Make a call*ID */
02643         snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02644    /* Transmit the connection create */
02645    transmit_connect_with_sdp(sub, NULL);
02646    ast_mutex_unlock(&sub->lock);
02647 }

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

Definition at line 2333 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_request(), mgcp_audit_endpoint(), and reload_config().

02334 {
02335    struct mgcp_request resp;
02336    reqprep(&resp, p, "AUEP");
02337    /* removed unknown param VS */
02338    /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
02339    add_header(&resp, "F", "A");
02340    /* fill in new fields */
02341    resp.cmd = MGCP_CMD_AUEP;
02342    resp.trid = oseq;
02343    return send_request(p, NULL, &resp, oseq);  /* SC */
02344 }

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

Definition at line 2179 of file chan_mgcp.c.

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

Referenced by start_rtp().

02180 {
02181    struct mgcp_request resp;
02182    char local[256];
02183    char tmp[80];
02184    int x;
02185    struct mgcp_endpoint *p = sub->parent;
02186 
02187    snprintf(local, sizeof(local), "p:20");
02188    for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02189       if (p->capability & x) {
02190          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02191          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02192       }
02193    }
02194    if (mgcpdebug) {
02195       ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 
02196          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02197    }
02198    reqprep(&resp, p, "CRCX");
02199    add_header(&resp, "C", sub->callid);
02200    add_header(&resp, "L", local);
02201    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02202    /* X header should not be sent. kept for compatibility */
02203    add_header(&resp, "X", sub->txident);
02204    /*add_header(&resp, "S", "");*/
02205    add_sdp(&resp, sub, rtp);
02206    /* fill in new fields */
02207    resp.cmd = MGCP_CMD_CRCX;
02208    resp.trid = oseq;
02209    return send_request(p, sub, &resp, oseq);  /* SC */
02210 }

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

Definition at line 2346 of file chan_mgcp.c.

References add_header(), ast_verbose(), 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, mgcp_subchannel::txident, and VERBOSE_PREFIX_3.

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

02347 {
02348    struct mgcp_endpoint *p = sub->parent;
02349    struct mgcp_request resp;
02350 
02351    if (mgcpdebug) {
02352       ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 
02353          sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02354    }
02355    reqprep(&resp, p, "DLCX");
02356    /* check if call id is avail */
02357    if (sub->callid[0])
02358       add_header(&resp, "C", sub->callid);
02359    /* X header should not be sent. kept for compatibility */
02360    add_header(&resp, "X", sub->txident);
02361    /* check if cxident is avail */
02362    if (sub->cxident[0])
02363       add_header(&resp, "I", sub->cxident);
02364    /* fill in new fields */
02365    resp.cmd = MGCP_CMD_DLCX;
02366    resp.trid = oseq;
02367    return send_request(p, sub, &resp, oseq);  /* SC */
02368 }

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

Definition at line 2370 of file chan_mgcp.c.

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

Referenced by handle_response().

02371 {
02372    struct mgcp_request resp;
02373 
02374    if (mgcpdebug) {
02375       ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n", 
02376          cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02377    }
02378    reqprep(&resp, p, "DLCX");
02379    /* check if call id is avail */
02380    if (callid && *callid)
02381       add_header(&resp, "C", callid);
02382    /* check if cxident is avail */
02383    if (cxident && *cxident)
02384       add_header(&resp, "I", cxident);
02385    /* fill in new fields */
02386    resp.cmd = MGCP_CMD_DLCX;
02387    resp.trid = oseq;
02388    return send_request(p, p->sub, &resp, oseq);
02389 }

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2288 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_strlen_zero(), ast_verbose(), 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, mgcp_subchannel::txident, and VERBOSE_PREFIX_3.

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

02289 {
02290    struct mgcp_request resp;
02291    struct mgcp_endpoint *p = sub->parent;
02292 
02293    if (ast_strlen_zero(sub->cxident)) {
02294       /* We don't have a CXident yet, store the destination and
02295          wait a bit */
02296       return 0;
02297    }
02298    if (mgcpdebug) {
02299       ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n", 
02300          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02301    }
02302    reqprep(&resp, p, "MDCX");
02303    add_header(&resp, "C", sub->callid);
02304    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02305    /* X header should not be sent. kept for compatibility */
02306    add_header(&resp, "X", sub->txident);
02307    add_header(&resp, "I", sub->cxident);
02308    switch (sub->parent->hookstate) {
02309    case MGCP_ONHOOK:
02310       add_header(&resp, "R", "L/hd(N)");
02311       break;
02312    case MGCP_OFFHOOK:
02313       add_header_offhook(sub, &resp);
02314       break;
02315    }
02316    /* fill in new fields */
02317    resp.cmd = MGCP_CMD_MDCX;
02318    resp.trid = oseq;
02319    return send_request(p, sub, &resp, oseq); /* SC */
02320 }

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

Definition at line 2139 of file chan_mgcp.c.

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

Referenced by handle_response(), and mgcp_set_rtp_peer().

02140 {
02141    struct mgcp_request resp;
02142    char local[256];
02143    char tmp[80];
02144    int x;
02145    int capability;
02146    struct mgcp_endpoint *p = sub->parent;
02147 
02148    capability = p->capability;
02149    if (codecs)
02150       capability = codecs;
02151    if (ast_strlen_zero(sub->cxident) && rtp) {
02152       /* We don't have a CXident yet, store the destination and
02153          wait a bit */
02154       ast_rtp_get_peer(rtp, &sub->tmpdest);
02155       return 0;
02156    }
02157    snprintf(local, sizeof(local), "p:20");
02158    for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02159       if (p->capability & x) {
02160          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02161          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02162       }
02163    }
02164    reqprep(&resp, p, "MDCX");
02165    add_header(&resp, "C", sub->callid);
02166    add_header(&resp, "L", local);
02167    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02168    /* X header should not be sent. kept for compatibility */
02169    add_header(&resp, "X", sub->txident);
02170    add_header(&resp, "I", sub->cxident);
02171    /*add_header(&resp, "S", "");*/
02172    add_sdp(&resp, sub, rtp);
02173    /* fill in new fields */
02174    resp.cmd = MGCP_CMD_MDCX;
02175    resp.trid = oseq;
02176    return send_request(p, sub, &resp, oseq); /* SC */
02177 }

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

Definition at line 2212 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_strlen_zero(), ast_verbose(), 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, mgcp_request::trid, and VERBOSE_PREFIX_3.

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().

02213 {
02214    struct mgcp_request resp;
02215    struct mgcp_endpoint *p = sub->parent;
02216 
02217    if (mgcpdebug) {
02218       ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
02219          tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02220    }
02221    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02222    reqprep(&resp, p, "RQNT");
02223    add_header(&resp, "X", p->rqnt_ident); /* SC */
02224    switch (p->hookstate) {
02225    case MGCP_ONHOOK:
02226       add_header(&resp, "R", "L/hd(N)");
02227       break;
02228    case MGCP_OFFHOOK:
02229       add_header_offhook(sub, &resp);
02230       break;
02231    }
02232    if (!ast_strlen_zero(tone)) {
02233       add_header(&resp, "S", tone);
02234    }
02235    /* fill in new fields */
02236    resp.cmd = MGCP_CMD_RQNT;
02237    resp.trid = oseq;
02238    return send_request(p, NULL, &resp, oseq); /* SC */
02239 }

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

Definition at line 2241 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_localtime(), ast_strlen_zero(), ast_verbose(), 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, t, mgcp_request::trid, and VERBOSE_PREFIX_3.

Referenced by mgcp_call(), and mgcp_hangup().

02242 {
02243    struct mgcp_request resp;
02244    char tone2[256];
02245    char *l, *n;
02246    time_t t;
02247    struct tm tm;
02248    struct mgcp_endpoint *p = sub->parent;
02249    
02250    time(&t);
02251    ast_localtime(&t, &tm, NULL);
02252    n = callername;
02253    l = callernum;
02254    if (!n)
02255       n = "";
02256    if (!l)
02257       l = "";
02258 
02259    /* Keep track of last callerid for blacklist and callreturn */
02260    ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02261 
02262    snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
02263       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02264    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02265    reqprep(&resp, p, "RQNT");
02266    add_header(&resp, "X", p->rqnt_ident); /* SC */
02267    switch (p->hookstate) {
02268    case MGCP_ONHOOK:
02269       add_header(&resp, "R", "L/hd(N)");
02270       break;
02271    case MGCP_OFFHOOK:
02272       add_header_offhook(sub, &resp);
02273       break;
02274    }
02275    if (!ast_strlen_zero(tone2)) {
02276       add_header(&resp, "S", tone2);
02277    }
02278    if (mgcpdebug) {
02279       ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
02280          tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02281    }
02282    /* fill in new fields */
02283    resp.cmd = MGCP_CMD_RQNT;
02284    resp.trid = oseq;
02285    return send_request(p, NULL, &resp, oseq);  /* SC */
02286 }

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

Definition at line 2023 of file chan_mgcp.c.

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

Referenced by 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_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), handle_server_request_message(), 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(), receive_message(), register_verify(), send_provisional_keepalive_full(), sip_indicate(), sip_park_thread(), sipsock_read(), skinny_hold(), skinny_reset_device(), skinny_unhold(), transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_provisional_response(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

02024 {
02025    struct mgcp_request resp;
02026    struct mgcp_endpoint *p = sub->parent;
02027    struct mgcp_response *mgr;
02028 
02029    respprep(&resp, p, msg, req, msgrest);
02030    mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
02031    if (mgr) {
02032       /* Store MGCP response in case we have to retransmit */
02033       memset(mgr, 0, sizeof(struct mgcp_response));
02034       sscanf(req->identifier, "%30d", &mgr->seqno);
02035       time(&mgr->whensent);
02036       mgr->len = resp.len;
02037       memcpy(mgr->buf, resp.data, resp.len);
02038       mgr->buf[resp.len] = '\0';
02039       mgr->next = p->parent->responses;
02040       p->parent->responses = mgr;
02041    }
02042    return send_response(sub, &resp);
02043 }

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

Definition at line 463 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_log(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_DEBUG, 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().

00464 {
00465    struct mgcp_endpoint *p = sub->parent;
00466    if (p->sub == sub) {
00467       ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00468       return -1;
00469    }
00470    ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00471 
00472    sub->owner = NULL;
00473    if (!ast_strlen_zero(sub->cxident)) {
00474       transmit_connection_del(sub);
00475    }
00476    sub->cxident[0] = '\0';
00477    sub->callid[0] = '\0';
00478    sub->cxmode = MGCP_CX_INACTIVE;
00479    sub->outgoing = 0;
00480    sub->alreadygone = 0;
00481    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00482    if (sub->rtp) {
00483       ast_rtp_destroy(sub->rtp);
00484       sub->rtp = NULL;
00485    }
00486    dump_cmd_queues(NULL, sub); /* SC */
00487    return 0;
00488 }

static int unload_module ( void   )  [static]

Definition at line 4366 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().

04367 {
04368    struct mgcp_endpoint *e;
04369    struct mgcp_gateway *g;
04370 
04371    /* Check to see if we're reloading */
04372    if (ast_mutex_trylock(&mgcp_reload_lock)) {
04373       ast_log(LOG_WARNING, "MGCP is currently reloading.  Unable to remove module.\n");
04374       return -1;
04375    } else {
04376       mgcp_reloading = 1;
04377       ast_mutex_unlock(&mgcp_reload_lock);
04378    }
04379 
04380    /* First, take us out of the channel loop */
04381    ast_channel_unregister(&mgcp_tech);
04382 
04383    /* Shut down the monitoring thread */
04384    if (!ast_mutex_lock(&monlock)) {
04385       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04386          pthread_cancel(monitor_thread);
04387          pthread_kill(monitor_thread, SIGURG);
04388          pthread_join(monitor_thread, NULL);
04389       }
04390       monitor_thread = AST_PTHREADT_STOP;
04391       ast_mutex_unlock(&monlock);
04392    } else {
04393       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04394       /* We always want to leave this in a consistent state */
04395       ast_channel_register(&mgcp_tech);
04396       mgcp_reloading = 0;
04397       mgcp_reload(0, 0, NULL);
04398       return -1;
04399    }
04400 
04401    if (!ast_mutex_lock(&gatelock)) {
04402       for (g = gateways; g; g = g->next) {
04403          g->delme = 1;
04404          for (e = g->endpoints; e; e = e->next)
04405             e->delme = 1;
04406       }
04407 
04408       prune_gateways();
04409       ast_mutex_unlock(&gatelock);
04410    } else {
04411       ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04412       /* We always want to leave this in a consistent state */
04413       ast_channel_register(&mgcp_tech);
04414       /* Allow the monitor to restart */
04415       monitor_thread = AST_PTHREADT_NULL;
04416       mgcp_reloading = 0;
04417       mgcp_reload(0, 0, NULL);
04418       return -1;
04419    }
04420 
04421    close(mgcpsock);
04422    ast_rtp_proto_unregister(&mgcp_rtp);
04423    ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04424    sched_context_destroy(sched);
04425 
04426    return 0;
04427 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 4433 of file chan_mgcp.c.

struct in_addr __ourip [static]

Definition at line 224 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 189 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 195 of file chan_mgcp.c.

int amaflags = 0 [static]

Definition at line 193 of file chan_mgcp.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4433 of file chan_mgcp.c.

char audit_endpoint_usage[] [static]

Initial value:

 
"Usage: mgcp audit endpoint <endpointid>\n"
"       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
"       mgcp debug MUST be on to see the results of this command.\n"

Definition at line 1050 of file chan_mgcp.c.

struct sockaddr_in bindaddr [static]

Definition at line 409 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 174 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int callwaiting = 0 [static]

Definition at line 172 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int cancallforward = 0 [static]

Definition at line 183 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int canreinvite = CANREINVITE [static]

Definition at line 187 of file chan_mgcp.c.

Referenced by build_gateway().

int capability = AST_FORMAT_ULAW [static]

Definition at line 220 of file chan_mgcp.c.

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

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 160 of file chan_mgcp.c.

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

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 159 of file chan_mgcp.c.

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

struct ast_cli_entry cli_mgcp[] [static]

Definition at line 1139 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

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

Definition at line 113 of file chan_mgcp.c.

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

Definition at line 155 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 165 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 166 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

char debug_usage[] [static]

Initial value:

 
"Usage: mgcp set debug\n"
"       Enables dumping of MGCP packets for debugging purposes\n"

Definition at line 1055 of file chan_mgcp.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 103 of file chan_mgcp.c.

int dtmfmode = 0 [static]

Definition at line 162 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 200 of file chan_mgcp.c.

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

gatelock: mutex for gateway/endpoint lists

Definition at line 405 of file chan_mgcp.c.

Referenced by find_subchannel_and_lock(), mgcp_audit_endpoint(), mgcp_devicestate(), mgcp_show_endpoints(), prune_gateways(), reload_config(), and unload_module().

struct mgcp_gateway * gateways [static]

Referenced by build_gateway(), do_monitor(), find_subchannel_and_lock(), mgcp_audit_endpoint(), mgcp_devicestate(), mgcp_show_endpoints(), prune_gateways(), reload_config(), and unload_module().

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic)

Definition at line 203 of file chan_mgcp.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 110 of file chan_mgcp.c.

int immediate = 0 [static]

Definition at line 170 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

struct io_context* io [static]

Definition at line 230 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 157 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 191 of file chan_mgcp.c.

Referenced by action_mailboxcount(), action_mailboxstatus(), append_mailbox_mapping(), build_device(), build_gateway(), build_peer(), disa_exec(), and realtime_directory().

int matchdigittimeout = 3000 [static]

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

Definition at line 206 of file chan_mgcp.c.

char* mgcp_cxmodes[] [static]

}

Definition at line 135 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_MUTEX_INITIALIZER ) [static]

Definition at line 401 of file chan_mgcp.c.

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

char mgcp_reload_usage[] [static]

Initial value:

"Usage: mgcp reload\n"
"       Reloads MGCP configuration from mgcp.conf\n"
"       Deprecated:  please use 'reload chan_mgcp.so' instead.\n"

Definition at line 1063 of file chan_mgcp.c.

int mgcp_reloading = 0 [static]

Definition at line 402 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 4019 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 439 of file chan_mgcp.c.

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

int mgcpdebug = 0 [static]

Definition at line 227 of file chan_mgcp.c.

Referenced by add_sdp(), mgcp_audit_endpoint(), mgcp_call(), mgcp_do_debug(), mgcp_hangup(), mgcp_indicate(), mgcp_no_debug(), parse(), process_sdp(), retrans_pkt(), and send_request().

int mgcpsock = -1 [static]

Definition at line 407 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 3439 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 216 of file chan_mgcp.c.

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

Definition at line 212 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

Definition at line 158 of file chan_mgcp.c.

Referenced by ast_do_masquerade(), begin_dial(), build_gateway(), findmeexec(), func_channel_write_real(), gtalk_new(), local_call(), moh2_exec(), and moh_write().

int nat = 0 [static]

Definition at line 163 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [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 210 of file chan_mgcp.c.

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

char no_debug_usage[] [static]

Initial value:

 
"Usage: mgcp set debug off\n"
"       Disables dumping of MGCP packets for debugging purposes\n"

Definition at line 1059 of file chan_mgcp.c.

int nonCodecCapability = AST_RTP_DTMF [static]

Definition at line 221 of file chan_mgcp.c.

Referenced by process_sdp().

unsigned int oseq [static]

Definition at line 197 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 223 of file chan_mgcp.c.

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

int ourport [static]

Definition at line 225 of file chan_mgcp.c.

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

struct sched_context* sched [static]

Definition at line 229 of file chan_mgcp.c.

char show_endpoints_usage[] [static]

Initial value:

 
"Usage: mgcp show endpoints\n"
"       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n"

Definition at line 1046 of file chan_mgcp.c.

int singlepath = 0 [static]

Definition at line 185 of file chan_mgcp.c.

Referenced by build_gateway().

int slowsequence = 0 [static]

Definition at line 176 of file chan_mgcp.c.

Referenced by build_gateway().

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

Definition at line 112 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 178 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

int tos = 0 [static]

Definition at line 168 of file chan_mgcp.c.

int transfer = 0 [static]

This is for flashhook transfers

Definition at line 181 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), and leave_voicemail().


Generated on Sat Aug 6 00:39:46 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7