Sun Aug 6 15:06:03 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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"

Include dependency graph for chan_mgcp.c:

Go to the source code of this file.

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 const 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(), send_request(), and transmit_connect_with_sdp().

#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(), transmit_modify_request(), and transmit_modify_with_sdp().

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

References mgcp_request::header.

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

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

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, LOG_WARNING, and mgcpsock.

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 1844 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_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_invite(), transmit_modify_request(), transmit_modify_with_sdp(), 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().

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

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

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

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

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

Definition at line 1968 of file chan_mgcp.c.

References add_line(), AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_get_peer(), ast_rtp_get_us(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, ast_verbose(), mgcp_endpoint::capability, mgcp_response::len, LOG_WARNING, mgcpdebug, mgcp_endpoint::nonCodecCapability, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, t, and mgcp_subchannel::tmpdest.

Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp().

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

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

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

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

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

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

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

References desc.

04381 {
04382    return (char *) desc;
04383 }

static void destroy_endpoint struct mgcp_endpoint e  )  [static]
 

Definition at line 3972 of file chan_mgcp.c.

References ast_dsp_free(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, dump_cmd_queues(), dump_queue(), free, mgcp_endpoint::lock, mgcp_subchannel::lock, mgcp_subchannel::magic, MAX_SUBS, mgcp_queue_hangup(), mgcp_subchannel::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and transmit_connection_del().

Referenced by prune_gateways().

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

static void destroy_gateway struct mgcp_gateway g  )  [static]
 

Definition at line 4014 of file chan_mgcp.c.

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

Referenced by prune_gateways().

04015 {
04016    if (g->ha)
04017       ast_free_ha(g->ha);
04018 
04019    dump_queue(g, NULL);
04020 
04021    free (g);
04022 }

static void* do_monitor void *  data  )  [static]
 

Definition at line 3358 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(), gateways, has_voicemail(), mgcp_do_reload(), MGCP_ONHOOK, mgcp_reloading, mgcpsock, mgcpsock_read(), mgcpsock_read_id, option_verbose, transmit_notify_request(), TYPE_LINE, and VERBOSE_PREFIX_1.

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

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

Definition at line 2307 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 destroy_endpoint(), handle_request(), handle_response(), and unalloc_sub().

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

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_endpoint(), 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 3235 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().

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

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

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

Referenced by agi_handle_command(), handle_response(), and handle_showagi().

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

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

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

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

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

Definition at line 1518 of file chan_mgcp.c.

References s.

Referenced by handle_response().

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

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

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

01512 {
01513    int start = 0;
01514    return __get_header(req, name, &start);
01515 }

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

Definition at line 1463 of file chan_mgcp.c.

References get_sdp_by_line(), and mgcp_request::line.

Referenced by process_sdp().

01464 {
01465    int x;
01466    int len = strlen(name);
01467    char *r;
01468 
01469    for (x=0; x<req->lines; x++) {
01470       r = get_sdp_by_line(req->line[x], name, len);
01471       if (r[0] != '\0') return r;
01472    }
01473    return "";
01474 }

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

Definition at line 1453 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01454 {
01455    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01456       char* r = line + nameLen + 1;
01457       while (*r && (*r < 33)) ++r;
01458       return r;
01459    }
01460    return "";
01461 }

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

Definition at line 1481 of file chan_mgcp.c.

References get_sdp_by_line(), and mgcp_request::line.

Referenced by process_sdp().

01482 {
01483    int len = strlen(name);
01484    char *r;
01485    while (*iterator < req->lines) {
01486       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01487       if (r[0] != '\0') return r;
01488    }
01489    return "";
01490 }

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

Definition at line 2874 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(), t, transmit_modify_request(), and transmit_notify_request().

Referenced by handle_request().

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

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

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

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

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 2373 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_subchannel::id, mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), n, mgcp_gateway::name, option_verbose, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), 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().

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

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

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

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

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

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

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

References ASTERISK_GPL_KEY.

