Mon Sep 18 09:14:17 2006

Asterisk developer's documentation


chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

#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.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"

Go to the source code of this file.

Data Structures

struct  mgcp_endpoint
struct  mgcp_gateway
struct  mgcp_message
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_CMD_AUCX   7
#define MGCP_CMD_AUEP   6
#define MGCP_CMD_CRCX   1
#define MGCP_CMD_DLCX   3
#define MGCP_CMD_EPCF   0
#define MGCP_CMD_MDCX   2
#define MGCP_CMD_NTFY   5
#define MGCP_CMD_RQNT   4
#define MGCP_CMD_RSIP   8
#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

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 int add_header (struct mgcp_request *req, char *var, char *value)
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)
 AST_MUTEX_DEFINE_STATIC (gatelock)
 AST_MUTEX_DEFINE_STATIC (mgcp_reload_lock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 AST_MUTEX_DEFINE_STATIC (netlock)
 AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static int attempt_transfer (struct mgcp_endpoint *p)
static struct mgcp_gatewaybuild_gateway (char *cat, struct ast_variable *v)
static char * control2str (int ind)
char * description ()
 Provides a description of the module.
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)
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)
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)
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)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module ()
 Initialize the module.
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_do_debug (int fd, int argc, char *argv[])
static int mgcp_do_reload (void)
static int mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static struct ast_rtpmgcp_get_rtp_peer (struct ast_channel *chan)
static int mgcp_hangup (struct ast_channel *ast)
static int mgcp_indicate (struct ast_channel *ast, int ind)
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 (struct ast_channel *ast, char digit)
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)
int reload (void)
 Reload stuff.
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 (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)
int unload_module ()
 Cleanup all module structures, sockets, etc.
int usecount ()
 Provides a usecount.

Variables

static struct in_addr __ourip
static char accountcode [AST_MAX_ACCOUNT_CODE] = ""
static int adsi = 0
static int amaflags = 0
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_audit_endpoint
static struct ast_cli_entry cli_debug
static struct ast_cli_entry cli_mgcp_reload
static struct ast_cli_entry cli_no_debug
static struct ast_cli_entry cli_show_endpoints
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 const char desc [] = "Media Gateway Control Protocol (MGCP)"
static int dtmfmode = 0
static int firstdigittimeout = 16000
static struct mgcp_gatewaygateways
static int gendigittimeout = 8000
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 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 char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
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
static const char type [] = "MGCP"
static int usecnt = 0


Detailed Description

Implementation of Media Gateway Control Protocol.

See also

Definition in file chan_mgcp.c.


Define Documentation

#define CANREINVITE   1

Definition at line 130 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_EXPIRY   120

Definition at line 128 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_CA_PORT   2727

Definition at line 146 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT   2427

Definition at line 145 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS   1000

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

Referenced by build_gateway().

#define IPTOS_MINCOST   0x02

Definition at line 118 of file chan_mgcp.c.

#define MAX_EXPIRY   3600

Definition at line 129 of file chan_mgcp.c.

#define MAX_RETRANS   5

Definition at line 149 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 333 of file chan_mgcp.c.

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

#define MGCP_CMD_AUCX   7

Definition at line 176 of file chan_mgcp.c.

#define MGCP_CMD_AUEP   6

Definition at line 175 of file chan_mgcp.c.

Referenced by handle_response(), and transmit_audit_endpoint().

#define MGCP_CMD_CRCX   1

Definition at line 170 of file chan_mgcp.c.

Referenced by handle_response(), and send_request().

#define MGCP_CMD_DLCX   3

Definition at line 172 of file chan_mgcp.c.

Referenced by send_request(), transmit_connection_del(), and transmit_connection_del_w_params().

#define MGCP_CMD_EPCF   0

Definition at line 169 of file chan_mgcp.c.

#define MGCP_CMD_MDCX   2

Definition at line 171 of file chan_mgcp.c.

Referenced by send_request(), and transmit_modify_request().

#define MGCP_CMD_NTFY   5

Definition at line 174 of file chan_mgcp.c.

#define MGCP_CMD_RQNT   4

Definition at line 173 of file chan_mgcp.c.

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

#define MGCP_CMD_RSIP   8

Definition at line 177 of file chan_mgcp.c.

#define MGCP_CX_CONF   3

Definition at line 155 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 156 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 158 of file chan_mgcp.c.

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

#define MGCP_CX_MUTE   4

Definition at line 157 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

Definition at line 153 of file chan_mgcp.c.

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

#define MGCP_CX_SENDONLY   0

Definition at line 152 of file chan_mgcp.c.

#define MGCP_CX_SENDRECV   2

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

Referenced by build_gateway(), mgcp_hangup(), mgcp_new(), and mgcp_ss().

#define MGCP_DTMF_INBAND   (1 << 1)

Definition at line 142 of file chan_mgcp.c.

Referenced by build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_ss(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

#define MGCP_DTMF_RFC2833   (1 << 0)

Definition at line 141 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_rtp_read().

#define MGCP_MAX_HEADERS   64

Definition at line 282 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

Definition at line 283 of file chan_mgcp.c.

Referenced by add_line(), and parse().

#define MGCP_MAX_PACKET   1500

Definition at line 147 of file chan_mgcp.c.

#define MGCP_OFFHOOK   2

Definition at line 375 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 374 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!"

Definition at line 344 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 127 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

Definition at line 323 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 336 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 335 of file chan_mgcp.c.

#define TYPE_LINE   2

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

Referenced by build_device(), and build_gateway().


Function Documentation

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

Definition at line 1497 of file chan_mgcp.c.

References mgcp_request::header, and mgcp_request::headers.

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

01498 {
01499    int x;
01500    int len = strlen(name);
01501    char *r;
01502    for (x=*start;x<req->headers;x++) {
01503       if (!strncasecmp(req->header[x], name, len) && 
01504           (req->header[x][len] == ':')) {
01505          r = req->header[x] + len + 1;
01506          while(*r && (*r < 33))
01507             r++;
01508          *start = x+1;
01509          return r;
01510       }
01511    }
01512    /* Don't return NULL, so get_header is always a valid pointer */
01513    return "";
01514 }

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

Definition at line 550 of file chan_mgcp.c.

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

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

00551 {
00552    int res;
00553    if (gw->addr.sin_addr.s_addr)
00554       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00555    else 
00556       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00557    if (res != len) {
00558       ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00559    }
00560    return res;
00561 }

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

Definition at line 1849 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_route(), add_sdp(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), initreqprep(), reqprep(), respprep(), sip_notify(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_invite(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request_with_auth(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_unsupported(), and transmit_state_notify().

01850 {
01851    if (req->len >= sizeof(req->data) - 4) {
01852       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01853       return -1;
01854    }
01855    if (req->lines) {
01856       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01857       return -1;
01858    }
01859    req->header[req->headers] = req->data + req->len;
01860    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01861    req->len += strlen(req->header[req->headers]);
01862    if (req->headers < MGCP_MAX_HEADERS)
01863       req->headers++;
01864    else {
01865       ast_log(LOG_WARNING, "Out of header space\n");
01866       return -1;
01867    }
01868    return 0;   
01869 }

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

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

01872 {
01873    if (req->len >= sizeof(req->data) - 4) {
01874       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01875       return -1;
01876    }
01877    if (!req->lines) {
01878       /* Add extra empty return */
01879       snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
01880       req->len += strlen(req->data + req->len);
01881    }
01882    req->line[req->lines] = req->data + req->len;
01883    snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01884    req->len += strlen(req->line[req->lines]);
01885    if (req->lines < MGCP_MAX_LINES)
01886       req->lines++;
01887    else {
01888       ast_log(LOG_WARNING, "Out of line space\n");
01889       return -1;
01890    }
01891    return 0;   
01892 }

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

Definition at line 1973 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, mgcp_response::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(), and transmit_response_with_sdp().

01974 {
01975    int len;
01976    int codec;
01977    char costr[80];
01978    struct sockaddr_in sin;
01979    char v[256];
01980    char s[256];
01981    char o[256];
01982    char c[256];
01983    char t[256];
01984    char m[256] = "";
01985    char a[1024] = "";
01986    char iabuf[INET_ADDRSTRLEN];
01987    int x;
01988    struct sockaddr_in dest;
01989    struct mgcp_endpoint *p = sub->parent;
01990    /* XXX We break with the "recommendation" and send our IP, in order that our
01991           peer doesn't have to ast_gethostbyname() us XXX */
01992    len = 0;
01993    if (!sub->rtp) {
01994       ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
01995       return -1;
01996    }
01997    ast_rtp_get_us(sub->rtp, &sin);
01998    if (rtp) {
01999       ast_rtp_get_peer(rtp, &dest);
02000    } else {
02001       if (sub->tmpdest.sin_addr.s_addr) {
02002          dest.sin_addr = sub->tmpdest.sin_addr;
02003          dest.sin_port = sub->tmpdest.sin_port;
02004          /* Reset temporary destination */
02005          memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02006       } else {
02007          dest.sin_addr = p->parent->ourip;
02008          dest.sin_port = sin.sin_port;
02009       }
02010    }
02011    if (mgcpdebug) {
02012       ast_verbose("We're at %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->ourip), ntohs(sin.sin_port));
02013    }
02014    snprintf(v, sizeof(v), "v=0\r\n");
02015    snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
02016    snprintf(s, sizeof(s), "s=session\r\n");
02017    snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
02018    snprintf(t, sizeof(t), "t=0 0\r\n");
02019    snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02020    for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02021       if (p->capability & x) {
02022          if (mgcpdebug) {
02023             ast_verbose("Answering with capability %d\n", x);
02024          }
02025          codec = ast_rtp_lookup_code(sub->rtp, 1, x);
02026          if (codec > -1) {
02027             snprintf(costr, sizeof(costr), " %d", codec);
02028             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02029             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
02030             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02031          }
02032       }
02033    }
02034    for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02035       if (p->nonCodecCapability & x) {
02036          if (mgcpdebug) {
02037             ast_verbose("Answering with non-codec capability %d\n", x);
02038          }
02039          codec = ast_rtp_lookup_code(sub->rtp, 0, x);
02040          if (codec > -1) {
02041             snprintf(costr, sizeof(costr), " %d", codec);
02042             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02043             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
02044             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02045             if (x == AST_RTP_DTMF) {
02046                /* Indicate we support DTMF...  Not sure about 16,
02047                   but MSN supports it so dang it, we will too... */
02048                snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02049                strncat(a, costr, sizeof(a) - strlen(a) - 1);
02050             }
02051          }
02052       }
02053    }
02054    strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02055    len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02056    snprintf(costr, sizeof(costr), "%d", len);
02057    add_line(resp, v);
02058    add_line(resp, o);
02059    add_line(resp, s);
02060    add_line(resp, c);
02061    add_line(resp, t);
02062    add_line(resp, m);
02063    add_line(resp, a);
02064    return 0;
02065 }

AST_MUTEX_DEFINE_STATIC ( gatelock   ) 

AST_MUTEX_DEFINE_STATIC ( mgcp_reload_lock   ) 

AST_MUTEX_DEFINE_STATIC ( monlock   ) 

AST_MUTEX_DEFINE_STATIC ( netlock   ) 

AST_MUTEX_DEFINE_STATIC ( usecnt_lock   ) 

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

Definition at line 2825 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_indicate(), ast_log(), ast_moh_stop(), 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.

Referenced by handle_message(), handle_request(), handle_request_refer(), and zt_handle_event().

02826 {
02827    /* *************************
02828     * I hope this works.
02829     * Copied out of chan_zap
02830     * Cross your fingers
02831     * *************************/
02832 
02833    /* In order to transfer, we need at least one of the channels to
02834       actually be in a call bridge.  We can't conference two applications
02835       together (but then, why would we want to?) */
02836    if (ast_bridged_channel(p->sub->owner)) {
02837       /* The three-way person we're about to transfer to could still be in MOH, so
02838          stop if now if appropriate */
02839       if (ast_bridged_channel(p->sub->next->owner))
02840          ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
02841       if (p->sub->owner->_state == AST_STATE_RINGING) {
02842          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02843       }
02844       if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
02845          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02846             ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
02847          return -1;
02848       }
02849       /* Orphan the channel */
02850       unalloc_sub(p->sub->next);
02851    } else if (ast_bridged_channel(p->sub->next->owner)) {
02852       if (p->sub->owner->_state == AST_STATE_RINGING) {
02853          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
02854       }
02855       ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
02856       if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
02857          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
02858             ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
02859          return -1;
02860       }
02861       /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
02862       if (option_verbose > 2) {
02863          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);
02864       }
02865       p->sub = p->sub->next;
02866       unalloc_sub(p->sub->next);
02867       /* Tell the caller not to hangup */
02868       return 1;
02869    } else {
02870       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
02871          p->sub->owner->name, p->sub->next->owner->name);
02872       p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02873       if (p->sub->next->owner) {
02874          p->sub->next->alreadygone = 1;
02875          mgcp_queue_hangup(p->sub->next);
02876       }
02877    }
02878    return 0;
02879 }

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

Definition at line 3535 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_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_ouraddrfor(), 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().

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

static char* control2str ( int  ind  )  [static]

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

01315                                   {
01316    switch (ind) {
01317    case AST_CONTROL_HANGUP:
01318       return "Other end has hungup";
01319    case AST_CONTROL_RING:
01320       return "Local ring";
01321    case AST_CONTROL_RINGING:
01322       return "Remote end is ringing";
01323    case AST_CONTROL_ANSWER:
01324       return "Remote end has answered";
01325    case AST_CONTROL_BUSY:
01326       return "Remote end is busy";
01327    case AST_CONTROL_TAKEOFFHOOK:
01328       return "Make it go off hook";
01329    case AST_CONTROL_OFFHOOK:
01330       return "Line is off hook";
01331    case AST_CONTROL_CONGESTION:
01332       return "Congestion (circuits busy)";
01333    case AST_CONTROL_FLASH:
01334       return "Flash hook";
01335    case AST_CONTROL_WINK:
01336       return "Wink";
01337    case AST_CONTROL_OPTION:
01338       return "Set a low-level option";
01339    case AST_CONTROL_RADIO_KEY:
01340       return "Key Radio";
01341    case AST_CONTROL_RADIO_UNKEY:
01342       return "Un-Key Radio";
01343    }
01344    return "UNKNOWN";
01345 }

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 4387 of file chan_mgcp.c.

References desc.

04388 {
04389    return (char *) desc;
04390 }

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

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

03980 {
03981    struct mgcp_subchannel *sub = e->sub->next, *s;
03982    int i;
03983 
03984    for (i = 0; i < MAX_SUBS; i++) {
03985       ast_mutex_lock(&sub->lock);
03986       if (!ast_strlen_zero(sub->cxident)) {
03987          transmit_connection_del(sub);
03988       }
03989       if (sub->rtp) {
03990          ast_rtp_destroy(sub->rtp);
03991          sub->rtp = NULL;
03992       }
03993       memset(sub->magic, 0, sizeof(sub->magic));
03994       mgcp_queue_hangup(sub);
03995       dump_cmd_queues(NULL, sub);
03996       ast_mutex_unlock(&sub->lock);
03997       sub = sub->next;
03998    }
03999 
04000    if (e->dsp) {
04001       ast_dsp_free(e->dsp);
04002    }
04003 
04004    dump_queue(e->parent, e);
04005    dump_cmd_queues(e, NULL);
04006 
04007    sub = e->sub;
04008    for (i = 0; (i < MAX_SUBS) && sub; i++) {
04009       s = sub;
04010       sub = sub->next;
04011       ast_mutex_destroy(&s->lock);
04012       ast_mutex_destroy(&s->cx_queue_lock);
04013       free(s);
04014    }
04015    ast_mutex_destroy(&e->lock);
04016    ast_mutex_destroy(&e->rqnt_queue_lock);
04017    ast_mutex_destroy(&e->cmd_queue_lock);
04018    free(e);
04019 }

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4021 of file chan_mgcp.c.

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

