Thu Oct 8 00:59:27 2009

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 = "6989f2ec67f8497e38c12890500c525b" , .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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static ast_mutex_t netlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 1569 of file chan_mgcp.c.

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

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

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

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

static void __unreg_module ( void   )  [static]

Definition at line 4430 of file chan_mgcp.c.

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

Definition at line 1919 of file chan_mgcp.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

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

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

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

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

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

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

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4064 of file chan_mgcp.c.

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

04065 {
04066    if (g->ha)
04067       ast_free_ha(g->ha);
04068 
04069    dump_queue(g, NULL);
04070 
04071    free (g);
04072 }

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

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

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

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

dump_cmd_queues: (SC:) cleanup pending commands

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

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

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

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

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

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

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

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

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

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

get_csv: (SC:) get comma separated value

Definition at line 1595 of file chan_mgcp.c.

References s.

Referenced by handle_response().

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

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

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

01589 {
01590    int start = 0;
01591    return __get_header(req, name, &start);
01592 }

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

Definition at line 1540 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

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

Definition at line 1530 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

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

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

Definition at line 1558 of file chan_mgcp.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

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

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

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

References reload_config().

Referenced by do_monitor().

04334 {
04335    reload_config();
04336    return 0;
04337 }

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

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

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_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, 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 -1:
01448       transmit_notify_request(sub, "");
01449       break;
01450    default:
01451       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01452       res = -1;
01453    }
01454    ast_mutex_unlock(&sub->lock);
01455    return res;
01456 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1732 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(), cut_internal(), 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().

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

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

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

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

static void prune_gateways ( void   )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 4357 of file chan_mgcp.c.

References mgcp_reload().

04358 {
04359    mgcp_reload(0, 0, NULL);
04360    return 0;
04361 }

static int reload_config ( void   )  [static]

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

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

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

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

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

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

02004 {
02005    memset(resp, 0, sizeof(*resp));
02006    init_resp(resp, msg, req, msgrest);
02007    return 0;
02008 }

static int restart_monitor ( void   )  [static]

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

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

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

Referenced by process_sdp().

01554 {
01555    *iterator = 0;
01556 }

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

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

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

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

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

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

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

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

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

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

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

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

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

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

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2020 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(), local_attended_transfer(), receive_message(), register_verify(), 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_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

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

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

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


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 = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 4430 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 4430 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 4016 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 3436 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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(), func_channel_write(), 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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(), leave_voicemail(), and send_packet().


Generated on Thu Oct 8 00:59:28 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7