04376 {
04377    return ASTERISK_GPL_KEY;
04378 }

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

References ast_channel_register(), ast_cli_register(), ast_log(), ast_rtp_proto_register(), io_context_create(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), and type.

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

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(), 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 3934 of file chan_mgcp.c.

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

03935 {
03936    if (argc != 2)
03937       return RESULT_SHOWUSAGE;
03938    mgcpdebug = 1;
03939    ast_cli(fd, "MGCP Debugging Enabled\n");
03940    return RESULT_SUCCESS;
03941 }

static int mgcp_do_reload void   )  [static]
 

Definition at line 4274 of file chan_mgcp.c.

References reload_config().

Referenced by do_monitor().

04275 {
04276    reload_config();
04277    return 0;
04278 }

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

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

03908 {
03909    struct mgcp_subchannel *sub;
03910    sub = chan->tech_pvt;
03911    if (sub && sub->rtp && sub->parent->canreinvite)
03912       return sub->rtp;
03913    return NULL;
03914 }

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, 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, 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_set_callerid(), 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, mgcp_endpoint::cid_name, 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_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, 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       ast_set_callerid(tmp, i->cid_num, i->cid_name, i->cid_num);
01432       if (!i->adsi)
01433          tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01434       tmp->priority = 1;
01435       if (state != AST_STATE_DOWN) {
01436          if (ast_pbx_start(tmp)) {
01437             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01438             ast_hangup(tmp);
01439             tmp = NULL;
01440          }
01441       }
01442       /* SC: verbose level check */
01443       if (option_verbose > 2) {
01444          ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01445             tmp->name, ast_state2str(state));
01446       }
01447    } else {
01448       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01449    }
01450    return tmp;
01451 }

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

Definition at line 3943 of file chan_mgcp.c.

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

03944 {
03945    if (argc != 3)
03946       return RESULT_SHOWUSAGE;
03947    mgcpdebug = 0;
03948    ast_cli(fd, "MGCP Debugging Disabled\n");
03949    return RESULT_SUCCESS;
03950 }

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(), destroy_endpoint(), 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 4280 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().

04281 {
04282    ast_mutex_lock(&mgcp_reload_lock);
04283    if (mgcp_reloading) {
04284       ast_verbose("Previous mgcp reload not yet done\n");
04285    } else
04286       mgcp_reloading = 1;
04287    ast_mutex_unlock(&mgcp_reload_lock);
04288    restart_monitor();
04289    return 0;
04290 }

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

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

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

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

References ast_channel::tech_pvt, and transmit_modify_with_sdp().

03917 {
03918    /* XXX Is there such thing as video support with MGCP? XXX */
03919    struct mgcp_subchannel *sub;
03920    sub = chan->tech_pvt;
03921    if (sub) {
03922       transmit_modify_with_sdp(sub, rtp, codecs);
03923       return 0;
03924    }
03925    return -1;
03926 }

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 2563 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, ast_callerid::cid_ani, 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(), ast_channel::tech_pvt, transmit_notify_request(), and VERBOSE_PREFIX_3.

Referenced by handle_hd_hf().

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

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 3267 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, mgcpdebug, 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().

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

static void parse struct mgcp_request req  )  [static]
 

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

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

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

Definition at line 1758 of file chan_mgcp.c.

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

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

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

static void prune_gateways void   )  [static]
 

Definition at line 4024 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

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

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

References mgcp_reload().

04293 {
04294    mgcp_reload(0, 0, NULL);
04295    return 0;
04296 }

static int reload_config void   )  [static]
 

Definition at line 4067 of file chan_mgcp.c.

References __ourip, 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_gateway::delme, dtmfmode, mgcp_gateway::endpoints, format, gateways, hp, 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_endpoint::next, mgcp_gateway::next, ast_variable::next, option_verbose, ourhost, ourport, prune_gateways(), tos, transmit_audit_endpoint(), ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

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

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

Definition at line 1935 of file chan_mgcp.c.