04022 {
04023    if (g->ha)
04024       ast_free_ha(g->ha);
04025 
04026    dump_queue(g, NULL);
04027 
04028    free (g);
04029 }

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

Definition at line 3365 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_reloading, mgcpsock, mgcpsock_read(), option_verbose, transmit_notify_request(), TYPE_LINE, and VERBOSE_PREFIX_1.

03366 {
03367    int res;
03368    int reloading;
03369    /*struct mgcp_gateway *g;*/
03370    /*struct mgcp_endpoint *e;*/
03371    /*time_t thispass = 0, lastpass = 0;*/
03372 
03373    /* Add an I/O event to our UDP socket */
03374    if (mgcpsock > -1) 
03375       mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03376    
03377    /* This thread monitors all the frame relay interfaces which are not yet in use
03378       (and thus do not have a separate thread) indefinitely */
03379    /* From here on out, we die whenever asked */
03380    for(;;) {
03381       /* Check for a reload request */
03382       ast_mutex_lock(&mgcp_reload_lock);
03383       reloading = mgcp_reloading;
03384       mgcp_reloading = 0;
03385       ast_mutex_unlock(&mgcp_reload_lock);
03386       if (reloading) {
03387          if (option_verbose > 0)
03388             ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
03389          mgcp_do_reload();
03390          /* Add an I/O event to our UDP socket */
03391          if (mgcpsock > -1) 
03392             mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03393       }
03394 
03395       /* Check for interfaces needing to be killed */
03396       /* Don't let anybody kill us right away.  Nobody should lock the interface list
03397          and wait for the monitor list, but the other way around is okay. */
03398       ast_mutex_lock(&monlock);
03399       /* Lock the network interface */
03400       ast_mutex_lock(&netlock);
03401 
03402 #if 0
03403       /* XXX THIS IS COMPLETELY HOSED */
03404       /* The gateway goes into a state of panic */
03405       /* If the vmwi indicator is sent while it is reseting interfaces */
03406       lastpass = thispass;
03407       thispass = time(NULL);
03408       g = gateways;
03409       while(g) {
03410          if (thispass != lastpass) {
03411             e = g->endpoints;
03412             while(e) {
03413                if (e->type == TYPE_LINE) {
03414                   res = has_voicemail(e);
03415                   if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03416                      if (res) {
03417                         transmit_notify_request(e, "L/vmwi(+)");
03418                      } else {
03419                         transmit_notify_request(e, "L/vmwi(-)");
03420                      }
03421                      e->msgstate = res;
03422                      e->onhooktime = thispass;
03423                   }
03424                }
03425                e = e->next;
03426             }
03427          }
03428          g = g->next;
03429       }
03430 #endif
03431       /* Okay, now that we know what to do, release the network lock */
03432       ast_mutex_unlock(&netlock);
03433       /* And from now on, we're okay to be killed, so release the monitor lock as well */
03434       ast_mutex_unlock(&monlock);
03435       pthread_testcancel();
03436       /* Wait for sched or io */
03437       res = ast_sched_wait(sched);
03438       /* SC: copied from chan_sip.c */
03439       if ((res < 0) || (res > 1000))
03440          res = 1000;
03441       res = ast_io_wait(io, res);
03442       ast_mutex_lock(&monlock);
03443       if (res >= 0) 
03444          ast_sched_runq(sched);
03445       ast_mutex_unlock(&monlock);
03446    }
03447    /* Never reached */
03448    return NULL;
03449 }

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

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

02313 {
02314    struct mgcp_request *t, *q;
02315 
02316    if (p) {
02317       ast_mutex_lock(&p->rqnt_queue_lock);
02318       for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
02319       p->rqnt_queue = NULL;
02320       ast_mutex_unlock(&p->rqnt_queue_lock);
02321 
02322       ast_mutex_lock(&p->cmd_queue_lock);
02323       for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
02324       p->cmd_queue = NULL;
02325       ast_mutex_unlock(&p->cmd_queue_lock);
02326 
02327       ast_mutex_lock(&p->sub->cx_queue_lock);
02328       for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
02329       p->sub->cx_queue = NULL;
02330       ast_mutex_unlock(&p->sub->cx_queue_lock);
02331 
02332       ast_mutex_lock(&p->sub->next->cx_queue_lock);
02333       for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
02334       p->sub->next->cx_queue = NULL;
02335       ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02336    } else if (sub) {
02337       ast_mutex_lock(&sub->cx_queue_lock);
02338       for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
02339       sub->cx_queue = NULL;
02340       ast_mutex_unlock(&sub->cx_queue_lock);
02341    }
02342 }

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

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

00593 {
00594    struct mgcp_message *cur, *q = NULL, *w, *prev;
00595 
00596    ast_mutex_lock(&gw->msgs_lock);
00597    prev = NULL, cur = gw->msgs;
00598    while (cur) {
00599       if (!p || cur->owner_ep == p) {
00600          if (prev)
00601             prev->next = cur->next;
00602          else
00603             gw->msgs = cur->next;
00604 
00605          ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 
00606             gw->name, cur->seqno);
00607 
00608          w = cur;
00609          cur = cur->next;
00610          if (q) {
00611             w->next = q;
00612          } else {
00613             w->next = NULL;
00614          }
00615          q = w;
00616       } else {
00617          prev = cur, cur=cur->next;
00618       }
00619    }
00620    ast_mutex_unlock(&gw->msgs_lock);
00621 
00622    while (q) {
00623       cur = q;
00624       q = q->next;
00625       free(cur);
00626    }
00627 }

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

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

03243 {
03244    int seqno=0;
03245    time_t now;
03246    struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03247    time(&now);
03248    if (sscanf(req->identifier, "%d", &seqno) != 1) 
03249       seqno = 0;
03250    cur = sub->parent->parent->responses;
03251    while(cur) {
03252       next = cur->next;
03253       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03254          /* Delete this entry */
03255          if (prev)
03256             prev->next = next;
03257          else
03258             sub->parent->parent->responses = next;
03259          free(cur);
03260       } else {
03261          if (seqno == cur->seqno)
03262             answer = cur;
03263          prev = cur;
03264       }
03265       cur = next;
03266    }
03267    if (answer) {
03268       resend_response(sub, answer);
03269       return 1;
03270    }
03271    return 0;
03272 }

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]

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

02348 {
02349    struct mgcp_request *prev, *req;
02350    char iabuf[INET_ADDRSTRLEN];
02351 
02352    ast_mutex_lock(l);
02353    for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02354       if (req->trid == ident) {
02355          /* remove from queue */
02356          if (!prev)
02357             *queue = req->next;
02358          else
02359             prev->next = req->next;
02360 
02361          /* send next pending command */
02362          if (*queue) {
02363             if (mgcpdebug) {
02364                ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 
02365                   ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02366             }
02367 
02368             mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02369          }
02370          break;
02371       }
02372    }
02373    ast_mutex_unlock(l);
02374    return req;
02375 }

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

Definition at line 1544 of file chan_mgcp.c.

References __ourip, mgcp_gateway::addr, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_ouraddrfor(), ast_verbose(), mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, 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().

01545 {
01546    struct mgcp_endpoint *p = NULL;
01547    struct mgcp_subchannel *sub = NULL;
01548    struct mgcp_gateway *g;
01549    char iabuf[INET_ADDRSTRLEN];
01550    char tmp[256] = "";
01551    char *at = NULL, *c;
01552    int found = 0;
01553    if (name) {
01554       strncpy(tmp, name, sizeof(tmp) - 1);
01555       at = strchr(tmp, '@');
01556       if (!at) {
01557          ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01558          return NULL;
01559       }
01560       *at = '\0';
01561       at++;
01562    }
01563    ast_mutex_lock(&gatelock);
01564    if (at && (at[0] == '[')) {
01565       at++;
01566       c = strrchr(at, ']');
01567       if (c)
01568          *c = '\0';
01569    }
01570    g = gateways;
01571    while(g) {
01572       if ((!name || !strcasecmp(g->name, at)) && 
01573           (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01574          /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
01575          if (sin && g->dynamic && name) {
01576             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01577                (g->addr.sin_port != sin->sin_port)) {
01578                memcpy(&g->addr, sin, sizeof(g->addr));
01579                if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01580                   memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01581                if (option_verbose > 2)
01582                   ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(iabuf, sizeof(iabuf), g->addr.sin_addr), ntohs(g->addr.sin_port));
01583             }
01584          }
01585          /* SC: not dynamic, check if the name matches */
01586          else if (name) {
01587             if (strcasecmp(g->name, at)) {
01588                g = g->next;
01589                continue;
01590             }
01591          }
01592          /* SC: not dynamic, no name, check if the addr matches */
01593          else if (!name && sin) {
01594             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01595                 (g->addr.sin_port != sin->sin_port)) {
01596                g = g->next;
01597                continue;
01598             }
01599          } else {
01600             g = g->next;
01601             continue;
01602          }
01603          /* SC */
01604          p = g->endpoints;
01605          while(p) {
01606             if (option_debug)
01607                ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
01608                   p->name, g->name);
01609             if (msgid) {
01610 #if 0 /* SC: new transport mech */
01611                sub = p->sub;
01612                do {
01613                   if (option_debug)
01614                      ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01615                         p->name, g->name, sub->id, msgid);
01616                   if (sub->lastout == msgid) {
01617                      if (option_debug)
01618                         ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01619                            sub->id, msgid, sub->lastout);
01620                      found = 1;
01621                      break;
01622                   }
01623                   sub = sub->next;
01624                } while (sub != p->sub);
01625                if (found) {
01626                   break;
01627                }
01628 #endif
01629                /* SC */
01630                sub = p->sub;
01631                found = 1;
01632                /* SC */
01633                break;
01634             } else if (name && !strcasecmp(p->name, tmp)) {
01635                ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
01636                   p->name, g->name, p->sub->id);
01637                sub = p->sub;
01638                found = 1;
01639                break;
01640             }
01641             p = p->next;
01642          }
01643          if (sub && found) {
01644             ast_mutex_lock(&sub->lock);
01645             break;
01646          }
01647       }
01648       g = g->next;
01649    }
01650    ast_mutex_unlock(&gatelock);
01651    if (!sub) {
01652       if (name) {
01653          if (g)
01654             ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01655          else
01656             ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01657       } 
01658    }
01659    return sub;
01660 }

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

Definition at line 1523 of file chan_mgcp.c.

References s.

Referenced by handle_response().

01524 {
01525    char *s;
01526 
01527    *next = NULL, *len = 0;
01528    if (!c) return NULL;
01529 
01530    while (*c && (*c < 33 || *c == ','))
01531       c++;
01532 
01533    s = c;
01534    while (*c && (*c >= 33 && *c != ','))
01535       c++, (*len)++;
01536    *next = c;
01537 
01538    if (*len == 0)
01539       s = NULL, *next = NULL;
01540 
01541    return s;
01542 }

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

Definition at line 1516 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(), func_header_read(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), gettag(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_invite(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), 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_getheader(), sip_sipredirect(), sipsock_read(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), and transmit_state_notify().

01517 {
01518    int start = 0;
01519    return __get_header(req, name, &start);
01520 }

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

Definition at line 1468 of file chan_mgcp.c.

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

Referenced by process_sdp().

01469 {
01470    int x;
01471    int len = strlen(name);
01472    char *r;
01473 
01474    for (x=0; x<req->lines; x++) {
01475       r = get_sdp_by_line(req->line[x], name, len);
01476       if (r[0] != '\0') return r;
01477    }
01478    return "";
01479 }

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

Definition at line 1458 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01459 {
01460    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01461       char* r = line + nameLen + 1;
01462       while (*r && (*r < 33)) ++r;
01463       return r;
01464    }
01465    return "";
01466 }

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

Definition at line 1486 of file chan_mgcp.c.

References get_sdp_by_line(), and mgcp_request::line.

Referenced by process_sdp().

01487 {
01488    int len = strlen(name);
01489    char *r;
01490    while (*iterator < req->lines) {
01491       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01492       if (r[0] != '\0') return r;
01493    }
01494    return "";
01495 }

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

Definition at line 2881 of file chan_mgcp.c.

References ast_bridged_channel(), AST_CONTROL_ANSWER, ast_hangup(), ast_log(), ast_moh_stop(), ast_pthread_create, AST_STATE_DOWN, AST_STATE_RING, mgcp_subchannel::cxmode, 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().

02882 {
02883    struct mgcp_endpoint *p = sub->parent;
02884    struct ast_channel *c;
02885    pthread_t t;
02886    pthread_attr_t attr;
02887    pthread_attr_init(&attr);
02888    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);   
02889 
02890    /* Off hook / answer */
02891    if (sub->outgoing) {
02892       /* Answered */
02893       if (sub->owner) {
02894          if (ast_bridged_channel(sub->owner)) {
02895             ast_moh_stop(ast_bridged_channel(sub->owner));
02896          }
02897          sub->cxmode = MGCP_CX_SENDRECV;
02898          if (!sub->rtp) {
02899             start_rtp(sub);
02900          } else {
02901             transmit_modify_request(sub);
02902          }
02903          /*transmit_notify_request(sub, "aw");*/
02904          transmit_notify_request(sub, "");
02905          mgcp_queue_control(sub, AST_CONTROL_ANSWER);
02906       }
02907    } else {
02908       /* Start switch */
02909       /*sub->cxmode = MGCP_CX_SENDRECV;*/
02910       if (!sub->owner) {
02911          if (!sub->rtp) {
02912             start_rtp(sub);
02913          } else {
02914             transmit_modify_request(sub);
02915          }
02916          if (p->immediate) {
02917             /* The channel is immediately up. Start right away */
02918 #ifdef DLINK_BUGGY_FIRMWARE   
02919             transmit_notify_request(sub, "rt");
02920 #else
02921             transmit_notify_request(sub, "G/rt");
02922 #endif      
02923             c = mgcp_new(sub, AST_STATE_RING);
02924             if (!c) {
02925                ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
02926                transmit_notify_request(sub, "G/cg");
02927                ast_hangup(c);
02928             }
02929          } else {
02930             if (has_voicemail(p)) {
02931                transmit_notify_request(sub, "L/sl");
02932             } else {
02933                transmit_notify_request(sub, "L/dl");
02934             }
02935             c = mgcp_new(sub, AST_STATE_DOWN);
02936             if (c) {
02937                if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
02938                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
02939                   ast_hangup(c);
02940                }
02941             } else {
02942                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
02943             }
02944          }
02945       } else {
02946          if (p->hookstate == MGCP_OFFHOOK) {
02947             ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
02948          } else {
02949             ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
02950             ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
02951          }
02952          if (ast_bridged_channel(sub->owner)) {
02953             ast_moh_stop(ast_bridged_channel(sub->owner));
02954          }
02955          sub->cxmode = MGCP_CX_SENDRECV;
02956          if (!sub->rtp) {
02957             start_rtp(sub);
02958          } else {
02959             transmit_modify_request(sub);
02960          }
02961          /*transmit_notify_request(sub, "aw");*/
02962          transmit_notify_request(sub, "");
02963          /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
02964       }
02965    }
02966 }

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

Definition at line 2968 of file chan_mgcp.c.

References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, AST_STATE_UP, ast_verbose(), attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, ast_frame::frametype, 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, ast_frame::src, mgcp_endpoint::sub, ast_frame::subclass, 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(), and sipsock_read().

02969 {
02970    char *ev, *s;
02971    struct ast_frame f = { 0, };
02972    struct mgcp_endpoint *p = sub->parent;
02973    struct mgcp_gateway *g = NULL;
02974    char iabuf[INET_ADDRSTRLEN];
02975    int res;
02976 
02977    if (mgcpdebug) {
02978       ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
02979    }
02980    /* Clear out potential response */
02981    if (!strcasecmp(req->verb, "RSIP")) {
02982       /* Test if this RSIP request is just a keepalive */
02983       if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
02984          if (option_verbose > 2)
02985             ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
02986          transmit_response(sub, "200", req, "OK");
02987       } else {
02988          dump_queue(p->parent, p);
02989          dump_cmd_queues(p, NULL);
02990          
02991          if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
02992             ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
02993          }
02994          /* JS: For RSIP on wildcard we reset all endpoints */
02995          if (!strcmp(p->name, p->parent->wcardep)) {
02996             /* Reset all endpoints */
02997             struct mgcp_endpoint *tmp_ep;
02998             
02999             g = p->parent;
03000             tmp_ep = g->endpoints;
03001             while (tmp_ep) {
03002                /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
03003                if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03004                   struct mgcp_subchannel *tmp_sub, *first_sub;
03005                   if (option_verbose > 2) {
03006                      ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03007                   }
03008                   
03009                   first_sub = tmp_ep->sub;
03010                   tmp_sub = tmp_ep->sub;
03011                   while (tmp_sub) {
03012                      mgcp_queue_hangup(tmp_sub);
03013                      tmp_sub = tmp_sub->next;
03014                      if (tmp_sub == first_sub)
03015                         break;
03016                   }
03017                }
03018                tmp_ep = tmp_ep->next;
03019             }
03020          } else if (sub->owner) {
03021             mgcp_queue_hangup(sub);
03022          }
03023          transmit_response(sub, "200", req, "OK");
03024          /* JS: We dont send NTFY or AUEP to wildcard ep */
03025          if (strcmp(p->name, p->parent->wcardep) != 0) {
03026             transmit_notify_request(sub, "");
03027             /* SC: Audit endpoint. 
03028              Idea is to prevent lost lines due to race conditions 
03029             */
03030             transmit_audit_endpoint(p);
03031          }
03032       }
03033    } else if (!strcasecmp(req->verb, "NTFY")) {
03034       /* Acknowledge and be sure we keep looking for the same things */
03035       transmit_response(sub, "200", req, "OK");
03036       /* Notified of an event */
03037       ev = get_header(req, "O");
03038       s = strchr(ev, '/');
03039       if (s) ev = s + 1;
03040       ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03041       /* Keep looking for events unless this was a hangup */
03042       if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03043          transmit_notify_request(sub, p->curtone);
03044       }
03045       if (!strcasecmp(ev, "hd")) {
03046          p->hookstate = MGCP_OFFHOOK;
03047          sub->cxmode = MGCP_CX_SENDRECV;
03048          handle_hd_hf(sub, ev);
03049       } else if (!strcasecmp(ev, "hf")) {
03050          /* We can assume we are offhook if we received a hookflash */
03051          /* First let's just do call wait and ignore threeway */
03052          /* We're currently in charge */
03053          if (p->hookstate != MGCP_OFFHOOK) {
03054             /* Cisco c7940 sends hf even if the phone is onhook */
03055             /* Thanks to point on IRC for pointing this out */
03056             return -1;
03057          }
03058          /* do not let * conference two down channels */  
03059          if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03060             return -1;
03061 
03062          if (p->callwaiting || p->transfer || p->threewaycalling) {
03063             if (option_verbose > 2) {
03064                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);
03065             }
03066             p->sub = p->sub->next;
03067 
03068             /* transfer control to our next subchannel */
03069             if (!sub->next->owner) {
03070                /* plave the first call on hold and start up a new call */
03071                sub->cxmode = MGCP_CX_MUTE;
03072                if (option_verbose > 2) {
03073                   ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03074                }
03075                transmit_modify_request(sub);
03076                if (sub->owner && ast_bridged_channel(sub->owner)) {
03077                   ast_moh_start(ast_bridged_channel(sub->owner), NULL);
03078                }
03079                sub->next->cxmode = MGCP_CX_RECVONLY;
03080                handle_hd_hf(sub->next, ev);
03081             } else if (sub->owner && sub->next->owner) {
03082                /* We've got two active calls lets decide whether or not to conference or just flip flop */
03083                if ((!sub->outgoing) && (!sub->next->outgoing)) {
03084                   /* We made both calls lets conferenct */
03085                   if (option_verbose > 2) {
03086                      ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n", 
03087                         sub->id, sub->next->id, p->name, p->parent->name);
03088                   }
03089                   sub->cxmode = MGCP_CX_CONF;
03090                   sub->next->cxmode = MGCP_CX_CONF;
03091                   if (ast_bridged_channel(sub->next->owner)) 
03092                      ast_moh_stop(ast_bridged_channel(sub->next->owner));
03093                   transmit_modify_request(sub);
03094                   transmit_modify_request(sub->next);
03095                } else {
03096                   /* Let's flipflop between calls */
03097                   /* XXX Need to check for state up ??? */
03098                   /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
03099                   if (option_verbose > 2) {
03100                      ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 
03101                         sub->id, sub->next->id, p->name, p->parent->name);
03102                   }
03103                   sub->cxmode = MGCP_CX_MUTE;
03104                   if (option_verbose > 2) {
03105                      ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03106                   }
03107                   transmit_modify_request(sub);
03108                   if (ast_bridged_channel(sub->owner)) 
03109                      ast_moh_start(ast_bridged_channel(sub->owner), NULL);
03110                         
03111                   if (ast_bridged_channel(sub->next->owner)) 
03112                      ast_moh_stop(ast_bridged_channel(sub->next->owner));
03113                         
03114                   handle_hd_hf(sub->next, ev);
03115 #if 0
03116                   if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) {
03117                      handle_hd_hf(sub->next, ev);
03118                   } else {
03119                      ast_verbose(VERBOSE_PREFIX_3 "MGCP Unmuting %d on %s@%s\n", sub->next->id, p->name, p->parent->name);
03120                      sub->next->cxmode = MGCP_CX_SENDRECV;
03121                      transmit_modify_request(sub->next);
03122                   }
03123 #endif
03124                }
03125             } else {
03126                /* We've most likely lost one of our calls find an active call and bring it up */
03127                if (sub->owner) {
03128                   p->sub = sub;
03129                } else if (sub->next->owner) {
03130                   p->sub = sub->next;
03131                } else {
03132                   /* We seem to have lost both our calls */
03133                   /* XXX - What do we do now? */
03134                   return -1;
03135                }
03136                if (ast_bridged_channel(p->sub->owner)) {
03137                   ast_moh_stop(ast_bridged_channel(p->sub->owner));
03138                }
03139                p->sub->cxmode = MGCP_CX_SENDRECV;
03140                transmit_modify_request(p->sub);
03141             }
03142          } else {
03143             ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 
03144                p->name, p->parent->name);
03145          }
03146          /*ast_moh_stop(sub->owner->bridge);*/
03147       } else if (!strcasecmp(ev, "hu")) {
03148          p->hookstate = MGCP_ONHOOK;
03149          sub->cxmode = MGCP_CX_RECVONLY;
03150          ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03151          /* JS: Do we need to send MDCX before a DLCX ?
03152          if (sub->rtp) {
03153             transmit_modify_request(sub);
03154          }
03155          */
03156          if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03157             /* We're allowed to transfer, we have two avtive calls and */
03158             /* we made at least one of the calls.  Let's try and transfer */
03159             ast_mutex_lock(&p->sub->next->lock);
03160             res = attempt_transfer(p);
03161             if (res < 0) {
03162                if (p->sub->next->owner) {
03163                   sub->next->alreadygone = 1;
03164                   mgcp_queue_hangup(sub->next);
03165                }
03166             } else if (res) {
03167                ast_log(LOG_WARNING, "Transfer attempt failed\n");
03168                ast_mutex_unlock(&p->sub->next->lock);
03169                return -1;
03170             }
03171             ast_mutex_unlock(&p->sub->next->lock);
03172          } else {
03173             /* Hangup the current call */
03174             /* If there is another active call, mgcp_hangup will ring the phone with the other call */
03175             if (sub->owner) {
03176                sub->alreadygone = 1;
03177                mgcp_queue_hangup(sub);
03178             } else {
03179                /* SC: verbose level check */
03180                if (option_verbose > 2) {
03181                   ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03182                      p->name, p->parent->name, sub->id);
03183                }
03184                /* Instruct the other side to remove the connection since it apparently *
03185                 * still thinks the channel is active. *
03186                 * For Cisco IAD2421 /BAK/ */
03187                transmit_connection_del(sub);
03188             }
03189          }
03190          if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03191             p->hidecallerid = 0;
03192             if (p->hascallwaiting && !p->callwaiting) {
03193                if (option_verbose > 2)
03194                   ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03195                p->callwaiting = -1;
03196             }
03197             if (has_voicemail(p)) {
03198                if (option_verbose > 2) {
03199                   ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03200                }
03201                transmit_notify_request(sub, "L/vmwi(+)");
03202             } else {
03203                if (option_verbose > 2) {
03204                   ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03205                }
03206                transmit_notify_request(sub, "L/vmwi(-)");
03207             }
03208          }
03209       } else if ((strlen(ev) == 1) && 
03210             (((ev[0] >= '0') && (ev[0] <= '9')) ||
03211              ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03212               (ev[0] == '*') || (ev[0] == '#'))) {
03213          f.frametype = AST_FRAME_DTMF;
03214          f.subclass = ev[0];
03215          f.src = "mgcp";
03216          if (sub->owner) {
03217             /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
03218             mgcp_queue_frame(sub, &f);
03219             ast_mutex_lock(&sub->next->lock);
03220             if (sub->next->owner) {
03221                mgcp_queue_frame(sub->next, &f);
03222             }
03223             ast_mutex_unlock(&sub->next->lock);
03224          }
03225          if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
03226             memset(p->curtone, 0, sizeof(p->curtone));
03227          }
03228       } else if (!strcasecmp(ev, "T")) {
03229          /* Digit timeout -- unimportant */
03230       } else if (!strcasecmp(ev, "ping")) {
03231          /* ping -- unimportant */
03232       } else {
03233          ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03234       }
03235    } else {
03236       ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr));
03237       transmit_response(sub, "510", req, "Unknown verb");
03238    }
03239    return 0;
03240 }

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

References 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, mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), n, 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().

02380 {
02381    char *c;
02382    struct mgcp_request *req;
02383    struct mgcp_gateway *gw = p->parent;
02384 
02385    if (result < 200) {
02386       /* provisional response */
02387       return;
02388    }
02389 
02390    if (p->slowsequence) 
02391       req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02392    else if (sub)
02393       req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02394    else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02395       req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02396 
02397    if (!req) {
02398       if (option_verbose > 2) {
02399          ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n", 
02400             gw->name, ident);
02401       }
02402       return;
02403    }
02404 
02405    if (p && (result >= 400) && (result <= 599)) {
02406       switch (result) {
02407       case 401:
02408          p->hookstate = MGCP_OFFHOOK;
02409          break;
02410       case 402:
02411          p->hookstate = MGCP_ONHOOK;
02412          break;
02413       case 406:
02414          ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02415          break;
02416       case 407:
02417          ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02418          break;
02419       }
02420       if (sub) {
02421          if (sub->owner) {
02422             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
02423                result, p->name, p->parent->name, sub ? sub->id:-1);
02424             mgcp_queue_hangup(sub);
02425          }
02426       } else {
02427          if (p->sub->next->owner) {
02428             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
02429                result, p->name, p->parent->name, sub ? sub->id:-1);
02430             mgcp_queue_hangup(p->sub);
02431          }
02432 
02433          if (p->sub->owner) {
02434             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
02435                result, p->name, p->parent->name, sub ? sub->id:-1);
02436             mgcp_queue_hangup(p->sub);
02437          }
02438 
02439          dump_cmd_queues(p, NULL);
02440       }
02441    }
02442 
02443    if (resp) {
02444       if (req->cmd == MGCP_CMD_CRCX) {
02445          if ((c = get_header(resp, "I"))) {
02446             if (!ast_strlen_zero(c) && sub) {
02447                /* SC: if we are hanging up do not process this conn. */
02448                if (sub->owner) {
02449                   if (!ast_strlen_zero(sub->cxident)) {
02450                      if (strcasecmp(c, sub->cxident)) {
02451                         ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02452                      }
02453                   }
02454                   strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
02455                   if (sub->tmpdest.sin_addr.s_addr) {
02456                      transmit_modify_with_sdp(sub, NULL, 0);
02457                   }
02458                } else {
02459                   /* XXX SC: delete this one
02460                      callid and conn id may already be lost. 
02461                      so the following del conn may have a side effect of 
02462                      cleaning up the next subchannel */
02463                   transmit_connection_del(sub);
02464                }
02465             }
02466          }
02467       }
02468 
02469       if (req->cmd == MGCP_CMD_AUEP) {
02470          /* SC: check stale connection ids */
02471          if ((c = get_header(resp, "I"))) {
02472             char *v, *n;
02473             int len;
02474             while ((v = get_csv(c, &len, &n))) {
02475                if (len) {
02476                   if (strncasecmp(v, p->sub->cxident, len) &&
02477                       strncasecmp(v, p->sub->next->cxident, len)) {
02478                      /* connection id not found. delete it */
02479                      char cxident[80] = "";
02480 
02481                      if (len > (sizeof(cxident) - 1))
02482                         len = sizeof(cxident) - 1;
02483                      ast_copy_string(cxident, v, len);
02484                      if (option_verbose > 2) {
02485                         ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n", 
02486                                cxident, p->name, gw->name);
02487                      }
02488                      transmit_connection_del_w_params(p, NULL, cxident);
02489                   }
02490                }
02491                c = n;
02492             }
02493          }
02494 
02495          /* Try to determine the hookstate returned from an audit endpoint command */
02496          if ((c = get_header(resp, "ES"))) {
02497             if (!ast_strlen_zero(c)) {
02498                if (strstr(c, "hu")) {
02499                   if (p->hookstate != MGCP_ONHOOK) {
02500                      /* SC: XXX cleanup if we think we are offhook XXX */
02501                      if ((p->sub->owner || p->sub->next->owner ) && 
02502                          p->hookstate == MGCP_OFFHOOK)
02503                         mgcp_queue_hangup(sub);
02504                      p->hookstate = MGCP_ONHOOK;
02505 
02506                      /* SC: update the requested events according to the new hookstate */
02507                      transmit_notify_request(p->sub, "");
02508 
02509                      /* SC: verbose level check */
02510                      if (option_verbose > 2) {
02511                         ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02512                      }
02513                   }
02514                } else if (strstr(c, "hd")) {
02515                   if (p->hookstate != MGCP_OFFHOOK) {
02516                      p->hookstate = MGCP_OFFHOOK;
02517 
02518                      /* SC: update the requested events according to the new hookstate */
02519                      transmit_notify_request(p->sub, "");
02520 
02521                      /* SC: verbose level check */
02522                      if (option_verbose > 2) {
02523                         ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02524                      }
02525                   }
02526                }
02527             }
02528          }
02529       }
02530 
02531       if (resp && resp->lines) {
02532          /* SC: do not process sdp if we are hanging up. this may be a late response */
02533          if (sub && sub->owner) {
02534             if (!sub->rtp)
02535                start_rtp(sub);
02536             if (sub->rtp)
02537                process_sdp(sub, resp);
02538          }
02539       }
02540    }
02541 
02542    free(req);
02543 }

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