References init_req(), and oseq.

Referenced by transmit_audit_endpoint(), transmit_connect_with_sdp(), 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_modify_with_sdp(), 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().

01936 {
01937    memset(req, 0, sizeof(struct mgcp_request));
01938    oseq++;
01939    if (oseq > 999999999)
01940       oseq = 1;
01941    init_req(p, req, verb);
01942    return 0;
01943 }

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, mgcpdebug, mgcp_endpoint::parent, and mgcp_subchannel::parent.

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

01929 {
01930    memset(resp, 0, sizeof(*resp));
01931    init_resp(resp, msg, req, msgrest);
01932    return 0;
01933 }

static int restart_monitor void   )  [static]
 

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

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

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

Referenced by process_sdp().

01477 {
01478    *iterator = 0;
01479 }

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_connect_with_sdp(), 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_modify_with_sdp(), 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, mgcpdebug, mgcp_endpoint::parent, and mgcp_subchannel::parent.

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

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

static int transmit_audit_endpoint struct mgcp_endpoint p  )  [static]
 

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

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

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

Definition at line 2103 of file chan_mgcp.c.

References add_header(), add_sdp(), AST_FORMAT_MAX_AUDIO, ast_rtp_lookup_mime_subtype(), ast_rtp_offered_from_local(), ast_verbose(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_cxmodes, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::rtp, send_request(), mgcp_request::trid, mgcp_subchannel::txident, and VERBOSE_PREFIX_3.

Referenced by start_rtp().

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

static int transmit_connection_del struct mgcp_subchannel sub  )  [static]
 

Definition at line 2261 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, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, mgcp_subchannel::txident, and VERBOSE_PREFIX_3.

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

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

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

Definition at line 2285 of file chan_mgcp.c.

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

Referenced by handle_response().

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

static int transmit_modify_request struct mgcp_subchannel sub  )  [static]
 

Definition at line 2213 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, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::rtp, send_request(), mgcp_request::trid, mgcp_subchannel::txident, and VERBOSE_PREFIX_3.

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

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

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

Definition at line 2062 of file chan_mgcp.c.

References add_header(), add_sdp(), AST_FORMAT_MAX_AUDIO, ast_rtp_get_peer(), ast_rtp_lookup_mime_subtype(), ast_rtp_offered_from_local(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, capability, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, MGCP_CMD_MDCX, mgcp_cxmodes, oseq, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::rtp, send_request(), mgcp_subchannel::tmpdest, mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by handle_response(), and mgcp_set_rtp_peer().

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

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

Definition at line 2137 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, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, send_request(), 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().

02138 {
02139    struct mgcp_request resp;
02140    struct mgcp_endpoint *p = sub->parent;
02141 
02142    if (mgcpdebug) {
02143       ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
02144          tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02145    }
02146    strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
02147    reqprep(&resp, p, "RQNT");
02148    add_header(&resp, "X", p->rqnt_ident); /* SC */
02149    switch (p->hookstate) {
02150    case MGCP_ONHOOK:
02151       add_header(&resp, "R", "L/hd(N)");
02152       break;
02153    case MGCP_OFFHOOK:
02154       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)");
02155       break;
02156    }
02157    if (!ast_strlen_zero(tone)) {
02158       add_header(&resp, "S", tone);
02159    }
02160    /* SC: fill in new fields */
02161    resp.cmd = MGCP_CMD_RQNT;
02162    resp.trid = oseq;
02163    return send_request(p, NULL, &resp, oseq); /* SC */
02164 }

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

Definition at line 2166 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, mgcpdebug, n, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, send_request(), t, mgcp_request::trid, and VERBOSE_PREFIX_3.

Referenced by mgcp_call(), and mgcp_hangup().

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

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

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

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

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

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 4298 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(), gateways, LOG_WARNING, mgcp_reload(), mgcp_reloading, mgcpsock, monitor_thread, prune_gateways(), and sched_context_destroy().

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

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