Definition at line 517 of file chan_mgcp.c.

References ast_app_has_voicemail(), and mgcp_endpoint::mailbox.

Referenced by do_housekeeping(), do_monitor(), forward_message(), handle_hd_hf(), handle_init_event(), handle_request(), has_voicemail(), load_module(), mgcp_hangup(), mgcp_request(), vm_execmain(), and zt_handle_event().

00518 {
00519    return ast_app_has_voicemail(p->mailbox, NULL);
00520 }

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

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

01912 {
01913    /* Initialize a response */
01914    if (req->headers || req->len) {
01915       ast_log(LOG_WARNING, "Request already initialized?!?\n");
01916       return -1;
01917    }
01918    req->header[req->headers] = req->data + req->len;
01919    /* SC: check if we need brackets around the gw name */
01920    if (p->parent->isnamedottedip)
01921       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);
01922    else
01923       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);
01924    req->len += strlen(req->header[req->headers]);
01925    if (req->headers < MGCP_MAX_HEADERS)
01926       req->headers++;
01927    else
01928       ast_log(LOG_WARNING, "Out of header space\n");
01929    return 0;
01930 }

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

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

01895 {
01896    /* Initialize a response */
01897    if (req->headers || req->len) {
01898       ast_log(LOG_WARNING, "Request already initialized?!?\n");
01899       return -1;
01900    }
01901    req->header[req->headers] = req->data + req->len;
01902    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
01903    req->len += strlen(req->header[req->headers]);
01904    if (req->headers < MGCP_MAX_HEADERS)
01905       req->headers++;
01906    else
01907       ast_log(LOG_WARNING, "Out of header space\n");
01908    return 0;
01909 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 4382 of file chan_mgcp.c.

References ASTERISK_GPL_KEY.

04383 {
04384    return ASTERISK_GPL_KEY;
04385 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 4246 of file chan_mgcp.c.

References ast_channel_register(), ast_cli_register(), ast_log(), ast_rtp_proto_register(), cli_audit_endpoint, cli_debug, cli_mgcp_reload, cli_no_debug, cli_show_endpoints, io, io_context_create(), LOG_ERROR, LOG_WARNING, mgcp_rtp, mgcp_tech, reload_config(), restart_monitor(), sched_context_create(), and type.

04247 {
04248    int res;
04249 
04250    sched = sched_context_create();
04251    if (!sched) {
04252       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04253       return -1;
04254    }
04255    io = io_context_create();
04256    if (!io) {
04257       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04258       return -1;
04259    }
04260 
04261    if (!(res = reload_config())) {
04262       /* Make sure we can register our mgcp channel type */
04263       if (ast_channel_register(&mgcp_tech)) {
04264          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
04265          return -1;
04266       }
04267       ast_rtp_proto_register(&mgcp_rtp);
04268       ast_cli_register(&cli_show_endpoints);
04269       ast_cli_register(&cli_audit_endpoint);
04270       ast_cli_register(&cli_debug);
04271       ast_cli_register(&cli_no_debug);
04272       ast_cli_register(&cli_mgcp_reload);
04273 
04274       /* And start the monitor for the first time */
04275       restart_monitor();
04276    }
04277 
04278    return res;
04279 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

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

01184 {
01185    int res = 0;
01186    struct mgcp_subchannel *sub = ast->tech_pvt;
01187    struct mgcp_endpoint *p = sub->parent;
01188 
01189    ast_mutex_lock(&sub->lock);
01190    sub->cxmode = MGCP_CX_SENDRECV;
01191    if (!sub->rtp) {
01192       start_rtp(sub);
01193    } else {
01194       transmit_modify_request(sub);
01195    }
01196    /* SC: verbose level check */
01197    if (option_verbose > 2) {
01198       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n", 
01199          ast->name, p->name, p->parent->name, sub->id);
01200    }
01201    if (ast->_state != AST_STATE_UP) {
01202       ast_setstate(ast, AST_STATE_UP);
01203       if (option_debug)
01204          ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
01205       transmit_notify_request(sub, "");
01206       transmit_modify_request(sub);
01207    }
01208    ast_mutex_unlock(&sub->lock);
01209    return res;
01210 }

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

Definition at line 1122 of file chan_mgcp.c.

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

01123 {
01124    struct mgcp_gateway  *g;
01125    struct mgcp_endpoint *e;
01126    int found = 0;
01127    char *ename,*gname, *c;
01128 
01129    if (!mgcpdebug) {
01130       return RESULT_SHOWUSAGE;
01131    }
01132    if (argc != 4) 
01133       return RESULT_SHOWUSAGE;
01134    /* split the name into parts by null */
01135    ename = argv[3];
01136    gname = ename;
01137    while (*gname) {
01138       if (*gname == '@') {
01139          *gname = 0;
01140          gname++;
01141          break;
01142       }
01143       gname++;
01144    }
01145    if (gname[0] == '[')
01146       gname++;
01147    if ((c = strrchr(gname, ']')))
01148       *c = '\0';
01149    ast_mutex_lock(&gatelock);
01150    g = gateways;
01151    while(g) {
01152       if (!strcasecmp(g->name, gname)) {
01153          e = g->endpoints;
01154          while(e) {
01155             if (!strcasecmp(e->name, ename)) {
01156                found = 1;
01157                transmit_audit_endpoint(e);
01158                break;
01159             }
01160             e = e->next;
01161          }
01162          if (found) {
01163             break;
01164          }
01165       }
01166       g = g->next;
01167    }
01168    if (!found) {
01169       ast_cli(fd, "   << Could not find endpoint >>     ");
01170    }
01171    ast_mutex_unlock(&gatelock);
01172    return RESULT_SUCCESS;
01173 }

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

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

00887 {
00888    int res;
00889    struct mgcp_endpoint *p;
00890    struct mgcp_subchannel *sub;
00891    char tone[50] = "";
00892    char *distinctive_ring = NULL;
00893    struct varshead *headp;
00894    struct ast_var_t *current;
00895 
00896    if (mgcpdebug) {
00897       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
00898    }
00899    sub = ast->tech_pvt;
00900    p = sub->parent;
00901    headp = &ast->varshead;
00902    AST_LIST_TRAVERSE(headp,current,entries) {
00903       /* Check whether there is an ALERT_INFO variable */
00904       if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
00905          distinctive_ring = ast_var_value(current);
00906       }
00907    }
00908 
00909    ast_mutex_lock(&sub->lock);
00910    switch (p->hookstate) {
00911    case MGCP_OFFHOOK:
00912       if (!ast_strlen_zero(distinctive_ring)) {
00913          snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
00914          if (mgcpdebug) {
00915             ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);
00916          }
00917       } else {
00918          snprintf(tone, sizeof(tone), "L/wt");
00919          if (mgcpdebug) {
00920             ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);
00921          }
00922       }
00923       break;
00924    case MGCP_ONHOOK:
00925    default:
00926       if (!ast_strlen_zero(distinctive_ring)) {
00927          snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
00928          if (mgcpdebug) {
00929             ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);
00930          }
00931       } else {
00932          snprintf(tone, sizeof(tone), "L/rg");
00933          if (mgcpdebug) {
00934             ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");
00935          }
00936       }
00937       break;
00938    }
00939 
00940    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00941       ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
00942       ast_mutex_unlock(&sub->lock);
00943       return -1;
00944    }
00945 
00946    res = 0;
00947    sub->outgoing = 1;
00948    sub->cxmode = MGCP_CX_RECVONLY;
00949    if (p->type == TYPE_LINE) {
00950       if (!sub->rtp) {
00951          start_rtp(sub);
00952       } else {
00953          transmit_modify_request(sub);
00954       }
00955 
00956       if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00957          /* try to prevent a callwait from disturbing the other connection */
00958          sub->next->cxmode = MGCP_CX_RECVONLY;
00959          transmit_modify_request(sub->next);
00960       }
00961 
00962       transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
00963       ast_setstate(ast, AST_STATE_RINGING);
00964 
00965       if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00966          /* Put the connection back in sendrecv */
00967          sub->next->cxmode = MGCP_CX_SENDRECV;
00968          transmit_modify_request(sub->next);
00969       }
00970    } else {
00971       ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
00972       res = -1;
00973    }
00974    ast_mutex_unlock(&sub->lock);
00975    ast_queue_control(ast, AST_CONTROL_RINGING);
00976    return res;
00977 }

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

Definition at line 3941 of file chan_mgcp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03942 {
03943    if (argc != 2)
03944       return RESULT_SHOWUSAGE;
03945    mgcpdebug = 1;
03946    ast_cli(fd, "MGCP Debugging Enabled\n");
03947    return RESULT_SUCCESS;
03948 }

static int mgcp_do_reload ( void   )  [static]

Definition at line 4281 of file chan_mgcp.c.

References reload_config().

Referenced by do_monitor().

04282 {
04283    reload_config();
04284    return 0;
04285 }

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

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

01285 {
01286    struct mgcp_subchannel *sub = newchan->tech_pvt;
01287 
01288    ast_mutex_lock(&sub->lock);
01289    ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01290    if (sub->owner != oldchan) {
01291       ast_mutex_unlock(&sub->lock);
01292       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01293       return -1;
01294    }
01295    sub->owner = newchan;
01296    ast_mutex_unlock(&sub->lock);
01297    return 0;
01298 }

static struct ast_rtp* mgcp_get_rtp_peer ( struct ast_channel chan  )  [static]

Definition at line 3914 of file chan_mgcp.c.

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

03915 {
03916    struct mgcp_subchannel *sub;
03917    sub = chan->tech_pvt;
03918    if (sub && sub->rtp && sub->parent->canreinvite)
03919       return sub->rtp;
03920    return NULL;
03921 }

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 979 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_dsp_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_update_use_count(), 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::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(), usecnt, usecnt_lock, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

00980 {
00981    struct mgcp_subchannel *sub = ast->tech_pvt;
00982    struct mgcp_endpoint *p = sub->parent;
00983 
00984    if (option_debug) {
00985       ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
00986    }
00987    if (!ast->tech_pvt) {
00988       ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
00989       return 0;
00990    }
00991    if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00992       ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
00993       return 0;
00994    }
00995    ast_mutex_lock(&sub->lock);
00996    if (mgcpdebug) {
00997       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00998    }
00999 
01000    if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
01001       /* SC: check whether other channel is active. */
01002       if (!sub->next->owner) {
01003          if (p->dtmfmode & MGCP_DTMF_HYBRID)
01004             p->dtmfmode &= ~MGCP_DTMF_INBAND;
01005          if (mgcpdebug) {
01006             ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
01007          }
01008          ast_dsp_free(p->dsp);
01009          p->dsp = NULL;
01010       }
01011    }
01012 
01013    sub->owner = NULL;
01014    if (!ast_strlen_zero(sub->cxident)) {
01015       transmit_connection_del(sub);
01016    }
01017    sub->cxident[0] = '\0';
01018    if ((sub == p->sub) && sub->next->owner) {
01019       if (p->hookstate == MGCP_OFFHOOK) {
01020          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
01021             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);
01022          }
01023       } else {
01024          /* set our other connection as the primary and swith over to it */
01025          p->sub = sub->next;
01026          p->sub->cxmode = MGCP_CX_RECVONLY;
01027          transmit_modify_request(p->sub);
01028          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
01029             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);
01030          }
01031       }
01032 
01033    } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
01034       transmit_notify_request(sub, "L/v");
01035    } else if (p->hookstate == MGCP_OFFHOOK) {
01036       transmit_notify_request(sub, "L/ro");
01037    } else {
01038       transmit_notify_request(sub, "");
01039    }
01040 
01041    ast->tech_pvt = NULL;
01042    sub->alreadygone = 0;
01043    sub->outgoing = 0;
01044    sub->cxmode = MGCP_CX_INACTIVE;
01045    sub->callid[0] = '\0';
01046    /* Reset temporary destination */
01047    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
01048    if (sub->rtp) {
01049       ast_rtp_destroy(sub->rtp);
01050       sub->rtp = NULL;
01051    }
01052 
01053    /* SC: Decrement use count */
01054    ast_mutex_lock(&usecnt_lock);
01055    usecnt--;
01056    ast_mutex_unlock(&usecnt_lock);
01057    ast_update_use_count();
01058    /* SC: Decrement use count */
01059 
01060    if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
01061       p->hidecallerid = 0;
01062       if (p->hascallwaiting && !p->callwaiting) {
01063          if (option_verbose > 2)
01064             ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
01065          p->callwaiting = -1;
01066       }
01067       if (has_voicemail(p)) {
01068          if (mgcpdebug) {
01069             ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 
01070                ast->name, p->name, p->parent->name);
01071          }
01072          transmit_notify_request(sub, "L/vmwi(+)");
01073       } else {
01074          if (mgcpdebug) {
01075             ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 
01076                ast->name, p->name, p->parent->name);
01077          }
01078          transmit_notify_request(sub, "L/vmwi(-)");
01079       }
01080    }
01081    ast_mutex_unlock(&sub->lock);
01082    return 0;
01083 }

static int mgcp_indicate ( struct ast_channel ast,
int  ind 
) [static]

Definition at line 1347 of file chan_mgcp.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_RINGING, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), control2str(), mgcp_subchannel::lock, LOG_WARNING, mgcpdebug, ast_channel::name, ast_channel::tech_pvt, transmit_notify_request(), and VERBOSE_PREFIX_3.

01348 {
01349    struct mgcp_subchannel *sub = ast->tech_pvt;
01350    int res = 0;
01351 
01352    if (mgcpdebug) {
01353       ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
01354          ind, control2str(ind), ast->name);
01355    }
01356    ast_mutex_lock(&sub->lock);
01357    switch(ind) {
01358    case AST_CONTROL_RINGING:
01359 #ifdef DLINK_BUGGY_FIRMWARE   
01360       transmit_notify_request(sub, "rt");
01361 #else
01362       transmit_notify_request(sub, "G/rt");
01363 #endif      
01364       break;
01365    case AST_CONTROL_BUSY:
01366       transmit_notify_request(sub, "L/bz");
01367       break;
01368    case AST_CONTROL_CONGESTION:
01369       transmit_notify_request(sub, "G/cg");
01370       break;
01371    case -1:
01372       transmit_notify_request(sub, "");
01373       break;      
01374    default:
01375       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01376       res = -1;
01377    }
01378    ast_mutex_unlock(&sub->lock);
01379    return res;
01380 }

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

Definition at line 1382 of file chan_mgcp.c.

References ast_channel::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_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtp_fd(), ast_setstate(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), ast_verbose(), mgcp_endpoint::call_forward, ast_channel::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_name, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, mgcp_endpoint::context, ast_channel::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DTMF_DETECT, mgcp_endpoint::dtmfmode, mgcp_endpoint::exten, ast_channel::exten, ast_channel::fds, fmt, mgcp_subchannel::id, ast_channel::language, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_tech, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::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, strdup, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, type, ast_channel::type, usecnt, usecnt_lock, VERBOSE_PREFIX_3, and ast_channel::writeformat.

Referenced by handle_hd_hf(), and mgcp_request().

01383 {
01384    struct ast_channel *tmp;
01385    struct mgcp_endpoint *i = sub->parent;
01386    int fmt;
01387 
01388    tmp = ast_channel_alloc(1);
01389    if (tmp) {
01390       tmp->tech = &mgcp_tech;
01391       tmp->nativeformats = i->capability;
01392       if (!tmp->nativeformats)
01393          tmp->nativeformats = capability;
01394       fmt = ast_best_codec(tmp->nativeformats);
01395       snprintf(tmp->name, sizeof(tmp->name), "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01396       if (sub->rtp)
01397          tmp->fds[0] = ast_rtp_fd(sub->rtp);
01398       tmp->type = type;
01399       if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01400          i->dsp = ast_dsp_new();
01401          ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
01402          /* SC: this is to prevent clipping of dtmf tones during dsp processing */
01403          ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01404       } else {
01405          i->dsp = NULL;
01406       }
01407       ast_setstate(tmp, state);
01408       if (state == AST_STATE_RING)
01409          tmp->rings = 1;
01410       tmp->writeformat = fmt;
01411       tmp->rawwriteformat = fmt;
01412       tmp->readformat = fmt;
01413       tmp->rawreadformat = fmt;
01414       tmp->tech_pvt = sub;
01415       if (!ast_strlen_zero(i->language))
01416          strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
01417       if (!ast_strlen_zero(i->accountcode))
01418          strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode)-1);
01419       if (i->amaflags)
01420          tmp->amaflags = i->amaflags;
01421       sub->owner = tmp;
01422       ast_mutex_lock(&usecnt_lock);
01423       usecnt++;
01424       ast_mutex_unlock(&usecnt_lock);
01425       ast_update_use_count();
01426       tmp->callgroup = i->callgroup;
01427       tmp->pickupgroup = i->pickupgroup;
01428       strncpy(tmp->call_forward, i->call_forward, sizeof(tmp->call_forward) - 1);
01429       strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
01430       strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
01431 
01432       if (!ast_strlen_zero(i->cid_num))
01433          tmp->cid.cid_num = strdup(i->cid_num);
01434       if (!ast_strlen_zero(i->cid_name))
01435          tmp->cid.cid_name = strdup(i->cid_name);
01436       
01437       if (!i->adsi)
01438          tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01439       tmp->priority = 1;
01440       if (state != AST_STATE_DOWN) {
01441          if (ast_pbx_start(tmp)) {
01442             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01443             ast_hangup(tmp);
01444             tmp = NULL;
01445          }
01446       }
01447       /* SC: verbose level check */
01448       if (option_verbose > 2) {
01449          ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01450             tmp->name, ast_state2str(state));
01451       }
01452    } else {
01453       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01454    }
01455    return tmp;
01456 }

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

Definition at line 3950 of file chan_mgcp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

03951 {
03952    if (argc != 3)
03953       return RESULT_SHOWUSAGE;
03954    mgcpdebug = 0;
03955    ast_cli(fd, "MGCP Debugging Disabled\n");
03956    return RESULT_SUCCESS;
03957 }

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

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

00736 {
00737    struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
00738    struct mgcp_message *cur;
00739    struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
00740    struct timeval tv;
00741 
00742    if (!msg) {
00743       return -1;
00744    }
00745    if (!gw) {
00746       return -1;
00747    }
00748 /* SC
00749    time(&t);
00750    if (gw->messagepending && (gw->lastouttime + 20 < t)) {
00751       ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
00752          gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
00753       dump_queue(sub->parent);
00754    }
00755 */
00756    msg->owner_sub = sub;
00757    msg->owner_ep = p;
00758    msg->seqno = seqno;
00759    msg->next = NULL;
00760    msg->len = len;
00761    msg->retrans = 0;
00762    memcpy(msg->buf, data, msg->len);
00763 
00764    ast_mutex_lock(&gw->msgs_lock);
00765    cur = gw->msgs;
00766    if (cur) {
00767       while(cur->next)
00768          cur = cur->next;
00769       cur->next = msg;
00770    } else {
00771       gw->msgs = msg;
00772    }
00773 
00774    if (gettimeofday(&tv, NULL) < 0) {
00775       /* This shouldn't ever happen, but let's be sure */
00776       ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
00777    } else {
00778       msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
00779 
00780       if (gw->retransid == -1)
00781          gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00782    }
00783    ast_mutex_unlock(&gw->msgs_lock);
00784 /* SC
00785    if (!gw->messagepending) {
00786       gw->messagepending = 1;
00787       gw->lastout = seqno;
00788       gw->lastouttime = t;
00789 */
00790    __mgcp_xmit(gw, msg->buf, msg->len);
00791       /* XXX Should schedule retransmission XXX */
00792 /* SC
00793    } else
00794       ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
00795 */
00796    return 0;
00797 }

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

Definition at line 665 of file chan_mgcp.c.

References AST_FRAME_CONTROL, mgcp_queue_frame(), and ast_frame::subclass.

Referenced by handle_hd_hf().

00666 {
00667    struct ast_frame f = { AST_FRAME_CONTROL, };
00668    f.subclass = control;
00669    return mgcp_queue_frame(sub, &f);
00670 }

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

Definition at line 629 of file chan_mgcp.c.

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

Referenced by handle_request(), and mgcp_queue_control().

00630 {
00631    for(;;) {
00632       if (sub->owner) {
00633          if (!ast_mutex_trylock(&sub->owner->lock)) {
00634             ast_queue_frame(sub->owner, f);
00635             ast_mutex_unlock(&sub->owner->lock);
00636             break;
00637          } else {
00638             ast_mutex_unlock(&sub->lock);
00639             usleep(1);
00640             ast_mutex_lock(&sub->lock);
00641          }
00642       } else
00643          break;
00644    }
00645 }

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

Definition at line 647 of file chan_mgcp.c.

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

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

00648 {
00649    for(;;) {
00650       if (sub->owner) {
00651          if (!ast_mutex_trylock(&sub->owner->lock)) {
00652             ast_queue_hangup(sub->owner);
00653             ast_mutex_unlock(&sub->owner->lock);
00654             break;
00655          } else {
00656             ast_mutex_unlock(&sub->lock);
00657             usleep(1);
00658             ast_mutex_lock(&sub->lock);
00659          }
00660       } else
00661          break;
00662    }
00663 }

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

Definition at line 1244 of file chan_mgcp.c.

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

01245 {
01246    struct ast_frame *f;
01247    struct mgcp_subchannel *sub = ast->tech_pvt;
01248    ast_mutex_lock(&sub->lock);
01249    f = mgcp_rtp_read(sub);
01250    ast_mutex_unlock(&sub->lock);
01251    return f;
01252 }

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

Definition at line 4287 of file chan_mgcp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), mgcp_reloading, and restart_monitor().

Referenced by reload(), and unload_module().

04288 {
04289    ast_mutex_lock(&mgcp_reload_lock);
04290    if (mgcp_reloading) {
04291       ast_verbose("Previous mgcp reload not yet done\n");
04292    } else
04293       mgcp_reloading = 1;
04294    ast_mutex_unlock(&mgcp_reload_lock);
04295    restart_monitor();
04296    return 0;
04297 }

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

Definition at line 3480 of file chan_mgcp.c.

References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, 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.

03481 {
03482    int oldformat;
03483    struct mgcp_subchannel *sub;
03484    struct ast_channel *tmpc = NULL;
03485    char tmp[256];
03486    char *dest = data;
03487 
03488    oldformat = format;
03489    format &= capability;
03490    if (!format) {
03491       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03492       return NULL;
03493    }
03494    strncpy(tmp, dest, sizeof(tmp) - 1);
03495    if (ast_strlen_zero(tmp)) {
03496       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03497       return NULL;
03498    }
03499    sub = find_subchannel_and_lock(tmp, 0, NULL);
03500    if (!sub) {
03501       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03502       *cause = AST_CAUSE_UNREGISTERED;
03503       return NULL;
03504    }
03505    
03506    if (option_verbose > 2) {
03507       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
03508       ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 
03509          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03510    }
03511    /* Must be busy */
03512    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03513       ((!sub->parent->callwaiting) && (sub->owner)) ||
03514        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03515       if (sub->parent->hookstate == MGCP_ONHOOK) {
03516          if (has_voicemail(sub->parent)) {
03517             transmit_notify_request(sub,"L/vmwi(+)");
03518          } else {
03519             transmit_notify_request(sub,"L/vmwi(-)");
03520          }
03521       }
03522       *cause = AST_CAUSE_BUSY;
03523       ast_mutex_unlock(&sub->lock);
03524       return NULL;
03525    }
03526    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03527    ast_mutex_unlock(&sub->lock);
03528    if (!tmpc)
03529       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03530    restart_monitor();
03531    return tmpc;
03532 }

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

Definition at line 1212 of file chan_mgcp.c.

References ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, ast_frame::frametype, 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, ast_frame::subclass, and ast_channel::writeformat.

Referenced by mgcp_read().

01213 {
01214    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
01215    struct ast_frame *f;
01216    static struct ast_frame null_frame = { AST_FRAME_NULL, };
01217 
01218    f = ast_rtp_read(sub->rtp);
01219    /* Don't send RFC2833 if we're not supposed to */
01220    if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01221       return &null_frame;
01222    if (sub->owner) {
01223       /* We already hold the channel lock */
01224       if (f->frametype == AST_FRAME_VOICE) {
01225          if (f->subclass != sub->owner->nativeformats) {
01226             ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01227             sub->owner->nativeformats = f->subclass;
01228             ast_set_read_format(sub->owner, sub->owner->readformat);
01229             ast_set_write_format(sub->owner, sub->owner->writeformat);
01230          }
01231          /* Courtesy fearnor aka alex@pilosoft.com */
01232          if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01233 #if 0
01234             ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01235 #endif
01236             f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01237          }
01238       }
01239    }
01240    return f;
01241 }

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

Definition at line 1300 of file chan_mgcp.c.

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

01301 {
01302    struct mgcp_subchannel *sub = ast->tech_pvt;
01303    char tmp[4];
01304 
01305    tmp[0] = 'D';
01306    tmp[1] = '/';
01307    tmp[2] = digit;
01308    tmp[3] = '\0';
01309    ast_mutex_lock(&sub->lock);
01310    transmit_notify_request(sub, tmp);
01311    ast_mutex_unlock(&sub->lock);
01312    return -1;
01313 }

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

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

03924 {
03925    /* XXX Is there such thing as video support with MGCP? XXX */
03926    struct mgcp_subchannel *sub;
03927    sub = chan->tech_pvt;
03928    if (sub) {
03929       transmit_modify_with_sdp(sub, rtp, codecs);
03930       return 0;
03931    }
03932    return -1;
03933 }

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

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

01086 {
01087    struct mgcp_gateway  *g;
01088    struct mgcp_endpoint *e;
01089    int hasendpoints = 0;
01090    char iabuf[INET_ADDRSTRLEN];
01091 
01092    if (argc != 3) 
01093       return RESULT_SHOWUSAGE;
01094    ast_mutex_lock(&gatelock);
01095    g = gateways;
01096    while(g) {
01097       e = g->endpoints;
01098       ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), g->addr.sin_addr) : ast_inet_ntoa(iabuf, sizeof(iabuf), g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
01099       while(e) {
01100          /* JS: Don't show wilcard endpoint */
01101          if (strcmp(e->name, g->wcardep) !=0)
01102             ast_cli(fd, "   -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
01103          hasendpoints = 1;
01104          e = e->next;
01105       }
01106       if (!hasendpoints) {
01107          ast_cli(fd, "   << No Endpoints Defined >>     ");
01108       }
01109       g = g->next;
01110    }
01111    ast_mutex_unlock(&gatelock);
01112    return RESULT_SUCCESS;
01113 }

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

Definition at line 2570 of file chan_mgcp.c.

References ast_bridged_channel(), ast_canmatch_extension(), 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_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, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmfmode, ast_channel::exten, exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_channel::language, mgcp_endpoint::lastcallerid, 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().