References usecnt.

04371 {
04372    return usecnt;
04373 }


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(), mkintf(), and setup_zap().

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_device(), build_gateway(), mkintf(), and setup_zap().

int callwaiting = 0 [static]
 

Definition at line 207 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), mkintf(), and setup_zap().

int cancallforward = 0 [static]
 

Definition at line 224 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), mkintf(), and setup_zap().

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_device(), build_gateway(), iax2_call(), mgcp_new(), mgcp_request(), process_sdp(), reload_config(), set_config(), set_local_capabilities(), skinny_new(), skinny_request(), and transmit_modify_with_sdp().

char cid_name[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 184 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), builtin_atxfer(), check_access(), load_module(), misdn_new(), mkif(), mkintf(), monitor_handle_notowned(), setup_zap(), vpb_new(), and zt_handle_event().

char cid_num[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 183 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), builtin_atxfer(), check_access(), load_module(), misdn_new(), mkif(), mkintf(), monitor_handle_notowned(), setup_zap(), vpb_new(), and zt_handle_event().

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.

struct ast_cli_entry cli_debug [static]
 

Initial value:

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

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

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

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_device(), build_gateway(), mkintf(), and setup_zap().

ast_group_t cur_pickupgroup = 0 [static]
 

Definition at line 196 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), mkintf(), and setup_zap().

char debug_usage[] [static]
 

Initial value:

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

Definition at line 3952 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(), load_module(), mkif(), reload_config(), and set_local_capabilities().

int firstdigittimeout = 16000 [static]
 

Definition at line 248 of file chan_mgcp.c.

Referenced by disa_exec(), mgcp_ss(), skinny_ss(), and ss_thread().

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(), skinny_ss(), and ss_thread().

int immediate = 0 [static]
 

Definition at line 205 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), build_port_config(), cb_events(), fill_defaults(), free_port_cfg(), misdn_cfg_get(), misdn_cfg_get_config_string(), mkintf(), and setup_zap().

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_device(), build_gateway(), disa_exec(), handle_request_subscribe(), mkintf(), realtime_directory(), and setup_zap().

int matchdigittimeout = 3000 [static]
 

Definition at line 254 of file chan_mgcp.c.

Referenced by mgcp_ss(), skinny_ss(), and ss_thread().

char* mgcp_cxmodes[] [static]
 

Definition at line 160 of file chan_mgcp.c.

Referenced by transmit_connect_with_sdp(), transmit_connection_del(), transmit_modify_request(), transmit_modify_with_sdp(), 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 3960 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 3928 of file chan_mgcp.c.

const struct ast_channel_tech mgcp_tech [static]
 

Definition at line 500 of file chan_mgcp.c.

int mgcpdebug = 0 [static]
 

Definition at line 275 of file chan_mgcp.c.

Referenced by add_sdp(), find_command(), handle_request(), mgcp_audit_endpoint(), mgcp_call(), mgcp_do_debug(), mgcp_hangup(), mgcp_indicate(), mgcp_no_debug(), mgcpsock_read(), parse(), process_sdp(), resend_response(), retrans_pkt(), send_request(), send_response(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

int mgcpsock = -1 [static]
 

Definition at line 471 of file chan_mgcp.c.

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

int* mgcpsock_read_id = NULL [static]
 

Definition at line 3356 of file chan_mgcp.c.

Referenced by do_monitor(), and 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_device(), build_gateway(), mkintf(), and setup_zap().

int nat = 0 [static]
 

Definition at line 187 of file chan_mgcp.c.

Referenced by build_device(), and 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 3956 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_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), 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(), handle_message(), and reload_config().

int ourport [static]
 

Definition at line 273 of file chan_mgcp.c.

Referenced by build_contact(), build_via(), handle_message(), 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_device(), build_gateway(), mkintf(), and setup_zap().

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_device(), build_gateway(), leave_voicemail(), mkintf(), and setup_zap().

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 Sun Aug 6 15:06:06 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2