02571 {
02572    struct ast_channel *chan = data;
02573    struct mgcp_subchannel *sub = chan->tech_pvt;
02574    struct mgcp_endpoint *p = sub->parent;
02575    char exten[AST_MAX_EXTENSION] = "";
02576    int len = 0;
02577    int timeout = firstdigittimeout;
02578    int res;
02579    int getforward = 0;
02580 
02581    while(len < AST_MAX_EXTENSION-1) {
02582       res = ast_waitfordigit(chan, timeout);
02583       timeout = 0;
02584       if (res < 0) {
02585          ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
02586          /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02587          ast_indicate(chan, -1);
02588          ast_hangup(chan);
02589          return NULL;
02590       } else if (res) {
02591          exten[len++]=res;
02592          exten[len] = '\0';
02593       }
02594       if (!ast_ignore_pattern(chan->context, exten)) {
02595          /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02596          ast_indicate(chan, -1);
02597       } else {
02598          /* XXX Redundant?  We should already be playing dialtone */
02599          /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
02600          transmit_notify_request(sub, "L/dl");
02601       }
02602       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
02603          if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
02604             if (getforward) {
02605                /* Record this as the forwarding extension */
02606                strncpy(p->call_forward, exten, sizeof(p->call_forward) - 1); 
02607                if (option_verbose > 2) {
02608                   ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n", 
02609                      p->call_forward, chan->name);
02610                }
02611                /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02612                transmit_notify_request(sub, "L/sl");
02613                if (res)
02614                   break;
02615                usleep(500000);
02616                /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02617                ast_indicate(chan, -1);
02618                sleep(1);
02619                memset(exten, 0, sizeof(exten));
02620                /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
02621                transmit_notify_request(sub, "L/dl");
02622                len = 0;
02623                getforward = 0;
02624             } else {
02625                /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02626                ast_indicate(chan, -1);
02627                strncpy(chan->exten, exten, sizeof(chan->exten)-1);
02628                ast_set_callerid(chan,
02629                      p->hidecallerid ? "" : p->cid_num,
02630                      p->hidecallerid ? "" : p->cid_name,
02631                      p->cid_num);
02632                ast_setstate(chan, AST_STATE_RING);
02633                /*zt_enable_ec(p);*/
02634                if (p->dtmfmode & MGCP_DTMF_HYBRID) {
02635                   p->dtmfmode |= MGCP_DTMF_INBAND;
02636                   ast_indicate(chan, -1);
02637                }
02638                res = ast_pbx_run(chan);
02639                if (res) {
02640                   ast_log(LOG_WARNING, "PBX exited non-zero\n");
02641                   /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
02642                   /*transmit_notify_request(p, "nbz", 1);*/
02643                   transmit_notify_request(sub, "G/cg");
02644                }
02645                return NULL;
02646             }
02647          } else {
02648             /* It's a match, but they just typed a digit, and there is an ambiguous match,
02649                so just set the timeout to matchdigittimeout and wait some more */
02650             timeout = matchdigittimeout;
02651          }
02652       } else if (res == 0) {
02653          ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
02654          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
02655          transmit_notify_request(sub, "G/cg");
02656          /*zt_wait_event(p->subs[index].zfd);*/
02657          ast_hangup(chan);
02658          return NULL;
02659       } else if (p->hascallwaiting && p->callwaiting && !strcmp(exten, "*70")) {
02660          if (option_verbose > 2) {
02661             ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
02662          }
02663          /* Disable call waiting if enabled */
02664          p->callwaiting = 0;
02665          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02666          transmit_notify_request(sub, "L/sl");
02667          len = 0;
02668          memset(exten, 0, sizeof(exten));
02669          timeout = firstdigittimeout;
02670       } else if (!strcmp(exten,ast_pickup_ext())) {
02671          /* Scan all channels and see if any there
02672           * ringing channqels with that have call groups
02673           * that equal this channels pickup group  
02674           */
02675          if (ast_pickup_call(chan)) {
02676             ast_log(LOG_WARNING, "No call pickup possible...\n");
02677             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
02678             transmit_notify_request(sub, "G/cg");
02679          }
02680          ast_hangup(chan);
02681          return NULL;
02682       } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
02683          if (option_verbose > 2) {
02684             ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
02685          }
02686          /* Disable Caller*ID if enabled */
02687          p->hidecallerid = 1;
02688          ast_set_callerid(chan, "", "", NULL);
02689          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02690          transmit_notify_request(sub, "L/sl");
02691          len = 0;
02692          memset(exten, 0, sizeof(exten));
02693          timeout = firstdigittimeout;
02694       } else if (p->callreturn && !strcmp(exten, "*69")) {
02695          res = 0;
02696          if (!ast_strlen_zero(p->lastcallerid)) {
02697             res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
02698          }
02699          if (!res)
02700             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02701             transmit_notify_request(sub, "L/sl");
02702          break;
02703       } else if (!strcmp(exten, "*78")) {
02704          /* Do not disturb */
02705          if (option_verbose > 2) {
02706             ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
02707          }
02708          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02709          transmit_notify_request(sub, "L/sl");
02710          p->dnd = 1;
02711          getforward = 0;
02712          memset(exten, 0, sizeof(exten));
02713          len = 0;
02714       } else if (!strcmp(exten, "*79")) {
02715          /* Do not disturb */
02716          if (option_verbose > 2) {
02717             ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
02718          }
02719          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02720          transmit_notify_request(sub, "L/sl");
02721          p->dnd = 0;
02722          getforward = 0;
02723          memset(exten, 0, sizeof(exten));
02724          len = 0;
02725       } else if (p->cancallforward && !strcmp(exten, "*72")) {
02726          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02727          transmit_notify_request(sub, "L/sl");
02728          getforward = 1;
02729          memset(exten, 0, sizeof(exten));
02730          len = 0;
02731       } else if (p->cancallforward && !strcmp(exten, "*73")) {
02732          if (option_verbose > 2) {
02733             ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
02734          }
02735          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02736          transmit_notify_request(sub, "L/sl");
02737          memset(p->call_forward, 0, sizeof(p->call_forward));
02738          getforward = 0;
02739          memset(exten, 0, sizeof(exten));
02740          len = 0;
02741       } else if (!strcmp(exten, ast_parking_ext()) && 
02742          sub->next->owner && ast_bridged_channel(sub->next->owner)) {
02743          /* This is a three way call, the main call being a real channel, 
02744             and we're parking the first call. */
02745          ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
02746          if (option_verbose > 2) {
02747             ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
02748          }
02749          break;
02750       } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(exten, "*60")) {
02751          if (option_verbose > 2) {
02752             ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
02753          }
02754          res = ast_db_put("blacklist", p->lastcallerid, "1");
02755          if (!res) {
02756             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02757             transmit_notify_request(sub, "L/sl");
02758             memset(exten, 0, sizeof(exten));
02759             len = 0;
02760          }
02761       } else if (p->hidecallerid && !strcmp(exten, "*82")) {
02762          if (option_verbose > 2) {
02763             ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
02764          }
02765          /* Enable Caller*ID if enabled */
02766          p->hidecallerid = 0;
02767          ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
02768          /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
02769          transmit_notify_request(sub, "L/sl");
02770          len = 0;
02771          memset(exten, 0, sizeof(exten));
02772          timeout = firstdigittimeout;
02773       } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
02774             ((exten[0] != '*') || (strlen(exten) > 2))) {
02775          if (option_debug)
02776             ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
02777          break;
02778       }
02779       if (!timeout)
02780          timeout = gendigittimeout;
02781       if (len && !ast_ignore_pattern(chan->context, exten))
02782          /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
02783          ast_indicate(chan, -1);
02784    }
02785 #if 0
02786    for (;;) {
02787       res = ast_waitfordigit(chan, to);
02788       if (!res) {
02789          ast_log(LOG_DEBUG, "Timeout...\n");
02790          break;
02791       }
02792       if (res < 0) {
02793          ast_log(LOG_DEBUG, "Got hangup...\n");
02794          ast_hangup(chan);
02795          break;
02796       }
02797       exten[pos++] = res;
02798       if (!ast_ignore_pattern(chan->context, exten))
02799          ast_indicate(chan, -1);
02800       if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
02801          if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
02802             to = 3000;
02803          else
02804             to = 8000;
02805       } else
02806          break;
02807    }
02808    if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
02809       strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
02810       if (!p->rtp) {
02811          start_rtp(p);
02812       }
02813       ast_setstate(chan, AST_STATE_RING);
02814       chan->rings = 1;
02815       if (ast_pbx_run(chan)) {
02816          ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
02817       } else
02818          return NULL;
02819    }
02820 #endif
02821    ast_hangup(chan);
02822    return NULL;
02823 }

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

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

01255 {
01256    struct mgcp_subchannel *sub = ast->tech_pvt;
01257    int res = 0;
01258    if (frame->frametype != AST_FRAME_VOICE) {
01259       if (frame->frametype == AST_FRAME_IMAGE)
01260          return 0;
01261       else {
01262          ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01263          return 0;
01264       }
01265    } else {
01266       if (!(frame->subclass & ast->nativeformats)) {
01267          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01268             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01269          return -1;
01270       }
01271    }
01272    if (sub) {
01273       ast_mutex_lock(&sub->lock);
01274       if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01275          if (sub->rtp) {
01276             res =  ast_rtp_write(sub->rtp, frame);
01277          }
01278       }
01279       ast_mutex_unlock(&sub->lock);
01280    }
01281    return res;
01282 }

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

Definition at line 3274 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(), find_and_retrans(), find_subchannel_and_lock(), free, handle_request(), handle_response(), 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(), result, mgcp_gateway::retransid, and mgcp_message::seqno.

Referenced by do_monitor().

03275 {
03276    struct mgcp_request req;
03277    struct sockaddr_in sin;
03278    struct mgcp_subchannel *sub;
03279    int res;
03280    socklen_t len;
03281    int result;
03282    int ident;
03283    char iabuf[INET_ADDRSTRLEN];
03284    len = sizeof(sin);
03285    memset(&req, 0, sizeof(req));
03286    res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03287    if (res < 0) {
03288       if (errno != ECONNREFUSED)
03289          ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03290       return 1;
03291    }
03292    req.data[res] = '\0';
03293    req.len = res;
03294    if (mgcpdebug) {
03295       ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
03296    }
03297    parse(&req);
03298    if (req.headers < 1) {
03299       /* Must have at least one header */
03300       return 1;
03301    }
03302    if (ast_strlen_zero(req.identifier)) {
03303       ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
03304       return 1;
03305    }
03306 
03307    if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
03308       /* Try to find who this message is for, if it's important */
03309       sub = find_subchannel_and_lock(NULL, ident, &sin);
03310       if (sub) {
03311          struct mgcp_gateway *gw = sub->parent->parent;
03312          struct mgcp_message *cur, *prev;
03313 
03314          ast_mutex_unlock(&sub->lock);
03315          ast_mutex_lock(&gw->msgs_lock);
03316          for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03317             if (cur->seqno == ident) {
03318                ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
03319                if (prev)
03320                   prev->next = cur->next;
03321                else
03322                   gw->msgs = cur->next;
03323                break;
03324             }
03325          }
03326 
03327          /* stop retrans timer if the queue is empty */
03328          if (!gw->msgs && (gw->retransid != -1)) {
03329             ast_sched_del(sched, gw->retransid);
03330             gw->retransid = -1;
03331          }
03332 
03333          ast_mutex_unlock(&gw->msgs_lock);
03334          if (cur) {
03335             handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03336             free(cur);
03337             return 1;
03338          }
03339 
03340          ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 
03341             gw->name, ident);
03342       }
03343    } else {
03344       if (ast_strlen_zero(req.endpoint) || 
03345             ast_strlen_zero(req.version) || 
03346          ast_strlen_zero(req.verb)) {
03347          ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03348          return 1;
03349       }
03350       /* Process request, with iflock held */
03351       sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03352       if (sub) {
03353          /* look first to find a matching response in the queue */
03354          if (!find_and_retrans(sub, &req))
03355             /* pass the request off to the currently mastering subchannel */
03356             handle_request(sub, &req, &sin);
03357          ast_mutex_unlock(&sub->lock);
03358       }
03359    }
03360    return 1;
03361 }

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1662 of file chan_mgcp.c.

References ast_log(), ast_strlen_zero(), ast_verbose(), mgcp_request::data, mgcp_request::endpoint, 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(), aqm_exec(), ast_hint_state_changed(), ast_parse_allow_disallow(), dial_exec_full(), enumlookup_exec(), get_in_brackets(), group_check_exec(), mgcpsock_read(), mixmonitor_exec(), pbx_builtin_background(), pqm_exec(), privacy_exec(), reload_agents(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), and upqm_exec().

01663 {
01664    /* Divide fields by NULL's */
01665    char *c;
01666    int f = 0;
01667    c = req->data;
01668 
01669    /* First header starts immediately */
01670    req->header[f] = c;
01671    while(*c) {
01672       if (*c == '\n') {
01673          /* We've got a new header */
01674          *c = 0;
01675 #if 0
01676          printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01677 #endif         
01678          if (ast_strlen_zero(req->header[f])) {
01679             /* Line by itself means we're now in content */
01680             c++;
01681             break;
01682          }
01683          if (f >= MGCP_MAX_HEADERS - 1) {
01684             ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01685          } else
01686             f++;
01687          req->header[f] = c + 1;
01688       } else if (*c == '\r') {
01689          /* Ignore but eliminate \r's */
01690          *c = 0;
01691       }
01692       c++;
01693    }
01694    /* Check for last header */
01695    if (!ast_strlen_zero(req->header[f])) 
01696       f++;
01697    req->headers = f;
01698    /* Now we process any mime content */
01699    f = 0;
01700    req->line[f] = c;
01701    while(*c) {
01702       if (*c == '\n') {
01703          /* We've got a new line */
01704          *c = 0;
01705 #if 0
01706          printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01707 #endif         
01708          if (f >= MGCP_MAX_LINES - 1) {
01709             ast_log(LOG_WARNING, "Too many SDP lines...\n");
01710          } else
01711             f++;
01712          req->line[f] = c + 1;
01713       } else if (*c == '\r') {
01714          /* Ignore and eliminate \r's */
01715          *c = 0;
01716       }
01717       c++;
01718    }
01719    /* Check for last line */
01720    if (!ast_strlen_zero(req->line[f])) 
01721       f++;
01722    req->lines = f;
01723    /* Parse up the initial header */
01724    c = req->header[0];
01725    while(*c && *c < 33) c++;
01726    /* First the verb */
01727    req->verb = c;
01728    while(*c && (*c > 32)) c++;
01729    if (*c) {
01730       *c = '\0';
01731       c++;
01732       while(*c && (*c < 33)) c++;
01733       req->identifier = c;
01734       while(*c && (*c > 32)) c++;
01735       if (*c) {
01736          *c = '\0';
01737          c++;
01738          while(*c && (*c < 33)) c++;
01739          req->endpoint = c;
01740          while(*c && (*c > 32)) c++;
01741          if (*c) {
01742             *c = '\0';
01743             c++;
01744             while(*c && (*c < 33)) c++;
01745             req->version = c;
01746             while(*c && (*c > 32)) c++;
01747             while(*c && (*c < 33)) c++;
01748             while(*c && (*c > 32)) c++;
01749             *c = '\0';
01750          }
01751       }
01752    }
01753       
01754    if (mgcpdebug) {
01755       ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01756          req->verb, req->identifier, req->endpoint, req->version);
01757       ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01758    }
01759    if (*c) 
01760       ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01761 }

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

Definition at line 1763 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(), host, hp, 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().

01764 {
01765    char *m;
01766    char *c;
01767    char *a;
01768    char host[258];
01769    int len;
01770    int portno;
01771    int peercapability, peerNonCodecCapability;
01772    struct sockaddr_in sin;
01773    char *codecs;
01774    struct ast_hostent ahp; struct hostent *hp;
01775    int codec, codec_count=0;
01776    int iterator;
01777    struct mgcp_endpoint *p = sub->parent;
01778 
01779    /* Get codec and RTP info from SDP */
01780    m = get_sdp(req, "m");
01781    c = get_sdp(req, "c");
01782    if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01783       ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01784       return -1;
01785    }
01786    if (sscanf(c, "IN IP4 %256s", host) != 1) {
01787       ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01788       return -1;
01789    }
01790    /* XXX This could block for a long time, and block the main thread! XXX */
01791    hp = ast_gethostbyname(host, &ahp);
01792    if (!hp) {
01793       ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01794       return -1;
01795    }
01796    if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
01797       ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
01798       return -1;
01799    }
01800    sin.sin_family = AF_INET;
01801    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01802    sin.sin_port = htons(portno);
01803    ast_rtp_set_peer(sub->rtp, &sin);
01804 #if 0
01805    printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
01806 #endif   
01807    /* Scan through the RTP payload types specified in a "m=" line: */
01808    ast_rtp_pt_clear(sub->rtp);
01809    codecs = ast_strdupa(m + len);
01810    while (!ast_strlen_zero(codecs)) {
01811       if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
01812          if (codec_count)
01813             break;
01814          ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01815          return -1;
01816       }
01817       ast_rtp_set_m_type(sub->rtp, codec);
01818       codec_count++;
01819       codecs += len;
01820    }
01821 
01822    /* Next, scan through each "a=rtpmap:" line, noting each */
01823    /* specified RTP payload type (with corresponding MIME subtype): */
01824    sdpLineNum_iterator_init(&iterator);
01825    while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01826       char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
01827       if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
01828          continue;
01829       /* Note: should really look at the 'freq' and '#chans' params too */
01830       ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
01831    }
01832 
01833    /* Now gather all of the codecs that were asked for: */
01834    ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
01835    p->capability = capability & peercapability;
01836    if (mgcpdebug) {
01837       ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01838          capability, peercapability, p->capability);
01839       ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01840          nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01841    }
01842    if (!p->capability) {
01843       ast_log(LOG_WARNING, "No compatible codecs!\n");
01844       return -1;
01845    }
01846    return 0;
01847 }

static void prune_gateways ( void   )  [static]

Definition at line 4031 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

04032 {
04033    struct mgcp_gateway *g, *z, *r;
04034    struct mgcp_endpoint *e, *p, *t;
04035 
04036    ast_mutex_lock(&gatelock);
04037 
04038    /* prune gateways */
04039    for (z = NULL, g = gateways; g;) {
04040       /* prune endpoints */
04041       for (p = NULL, e = g->endpoints; e; ) {
04042          if (e->delme || g->delme) {
04043             t = e;
04044             e = e->next;
04045             if (!p)
04046                g->endpoints = e;
04047             else
04048                p->next = e;
04049             destroy_endpoint(t);
04050          } else {
04051             p = e;
04052             e = e->next;
04053          }
04054       }
04055 
04056       if (g->delme) {
04057          r = g;
04058          g = g->next;
04059          if (!z)
04060             gateways = g;
04061          else
04062             z->next = g;
04063 
04064          destroy_gateway(r);
04065       } else {
04066          z = g;
04067          g = g->next;
04068       }
04069    }
04070 
04071    ast_mutex_unlock(&gatelock);
04072 }

int reload ( void   ) 

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
The return value is not used.

Definition at line 4299 of file chan_mgcp.c.

References mgcp_reload().

04300 {
04301    mgcp_reload(0, 0, NULL);
04302    return 0;
04303 }

static int reload_config ( void   )  [static]

Definition at line 4074 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_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_variable_browse(), ast_verbose(), bindaddr, build_gateway(), capability, cfg, config, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, dtmfmode, mgcp_gateway::endpoints, format, gateways, 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, 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.

04075 {
04076    struct ast_config *cfg;
04077    struct ast_variable *v;
04078    struct mgcp_gateway *g;
04079    struct mgcp_endpoint *e;
04080    char iabuf[INET_ADDRSTRLEN];
04081    char *cat;
04082    struct ast_hostent ahp;
04083    struct hostent *hp;
04084    int format;
04085    
04086    if (gethostname(ourhost, sizeof(ourhost)-1)) {
04087       ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04088       return 0;
04089    }
04090    cfg = ast_config_load(config);
04091 
04092    /* We *must* have a config file otherwise stop immediately */
04093    if (!cfg) {
04094       ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04095       return 0;
04096    }
04097    memset(&bindaddr, 0, sizeof(bindaddr));
04098    dtmfmode = 0;
04099    v = ast_variable_browse(cfg, "general");
04100    while(v) {
04101       /* Create the interface list */
04102       if (!strcasecmp(v->name, "bindaddr")) {
04103          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04104             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04105          } else {
04106             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04107          }
04108       } else if (!strcasecmp(v->name, "allow")) {
04109          format = ast_getformatbyname(v->value);
04110          if (format < 1) 
04111             ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04112          else
04113             capability |= format;
04114       } else if (!strcasecmp(v->name, "disallow")) {
04115          format = ast_getformatbyname(v->value);
04116          if (format < 1) 
04117             ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04118          else
04119             capability &= ~format;
04120       } else if (!strcasecmp(v->name, "tos")) {
04121          if (sscanf(v->value, "%d", &format) == 1)
04122             tos = format & 0xff;
04123          else if (!strcasecmp(v->value, "lowdelay"))
04124             tos = IPTOS_LOWDELAY;
04125          else if (!strcasecmp(v->value, "throughput"))
04126             tos = IPTOS_THROUGHPUT;
04127          else if (!strcasecmp(v->value, "reliability"))
04128             tos = IPTOS_RELIABILITY;
04129          else if (!strcasecmp(v->value, "mincost"))
04130             tos = IPTOS_MINCOST;
04131          else if (!strcasecmp(v->value, "none"))
04132             tos = 0;
04133          else
04134             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
04135       } else if (!strcasecmp(v->name, "port")) {
04136          if (sscanf(v->value, "%d", &ourport) == 1) {
04137             bindaddr.sin_port = htons(ourport);
04138          } else {
04139             ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04140          }
04141       }
04142       v = v->next;
04143    }
04144 
04145    /* SC: mark existing entries for deletion */
04146    ast_mutex_lock(&gatelock);
04147    g = gateways;
04148    while (g) {
04149       g->delme = 1;
04150       e = g->endpoints;
04151       while (e) {
04152          e->delme = 1;
04153          e = e->next;
04154       }
04155       g = g->next;
04156    }
04157    ast_mutex_unlock(&gatelock);
04158    
04159    cat = ast_category_browse(cfg, NULL);
04160    while(cat) {
04161       if (strcasecmp(cat, "general")) {
04162          ast_mutex_lock(&gatelock);
04163          g = build_gateway(cat, ast_variable_browse(cfg, cat));
04164          if (g) {
04165             if (option_verbose > 2) {
04166                ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
04167             }
04168             g->next = gateways;
04169             gateways = g;
04170          }
04171          ast_mutex_unlock(&gatelock);
04172 
04173          /* FS: process queue and IO */
04174          if (monitor_thread == pthread_self()) {
04175             if (sched) ast_sched_runq(sched);
04176             if (io) ast_io_wait(io, 10);
04177          }
04178       }
04179       cat = ast_category_browse(cfg, cat);
04180    }
04181 
04182       /* SC: prune deleted entries etc. */
04183       prune_gateways();
04184 
04185    if (ntohl(bindaddr.sin_addr.s_addr)) {
04186       memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04187    } else {
04188       hp = ast_gethostbyname(ourhost, &ahp);
04189       if (!hp) {
04190          ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04191          ast_config_destroy(cfg);
04192          return 0;
04193       }
04194       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04195    }
04196    if (!ntohs(bindaddr.sin_port))
04197       bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04198    bindaddr.sin_family = AF_INET;
04199    ast_mutex_lock(&netlock);
04200    if (mgcpsock > -1)
04201       close(mgcpsock);
04202 
04203    if (mgcpsock_read_id != NULL)
04204       ast_io_remove(io, mgcpsock_read_id);
04205    mgcpsock_read_id = NULL;
04206 
04207    mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04208    if (mgcpsock < 0) {
04209       ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04210    } else {
04211       if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04212          ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04213             ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04214                strerror(errno));
04215          close(mgcpsock);
04216          mgcpsock = -1;
04217       } else {
04218          if (option_verbose > 1) {
04219             ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n", 
04220                ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04221             ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
04222          }
04223          if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
04224             ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
04225       }
04226    }
04227    ast_mutex_unlock(&netlock);
04228    ast_config_destroy(cfg);
04229 
04230    /* SC: send audit only to the new endpoints */
04231    g = gateways;
04232    while (g) {
04233       e = g->endpoints;
04234       while (e && e->needaudit) {
04235          e->needaudit = 0;
04236          transmit_audit_endpoint(e);
04237          ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04238          e = e->next;
04239       }
04240       g = g->next;
04241    }
04242 
04243    return 0;
04244 }

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

Definition at line 1940 of file chan_mgcp.c.

References init_req(), and oseq.

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

01941 {
01942    memset(req, 0, sizeof(struct mgcp_request));
01943    oseq++;
01944    if (oseq > 999999999)
01945       oseq = 1;
01946    init_req(p, req, verb);
01947    return 0;
01948 }

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

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

00564 {
00565    struct mgcp_endpoint *p = sub->parent;
00566    int res;
00567    char iabuf[INET_ADDRSTRLEN];
00568    if (mgcpdebug) {
00569       ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00570    }
00571    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00572    if (res > 0)
00573       res = 0;
00574    return res;
00575 }

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

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

01934 {
01935    memset(resp, 0, sizeof(*resp));
01936    init_resp(resp, msg, req, msgrest);
01937    return 0;
01938 }

static int restart_monitor ( void   )  [static]

Definition at line 3451 of file chan_mgcp.c.

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

03452 {
03453    /* If we're supposed to be stopped -- stay stopped */
03454    if (monitor_thread == AST_PTHREADT_STOP)
03455       return 0;
03456    if (ast_mutex_lock(&monlock)) {
03457       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03458       return -1;
03459    }
03460    if (monitor_thread == pthread_self()) {
03461       ast_mutex_unlock(&monlock);
03462       ast_log(LOG_WARNING, "Cannot kill myself\n");
03463       return -1;
03464    }
03465    if (monitor_thread != AST_PTHREADT_NULL) {
03466       /* Wake up the thread */
03467       pthread_kill(monitor_thread, SIGURG);
03468    } else {
03469       /* Start a new monitor */
03470       if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03471          ast_mutex_unlock(&monlock);
03472          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03473          return -1;
03474       }
03475    }
03476    ast_mutex_unlock(&monlock);
03477    return 0;
03478 }

static int retrans_pkt ( void *  data  )  [static]

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

00673 {
00674    struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00675    struct mgcp_message *cur, *exq = NULL, *w, *prev;
00676    int res = 0;
00677 
00678    /* find out expired msgs */
00679    ast_mutex_lock(&gw->msgs_lock);
00680 
00681    prev = NULL, cur = gw->msgs;
00682    while (cur) {
00683       if (cur->retrans < MAX_RETRANS) {
00684          cur->retrans++;
00685          if (mgcpdebug) {
00686             ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00687                cur->retrans, cur->seqno, gw->name);
00688          }
00689          __mgcp_xmit(gw, cur->buf, cur->len);
00690 
00691          prev = cur;
00692          cur = cur->next;
00693       } else {
00694          if (prev)
00695             prev->next = cur->next;
00696          else
00697             gw->msgs = cur->next;
00698 
00699          ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00700             cur->seqno, gw->name);
00701 
00702          w = cur;
00703          cur = cur->next;
00704 
00705          if (exq) {
00706             w->next = exq;
00707          } else {
00708             w->next = NULL;
00709          }
00710          exq = w;
00711       }
00712    }
00713 
00714    if (!gw->msgs) {
00715       gw->retransid = -1;
00716       res = 0;
00717    } else {
00718       res = 1;
00719    }
00720    ast_mutex_unlock(&gw->msgs_lock);
00721 
00722    while (exq) {
00723       cur = exq;
00724       /* time-out transaction */
00725       handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
00726       exq = exq->next;
00727       free(cur);
00728    }
00729 
00730    return res;
00731 }

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1481 of file chan_mgcp.c.

Referenced by process_sdp().

01482 {
01483    *iterator = 0;
01484 }

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

Definition at line 800 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_request(), transmit_request_with_auth(), transmit_sip_request(), and transmit_state_notify().

00802 {
00803    int res = 0;
00804    struct mgcp_request **queue, *q, *r, *t;
00805    char iabuf[INET_ADDRSTRLEN];
00806    ast_mutex_t *l;
00807 
00808    ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
00809    if (p->slowsequence) {
00810       queue = &p->cmd_queue;
00811       l = &p->cmd_queue_lock;
00812       ast_mutex_lock(l);
00813    } else {
00814       switch (req->cmd) {
00815       case MGCP_CMD_DLCX:
00816          queue = &sub->cx_queue;
00817          l = &sub->cx_queue_lock;
00818          ast_mutex_lock(l);
00819          q = sub->cx_queue;
00820          /* delete pending cx cmds */
00821          while (q) {
00822             r = q->next;
00823             free(q);
00824             q = r;
00825          }
00826          *queue = NULL;
00827          break;
00828 
00829       case MGCP_CMD_CRCX:
00830       case MGCP_CMD_MDCX:
00831          queue = &sub->cx_queue;
00832          l = &sub->cx_queue_lock;
00833          ast_mutex_lock(l);
00834          break;
00835 
00836       case MGCP_CMD_RQNT:
00837          queue = &p->rqnt_queue;
00838          l = &p->rqnt_queue_lock;
00839          ast_mutex_lock(l);
00840          break;
00841 
00842       default:
00843          queue = &p->cmd_queue;
00844          l = &p->cmd_queue_lock;
00845          ast_mutex_lock(l);
00846          break;
00847       }
00848    }
00849 
00850    r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
00851    if (!r) {
00852       ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00853       ast_mutex_unlock(l);
00854       return -1;
00855    }
00856    memcpy(r, req, sizeof(struct mgcp_request));
00857 
00858    if (!(*queue)) {
00859       if (mgcpdebug) {
00860          ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
00861             ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00862       }
00863 
00864       res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00865    } else {
00866       if (mgcpdebug) {
00867          ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
00868             ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00869       }
00870    }
00871 
00872    /* XXX SC: find tail. We could also keep tail in the data struct for faster access */
00873    for (t = *queue; t && t->next; t = t->next);
00874 
00875    r->next = NULL;
00876    if (t)
00877       t->next = r;
00878    else
00879       *queue = r;
00880 
00881    ast_mutex_unlock(l);
00882 
00883    return res;
00884 }

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

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

00578 {
00579    struct mgcp_endpoint *p = sub->parent;
00580    int res;
00581    char iabuf[INET_ADDRSTRLEN];
00582    if (mgcpdebug) {
00583       ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00584    }
00585    res = __mgcp_xmit(p->parent, req->data, req->len);
00586    if (res > 0)
00587       res = 0;
00588    return res;
00589 }

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2545 of file chan_mgcp.c.

References ast_mutex_lock(), ast_mutex_unlock(), 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_message(), handle_response(), mgcp_answer(), mgcp_call(), mgcp_ss(), and skinny_answer().

02546 {
02547    ast_mutex_lock(&sub->lock);
02548    /* SC: check again to be on the safe side */
02549    if (sub->rtp) {
02550       ast_rtp_destroy(sub->rtp);
02551       sub->rtp = NULL;
02552    }
02553    /* Allocate the RTP now */
02554    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02555    if (sub->rtp && sub->owner)
02556       sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
02557    if (sub->rtp)
02558       ast_rtp_setnat(sub->rtp, sub->nat);
02559 #if 0
02560    ast_rtp_set_callback(p->rtp, rtpready);
02561    ast_rtp_set_data(p->rtp, p);
02562 #endif      
02563    /* Make a call*ID */
02564         snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
02565    /* Transmit the connection create */
02566    transmit_connect_with_sdp(sub, NULL);
02567    ast_mutex_unlock(&sub->lock);
02568 }

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

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

02254 {
02255    struct mgcp_request resp;
02256    reqprep(&resp, p, "AUEP");
02257    /* SC: removed unknown param VS */
02258    /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
02259    add_header(&resp, "F", "A");
02260    /* SC: fill in new fields */
02261    resp.cmd = MGCP_CMD_AUEP;
02262    resp.trid = oseq;
02263    return send_request(p, NULL, &resp, oseq);  /* SC */
02264 }

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

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

02109 {
02110    struct mgcp_request resp;
02111    char local[256];
02112    char tmp[80];
02113    int x;
02114    struct mgcp_endpoint *p = sub->parent;
02115 
02116    snprintf(local, sizeof(local), "p:20");
02117    for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02118       if (p->capability & x) {
02119          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
02120          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02121       }
02122    }
02123    if (mgcpdebug) {
02124       ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 
02125          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02126    }
02127    reqprep(&resp, p, "CRCX");
02128    add_header(&resp, "C", sub->callid);
02129    add_header(&resp, "L", local);
02130    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02131    /* SC: X header should not be sent. kept for compatibility */
02132    add_header(&resp, "X", sub->txident);
02133    /*add_header(&resp, "S", "");*/
02134    ast_rtp_offered_from_local(sub->rtp, 1);
02135    add_sdp(&resp, sub, rtp);
02136    /* SC: fill in new fields */
02137    resp.cmd = MGCP_CMD_CRCX;
02138    resp.trid = oseq;
02139    return send_request(p, sub, &resp, oseq);  /* SC */
02140 }

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

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

02267 {
02268    struct mgcp_endpoint *p = sub->parent;
02269    struct mgcp_request resp;
02270 
02271    if (mgcpdebug) {
02272       ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 
02273          sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02274    }
02275    reqprep(&resp, p, "DLCX");
02276    /* SC: check if call id is avail */
02277    if (sub->callid[0])
02278       add_header(&resp, "C", sub->callid);
02279    /* SC: X header should not be sent. kept for compatibility */
02280    add_header(&resp, "X", sub->txident);
02281    /* SC: check if cxident is avail */
02282    if (sub->cxident[0])
02283       add_header(&resp, "I", sub->cxident);
02284    /* SC: fill in new fields */
02285    resp.cmd = MGCP_CMD_DLCX;
02286    resp.trid = oseq;
02287    return send_request(p, sub, &resp, oseq);  /* SC */
02288 }

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

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

02291 {
02292    struct mgcp_request resp;
02293 
02294    if (mgcpdebug) {
02295       ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n", 
02296          cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02297    }
02298    reqprep(&resp, p, "DLCX");
02299    /* SC: check if call id is avail */
02300    if (callid && *callid)
02301       add_header(&resp, "C", callid);
02302    /* SC: check if cxident is avail */
02303    if (cxident && *cxident)
02304       add_header(&resp, "I", cxident);
02305    /* SC: fill in new fields */
02306    resp.cmd = MGCP_CMD_DLCX;
02307    resp.trid = oseq;
02308    return send_request(p, p->sub, &resp, oseq);
02309 }

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2218 of file chan_mgcp.c.

References add_header(), ast_strlen_zero(), ast_verbose(), mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dtmfmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, mgcp_cxmodes, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::rtp, 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().

02219 {
02220    struct mgcp_request resp;
02221    struct mgcp_endpoint *p = sub->parent;
02222 
02223    if (ast_strlen_zero(sub->cxident)) {
02224       /* We don't have a CXident yet, store the destination and
02225          wait a bit */
02226       return 0;
02227    }
02228    if (mgcpdebug) {
02229       ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n", 
02230          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02231    }
02232    reqprep(&resp, p, "MDCX");
02233    add_header(&resp, "C", sub->callid);
02234    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02235    /* SC: X header should not be sent. kept for compatibility */
02236    add_header(&resp, "X", sub->txident);
02237    add_header(&resp, "I", sub->cxident);
02238    switch (sub->parent->hookstate) {
02239    case MGCP_ONHOOK:
02240       add_header(&resp, "R", "L/hd(N)");
02241       break;
02242    case MGCP_OFFHOOK:
02243       add_header(&resp, "R",  (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
02244       break;
02245    }
02246    /* SC: fill in new fields */
02247    resp.cmd = MGCP_CMD_MDCX;
02248    resp.trid = oseq;
02249    return send_request(p, sub, &resp, oseq); /* SC */
02250 }

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

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

02068 {
02069    struct mgcp_request resp;
02070    char local[256];
02071    char tmp[80];
02072    int x;
02073    int capability;
02074    struct mgcp_endpoint *p = sub->parent;
02075 
02076    capability = p->capability;
02077    if (codecs)
02078       capability = codecs;
02079    if (ast_strlen_zero(sub->cxident) && rtp) {
02080       /* We don't have a CXident yet, store the destination and
02081          wait a bit */
02082       ast_rtp_get_peer(rtp, &sub->tmpdest);
02083       return 0;
02084    }
02085    snprintf(local, sizeof(local), "p:20");
02086    for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
02087       if (p->capability & x) {
02088          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
02089          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02090       }
02091    }
02092    reqprep(&resp, p, "MDCX");
02093    add_header(&resp, "C", sub->callid);
02094    add_header(&resp, "L", local);
02095    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02096    /* SC: X header should not be sent. kept for compatibility */
02097    add_header(&resp, "X", sub->txident);
02098    add_header(&resp, "I", sub->cxident);
02099    /*add_header(&resp, "S", "");*/
02100    ast_rtp_offered_from_local(sub->rtp, 0);
02101    add_sdp(&resp, sub, rtp);
02102    /* SC: fill in new fields */
02103    resp.cmd = MGCP_CMD_MDCX;
02104    resp.trid = oseq;
02105    return send_request(p, sub, &resp, oseq); /* SC */
02106 }

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

Definition at line 2142 of file chan_mgcp.c.

References add_header(), ast_strlen_zero(), ast_verbose(), mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmfmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, 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(), and mgcp_ss().

02143 {
02144    struct mgcp_request resp;
02145    struct mgcp_endpoint *p = sub->parent;
02146 
02147    if (mgcpdebug) {
02148       ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
02149          tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02150    }
02151    strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
02152    reqprep(&resp, p, "RQNT");
02153    add_header(&resp, "X", p->rqnt_ident); /* SC */
02154    switch (p->hookstate) {
02155    case MGCP_ONHOOK:
02156       add_header(&resp, "R", "L/hd(N)");
02157       break;
02158    case MGCP_OFFHOOK:
02159       add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
02160       break;
02161    }
02162    if (!ast_strlen_zero(tone)) {
02163       add_header(&resp, "S", tone);
02164    }
02165    /* SC: fill in new fields */
02166    resp.cmd = MGCP_CMD_RQNT;
02167    resp.trid = oseq;
02168    return send_request(p, NULL, &resp, oseq); /* SC */
02169 }

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

Definition at line 2171 of file chan_mgcp.c.

References add_header(), ast_strlen_zero(), ast_verbose(), mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmfmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::lastcallerid, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, n, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, send_request(), mgcp_endpoint::sub, t, mgcp_request::trid, and VERBOSE_PREFIX_3.

Referenced by mgcp_call(), and mgcp_hangup().

02172 {
02173    struct mgcp_request resp;
02174    char tone2[256];
02175    char *l, *n;
02176    time_t t;
02177    struct tm tm;
02178    struct mgcp_endpoint *p = sub->parent;
02179    
02180    time(&t);
02181    localtime_r(&t,&tm);
02182    n = callername;
02183    l = callernum;
02184    if (!n)
02185       n = "";
02186    if (!l)
02187       l = "";
02188 
02189    /* Keep track of last callerid for blacklist and callreturn */
02190    strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
02191 
02192    snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
02193       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02194    strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
02195    reqprep(&resp, p, "RQNT");
02196    add_header(&resp, "X", p->rqnt_ident); /* SC */
02197    switch (p->hookstate) {
02198    case MGCP_ONHOOK:
02199       add_header(&resp, "R", "L/hd(N)");
02200       break;
02201    case MGCP_OFFHOOK:
02202       add_header(&resp, "R",  (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
02203       break;
02204    }
02205    if (!ast_strlen_zero(tone2)) {
02206       add_header(&resp, "S", tone2);
02207    }
02208    if (mgcpdebug) {
02209       ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
02210          tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02211    }
02212    /* SC: fill in new fields */
02213    resp.cmd = MGCP_CMD_RQNT;
02214    resp.trid = oseq;
02215    return send_request(p, NULL, &resp, oseq);  /* SC */
02216 }

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

Definition at line 1950 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_message(), handle_request(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_refer(), handle_request_subscribe(), receive_message(), register_verify(), sip_indicate(), transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_diallednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), and transmit_tone().

01951 {
01952    struct mgcp_request resp;
01953    struct mgcp_endpoint *p = sub->parent;
01954    struct mgcp_response *mgr;
01955 
01956    respprep(&resp, p, msg, req, msgrest);
01957    mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
01958    if (mgr) {
01959       /* Store MGCP response in case we have to retransmit */
01960       memset(mgr, 0, sizeof(struct mgcp_response));
01961       sscanf(req->identifier, "%d", &mgr->seqno);
01962       time(&mgr->whensent);
01963       mgr->len = resp.len;
01964       memcpy(mgr->buf, resp.data, resp.len);
01965       mgr->buf[resp.len] = '\0';
01966       mgr->next = p->parent->responses;
01967       p->parent->responses = mgr;
01968    }
01969    return send_response(sub, &resp);
01970 }

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

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

Referenced by attempt_transfer(), ss_thread(), zt_handle_event(), and zt_hangup().

00523 {
00524    struct mgcp_endpoint *p = sub->parent;
00525    if (p->sub == sub) {
00526       ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00527       return -1;
00528    }
00529    ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00530 
00531    sub->owner = NULL;
00532    if (!ast_strlen_zero(sub->cxident)) {
00533       transmit_connection_del(sub);
00534    }
00535    sub->cxident[0] = '\0';
00536    sub->callid[0] = '\0';
00537    sub->cxmode = MGCP_CX_INACTIVE;
00538    sub->outgoing = 0;
00539    sub->alreadygone = 0;
00540    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00541    if (sub->rtp) {
00542       ast_rtp_destroy(sub->rtp);
00543       sub->rtp = NULL;
00544    }
00545    dump_cmd_queues(NULL, sub); /* SC */
00546    return 0;
00547 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 4305 of file chan_mgcp.c.

References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), cli_audit_endpoint, cli_debug, cli_mgcp_reload, cli_no_debug, cli_show_endpoints, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gateways, LOG_WARNING, mgcp_reload(), mgcp_reloading, mgcp_rtp, mgcp_tech, mgcpsock, monitor_thread, mgcp_gateway::next, mgcp_endpoint::next, prune_gateways(), and sched_context_destroy().

04306 {
04307    struct mgcp_endpoint *e;
04308    struct mgcp_gateway *g;
04309 
04310    /* Check to see if we're reloading */
04311    if (ast_mutex_trylock(&mgcp_reload_lock)) {
04312       ast_log(LOG_WARNING, "MGCP is currently reloading.  Unable to remove module.\n");
04313       return -1;
04314    } else {
04315       mgcp_reloading = 1;
04316       ast_mutex_unlock(&mgcp_reload_lock);
04317    }
04318 
04319    /* First, take us out of the channel loop */
04320    ast_channel_unregister(&mgcp_tech);
04321 
04322    /* Shut down the monitoring thread */
04323    if (!ast_mutex_lock(&monlock)) {
04324       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04325          pthread_cancel(monitor_thread);
04326          pthread_kill(monitor_thread, SIGURG);
04327          pthread_join(monitor_thread, NULL);
04328       }
04329       monitor_thread = AST_PTHREADT_STOP;
04330       ast_mutex_unlock(&monlock);
04331    } else {
04332       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04333       /* We always want to leave this in a consistent state */
04334       ast_channel_register(&mgcp_tech);
04335       mgcp_reloading = 0;
04336       mgcp_reload(0, 0, NULL);
04337       return -1;
04338    }
04339 
04340    if (!ast_mutex_lock(&gatelock)) {
04341       g = gateways;
04342       while (g) {
04343          g->delme = 1;
04344          e = g->endpoints;
04345          while (e) {
04346             e->delme = 1;
04347             e = e->next;
04348          }
04349          g = g->next;
04350       }
04351 
04352       prune_gateways();
04353       ast_mutex_unlock(&gatelock);
04354    } else {
04355       ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04356       /* We always want to leave this in a consistent state */
04357       ast_channel_register(&mgcp_tech);
04358       /* Allow the monitor to restart */
04359       monitor_thread = AST_PTHREADT_NULL;
04360       mgcp_reloading = 0;
04361       mgcp_reload(0, 0, NULL);
04362       return -1;
04363    }
04364 
04365    close(mgcpsock);
04366    ast_rtp_proto_unregister(&mgcp_rtp);
04367    ast_cli_unregister(&cli_show_endpoints);
04368    ast_cli_unregister(&cli_audit_endpoint);
04369    ast_cli_unregister(&cli_debug);
04370    ast_cli_unregister(&cli_no_debug);
04371    ast_cli_unregister(&cli_mgcp_reload);
04372    sched_context_destroy(sched);
04373 
04374    return 0;
04375 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 4377 of file chan_mgcp.c.

References usecnt.

04378 {
04379    return usecnt;
04380 }


Variable Documentation

struct in_addr __ourip [static]

Definition at line 272 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 234 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 240 of file chan_mgcp.c.

Referenced by build_gateway().

int amaflags = 0 [static]

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

struct sockaddr_in bindaddr [static]

Definition at line 473 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 215 of file chan_mgcp.c.

Referenced by build_gateway().

int callwaiting = 0 [static]

Definition at line 207 of file chan_mgcp.c.

Referenced by build_gateway().

int cancallforward = 0 [static]

Definition at line 224 of file chan_mgcp.c.

Referenced by build_gateway().

int canreinvite = CANREINVITE [static]

Definition at line 228 of file chan_mgcp.c.

Referenced by build_gateway().

int capability = AST_FORMAT_ULAW [static]

Definition at line 268 of file chan_mgcp.c.

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

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 184 of file chan_mgcp.c.

Referenced by build_gateway(), builtin_atxfer(), check_access(), misdn_new(), monitor_handle_notowned(), and vpb_new().

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 183 of file chan_mgcp.c.

Referenced by build_gateway(), builtin_atxfer(), check_access(), misdn_new(), monitor_handle_notowned(), and vpb_new().

struct ast_cli_entry cli_audit_endpoint [static]

Initial value:

 
   { { "mgcp", "audit", "endpoint", NULL }, mgcp_audit_endpoint, "Audit specified MGCP endpoint", audit_endpoint_usage }

Definition at line 1180 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_debug [static]

Initial value:

   { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage }

Definition at line 3971 of file chan_mgcp.c.

struct ast_cli_entry cli_mgcp_reload [static]

Initial value:

   { { "mgcp", "reload", NULL }, mgcp_reload, "Reload MGCP configuration", mgcp_reload_usage }

Definition at line 3975 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_no_debug [static]

Initial value:

   { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage }

Definition at line 3973 of file chan_mgcp.c.

struct ast_cli_entry cli_show_endpoints [static]

Initial value:

 
   { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage }

Definition at line 1119 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

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

Definition at line 139 of file chan_mgcp.c.

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

Definition at line 179 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 195 of file chan_mgcp.c.

Referenced by build_gateway().

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 196 of file chan_mgcp.c.

Referenced by build_gateway().

char debug_usage[] [static]

Initial value:

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

Definition at line 3959 of file chan_mgcp.c.

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

Definition at line 136 of file chan_mgcp.c.

int dtmfmode = 0 [static]

Definition at line 186 of file chan_mgcp.c.

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

int firstdigittimeout = 16000 [static]

Definition at line 248 of file chan_mgcp.c.

Referenced by disa_exec(), and mgcp_ss().

struct mgcp_gateway * gateways [static]

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

int gendigittimeout = 8000 [static]

Definition at line 251 of file chan_mgcp.c.

Referenced by mgcp_ss().

int immediate = 0 [static]

Definition at line 205 of file chan_mgcp.c.

Referenced by build_gateway().

struct io_context* io [static]

Definition at line 278 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 181 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 236 of file chan_mgcp.c.

Referenced by action_mailboxcount(), action_mailboxstatus(), build_gateway(), disa_exec(), handle_request_subscribe(), and realtime_directory().

int matchdigittimeout = 3000 [static]

Definition at line 254 of file chan_mgcp.c.

Referenced by mgcp_ss().

char* mgcp_cxmodes[] [static]

Definition at line 160 of file chan_mgcp.c.

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

char mgcp_reload_usage[] [static]

Initial value:

"Usage: mgcp reload\n"
"       Reloads MGCP configuration from mgcp.conf\n"

Definition at line 3967 of file chan_mgcp.c.

int mgcp_reloading = 0 [static]

Definition at line 467 of file chan_mgcp.c.

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

struct ast_rtp_protocol mgcp_rtp [static]

Initial value:

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

Definition at line 3935 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 500 of file chan_mgcp.c.

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

int mgcpdebug = 0 [static]

Definition at line 275 of file chan_mgcp.c.

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

int mgcpsock = -1 [static]

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

Referenced by reload_config().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 264 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

Definition at line 182 of file chan_mgcp.c.

Referenced by build_gateway(), and read_config().

int nat = 0 [static]

Definition at line 187 of file chan_mgcp.c.

Referenced by build_gateway().

char no_debug_usage[] [static]

Initial value:

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

Definition at line 3963 of file chan_mgcp.c.

int nonCodecCapability = AST_RTP_DTMF [static]

Definition at line 269 of file chan_mgcp.c.

Referenced by process_sdp().

unsigned int oseq [static]

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

Referenced by ast_find_ourip(), and reload_config().

int ourport [static]

Definition at line 273 of file chan_mgcp.c.

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

struct sched_context* sched [static]

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

int singlepath = 0 [static]

Definition at line 226 of file chan_mgcp.c.

Referenced by build_gateway().

int slowsequence = 0 [static]

Definition at line 217 of file chan_mgcp.c.

Referenced by build_gateway().

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

Definition at line 138 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 219 of file chan_mgcp.c.

Referenced by build_gateway().

int tos = 0 [static]

Definition at line 203 of file chan_mgcp.c.

int transfer = 0 [static]

Definition at line 222 of file chan_mgcp.c.

Referenced by build_gateway(), and leave_voicemail().

const char type[] = "MGCP" [static]

Definition at line 137 of file chan_mgcp.c.

int usecnt = 0 [static]

Definition at line 242 of file chan_mgcp.c.


Generated on Mon Sep 18 09:14:20 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7