Mon Mar 20 08:25:52 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"

Go to the source code of this file.

Data Structures

struct  mgcp_endpoint
struct  mgcp_gateway
struct  mgcp_message
struct  mgcp_request
struct  mgcp_response
struct  mgcp_subchannel

Defines

#define CANREINVITE   1
#define DEFAULT_EXPIRY   120
#define DEFAULT_MGCP_CA_PORT   2727
#define DEFAULT_MGCP_GW_PORT   2427
#define DEFAULT_RETRANS   1000
#define INADDR_NONE   (in_addr_t)(-1)
#define IPTOS_MINCOST   0x02
#define MAX_EXPIRY   3600
#define MAX_RETRANS   5
#define MAX_SUBS   2
#define MGCP_CMD_AUCX   7
#define MGCP_CMD_AUEP   6
#define MGCP_CMD_CRCX   1
#define MGCP_CMD_DLCX   3
#define MGCP_CMD_EPCF   0
#define MGCP_CMD_MDCX   2
#define MGCP_CMD_NTFY   5
#define MGCP_CMD_RQNT   4
#define MGCP_CMD_RSIP   8
#define MGCP_CX_CONF   3
#define MGCP_CX_CONFERENCE   3
#define MGCP_CX_INACTIVE   4
#define MGCP_CX_MUTE   4
#define MGCP_CX_RECVONLY   1
#define MGCP_CX_SENDONLY   0
#define MGCP_CX_SENDRECV   2
#define MGCP_DTMF_HYBRID   (1 << 2)
#define MGCP_DTMF_INBAND   (1 << 1)
#define MGCP_DTMF_RFC2833   (1 << 0)
#define MGCP_MAX_HEADERS   64
#define MGCP_MAX_LINES   64
#define MGCP_MAX_PACKET   1500
#define MGCP_OFFHOOK   2
#define MGCP_ONHOOK   1
#define MGCP_SUBCHANNEL_MAGIC   "!978!"
#define MGCPDUMPER
#define RESPONSE_TIMEOUT   30
#define SUB_ALT   1
#define SUB_REAL   0
#define TYPE_LINE   2
#define TYPE_TRUNK   1

Functions

char * __get_header (struct mgcp_request *req, char *name, int *start)
int __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len)
int add_header (struct mgcp_request *req, char *var, char *value)
int add_line (struct mgcp_request *req, char *line)
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)
int attempt_transfer (struct mgcp_endpoint *p)
mgcp_gatewaybuild_gateway (char *cat, struct ast_variable *v)
char * control2str (int ind)
char * description ()
 Provides a description of the module.
void destroy_endpoint (struct mgcp_endpoint *e)
void destroy_gateway (struct mgcp_gateway *g)
void * do_monitor (void *data)
void dump_cmd_queues (struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
void dump_queue (struct mgcp_gateway *gw, struct mgcp_endpoint *p)
int find_and_retrans (struct mgcp_subchannel *sub, struct mgcp_request *req)
mgcp_requestfind_command (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request **queue, ast_mutex_t *l, int ident)
mgcp_subchannelfind_subchannel_and_lock (char *name, int msgid, struct sockaddr_in *sin)
char * get_csv (char *c, int *len, char **next)
char * get_header (struct mgcp_request *req, char *name)
char * get_sdp (struct mgcp_request *req, char *name)
char * get_sdp_by_line (char *line, char *name, int nameLen)
char * get_sdp_iterate (int *iterator, struct mgcp_request *req, char *name)
void handle_hd_hf (struct mgcp_subchannel *sub, char *ev)
int handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
void handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
int has_voicemail (struct mgcp_endpoint *p)
int init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
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.
int mgcp_answer (struct ast_channel *ast)
int mgcp_audit_endpoint (int fd, int argc, char *argv[])
int mgcp_call (struct ast_channel *ast, char *dest, int timeout)
int mgcp_do_debug (int fd, int argc, char *argv[])
int mgcp_do_reload (void)
int mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
ast_rtpmgcp_get_rtp_peer (struct ast_channel *chan)
int mgcp_hangup (struct ast_channel *ast)
int mgcp_indicate (struct ast_channel *ast, int ind)
ast_channelmgcp_new (struct mgcp_subchannel *sub, int state)
int mgcp_no_debug (int fd, int argc, char *argv[])
int mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
void mgcp_queue_control (struct mgcp_subchannel *sub, int control)
void mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f)
void mgcp_queue_hangup (struct mgcp_subchannel *sub)
ast_framemgcp_read (struct ast_channel *ast)
int mgcp_reload (int fd, int argc, char *argv[])
ast_channelmgcp_request (const char *type, int format, void *data, int *cause)
ast_framemgcp_rtp_read (struct mgcp_subchannel *sub)
int mgcp_senddigit (struct ast_channel *ast, char digit)
int mgcp_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
int mgcp_show_endpoints (int fd, int argc, char *argv[])
void * mgcp_ss (void *data)
int mgcp_write (struct ast_channel *ast, struct ast_frame *frame)
int mgcpsock_read (int *id, int fd, short events, void *ignore)
void parse (struct mgcp_request *req)
int process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req)
void prune_gateways (void)
int reload (void)
 Reload stuff.
int reload_config (void)
int reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
int resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp)
int respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
int restart_monitor (void)
int retrans_pkt (void *data)
void sdpLineNum_iterator_init (int *iterator)
int send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
int send_response (struct mgcp_subchannel *sub, struct mgcp_request *req)
void start_rtp (struct mgcp_subchannel *sub)
int transmit_audit_endpoint (struct mgcp_endpoint *p)
int transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp)
int transmit_connection_del (struct mgcp_subchannel *sub)
int transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident)
int transmit_modify_request (struct mgcp_subchannel *sub)
int transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
int transmit_notify_request (struct mgcp_subchannel *sub, char *tone)
int transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
int transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
int unalloc_sub (struct mgcp_subchannel *sub)
int unload_module ()
 Cleanup all module structures, sockets, etc.
int usecount ()
 Provides a usecount.

Variables

in_addr __ourip
char accountcode [AST_MAX_ACCOUNT_CODE] = ""
int adsi = 0
int amaflags = 0
char audit_endpoint_usage []
sockaddr_in bindaddr
int callreturn = 0
int callwaiting = 0
int cancallforward = 0
int canreinvite = CANREINVITE
int capability = AST_FORMAT_ULAW
char cid_name [AST_MAX_EXTENSION] = ""
char cid_num [AST_MAX_EXTENSION] = ""
ast_cli_entry cli_audit_endpoint
ast_cli_entry cli_debug
ast_cli_entry cli_mgcp_reload
ast_cli_entry cli_no_debug
ast_cli_entry cli_show_endpoints
const char config [] = "mgcp.conf"
char context [AST_MAX_EXTENSION] = "default"
ast_group_t cur_callergroup = 0
ast_group_t cur_pickupgroup = 0
char debug_usage []
const char desc [] = "Media Gateway Control Protocol (MGCP)"
int dtmfmode = 0
int firstdigittimeout = 16000
mgcp_gatewaygateways
int gendigittimeout = 8000
int immediate = 0
io_contextio
char language [MAX_LANGUAGE] = ""
char mailbox [AST_MAX_EXTENSION]
int matchdigittimeout = 3000
char * mgcp_cxmodes []
char mgcp_reload_usage []
int mgcp_reloading = 0
ast_rtp_protocol mgcp_rtp
const struct ast_channel_tech mgcp_tech
int mgcpdebug = 0
int mgcpsock = -1
int * mgcpsock_read_id = NULL
pthread_t monitor_thread = AST_PTHREADT_NULL
char musicclass [MAX_MUSICCLASS] = ""
int nat = 0
char no_debug_usage []
int nonCodecCapability = AST_RTP_DTMF
unsigned int oseq
char ourhost [MAXHOSTNAMELEN]
int ourport
sched_contextsched
char show_endpoints_usage []
int singlepath = 0
int slowsequence = 0
const char tdesc [] = "Media Gateway Control Protocol (MGCP)"
int threewaycalling = 0
int tos = 0
int transfer = 0
const char type [] = "MGCP"
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.

#define DEFAULT_EXPIRY   120
 

Definition at line 128 of file chan_mgcp.c.

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

#define INADDR_NONE   (in_addr_t)(-1)
 

Definition at line 133 of file chan_mgcp.c.

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

#define MAX_SUBS   2
 

Definition at line 333 of file chan_mgcp.c.

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

#define MGCP_CMD_CRCX   1
 

Definition at line 170 of file chan_mgcp.c.

Referenced by send_request().

#define MGCP_CMD_DLCX   3
 

Definition at line 172 of file chan_mgcp.c.

Referenced by send_request().

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

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

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

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

#define MGCP_CX_MUTE   4
 

Definition at line 157 of file chan_mgcp.c.

#define MGCP_CX_RECVONLY   1
 

Definition at line 153 of file chan_mgcp.c.

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

#define MGCP_DTMF_HYBRID   (1 << 2)
 

Definition at line 143 of file chan_mgcp.c.

#define MGCP_DTMF_INBAND   (1 << 1)
 

Definition at line 142 of file chan_mgcp.c.

Referenced by mgcp_new(), 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.

#define MGCP_MAX_HEADERS   64
 

Definition at line 282 of file chan_mgcp.c.

Referenced by parse().

#define MGCP_MAX_LINES   64
 

Definition at line 283 of file chan_mgcp.c.

Referenced by 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 mgcp_call(), 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 mgcp_call(), 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.

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

#define TYPE_TRUNK   1
 

Definition at line 377 of file chan_mgcp.c.


Function Documentation

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

Definition at line 1495 of file chan_mgcp.c.

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

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

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 }

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

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

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

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

Definition at line 1869 of file chan_mgcp.c.

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

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

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

Definition at line 1971 of file chan_mgcp.c.

References add_line(), ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_verbose(), mgcp_endpoint::capability, LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, and mgcp_subchannel::tmpdest.

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

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   ) 
 

int attempt_transfer struct mgcp_endpoint p  )  [static]
 

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

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

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

Definition at line 3554 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, mgcp_endpoint::capability, mgcp_endpoint::cid_name, cid_name, mgcp_endpoint::cid_num, cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, context, cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, 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, mgcp_gateway::ha, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, immediate, mgcp_gateway::isnamedottedip, mgcp_endpoint::language, language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, mailbox, malloc, 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, mgcp_endpoint::needaudit, 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_gateway::retransid, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, sched, 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, ast_variable::value, VERBOSE_PREFIX_3, and mgcp_gateway::wcardep.

Referenced by reload_config().

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

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.

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

04407 {
04408    return (char *) desc;
04409 }

void destroy_endpoint struct mgcp_endpoint e  )  [static]
 

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

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

void destroy_gateway struct mgcp_gateway g  )  [static]
 

Definition at line 4040 of file chan_mgcp.c.

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

Referenced by prune_gateways().

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

void* do_monitor void *  data  )  [static]
 

Definition at line 3384 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(), has_voicemail(), io, mgcp_do_reload(), mgcp_reloading, mgcpsock, mgcpsock_read(), mgcpsock_read_id, mgcp_subchannel::next, option_verbose, sched, transmit_notify_request(), and VERBOSE_PREFIX_1.

Referenced by restart_monitor().

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

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

Definition at line 2310 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, and mgcp_endpoint::sub.

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

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

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 }

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

Definition at line 3261 of file chan_mgcp.c.

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

Referenced by mgcpsock_read().

03262 {
03263    int seqno=0;
03264    time_t now;
03265    struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03266    time(&now);
03267    if (sscanf(req->identifier, "%d", &seqno) != 1) 
03268       seqno = 0;
03269    cur = sub->parent->parent->responses;
03270    while(cur) {
03271       next = cur->next;
03272       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03273          /* Delete this entry */
03274          if (prev)
03275             prev->next = next;
03276          else
03277             sub->parent->parent->responses = next;
03278          free(cur);
03279       } else {
03280          if (seqno == cur->seqno)
03281             answer = cur;
03282          prev = cur;
03283       }
03284       cur = next;
03285    }
03286    if (answer) {
03287       resend_response(sub, answer);
03288       return 1;
03289    }
03290    return 0;
03291 }

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

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

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

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

Definition at line 1542 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, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_DEBUG, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, name, mgcp_endpoint::next, mgcp_subchannel::next, mgcp_gateway::next, option_verbose, mgcp_gateway::ourip, mgcp_endpoint::sub, and VERBOSE_PREFIX_3.

Referenced by mgcp_request(), and mgcpsock_read().

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

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

Definition at line 1521 of file chan_mgcp.c.

References s.

Referenced by handle_response().

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

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

Definition at line 1514 of file chan_mgcp.c.

References __get_header(), and name.

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

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

Definition at line 1466 of file chan_mgcp.c.

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

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

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

Definition at line 1456 of file chan_mgcp.c.

References name.

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

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

Definition at line 1484 of file chan_mgcp.c.

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

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

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

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

Referenced by handle_request().

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

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

Definition at line 2987 of file chan_mgcp.c.

References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_inet_ntoa(), ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, 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_queue_frame(), mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::next, mgcp_subchannel::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.

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

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

Definition at line 2376 of file chan_mgcp.c.

References ast_log(), ast_strlen_zero(), ast_verbose(), mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, dump_cmd_queues(), find_command(), free, get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_request::lines, LOG_NOTICE, LOG_WARNING, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, option_verbose, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), result, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), transmit_notify_request(), and VERBOSE_PREFIX_3.

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

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.

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

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

Definition at line 1909 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_gateway::name, mgcp_endpoint::name, oseq, and mgcp_endpoint::parent.

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

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

Definition at line 1892 of file chan_mgcp.c.

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

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

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

04402 {
04403    return ASTERISK_GPL_KEY;
04404 }

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

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

04266 {
04267    int res;
04268 
04269    sched = sched_context_create();
04270    if (!sched) {
04271       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04272       return -1;
04273    }
04274    io = io_context_create();
04275    if (!io) {
04276       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04277       return -1;
04278    }
04279 
04280    if (!(res = reload_config())) {
04281       /* Make sure we can register our mgcp channel type */
04282       if (ast_channel_register(&mgcp_tech)) {
04283          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
04284          return -1;
04285       }
04286       ast_rtp_proto_register(&mgcp_rtp);
04287       ast_cli_register(&cli_show_endpoints);
04288       ast_cli_register(&cli_audit_endpoint);
04289       ast_cli_register(&cli_debug);
04290       ast_cli_register(&cli_no_debug);
04291       ast_cli_register(&cli_mgcp_reload);
04292 
04293       /* And start the monitor for the first time */
04294       restart_monitor();
04295    }
04296 
04297    return res;
04298 }

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_gateway::name, mgcp_endpoint::name, ast_channel::name, 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 }

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, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, 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 }

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_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_OFFHOOK, MGCP_ONHOOK, 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, 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 }

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

Definition at line 3960 of file chan_mgcp.c.

References ast_cli(), and mgcpdebug.

03961 {
03962    if (argc != 2)
03963       return RESULT_SHOWUSAGE;
03964    mgcpdebug = 1;
03965    ast_cli(fd, "MGCP Debugging Enabled\n");
03966    return RESULT_SUCCESS;
03967 }

int mgcp_do_reload void   )  [static]
 

Definition at line 4300 of file chan_mgcp.c.

References reload_config().

Referenced by do_monitor().

04301 {
04302    reload_config();
04303    return 0;
04304 }

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 }

struct ast_rtp* mgcp_get_rtp_peer struct ast_channel chan  )  [static]
 

Definition at line 3933 of file chan_mgcp.c.

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

03934 {
03935    struct mgcp_subchannel *sub;
03936    sub = chan->tech_pvt;
03937    if (sub && sub->rtp && sub->parent->canreinvite)
03938       return sub->rtp;
03939    return NULL;
03940 }

int mgcp_hangup struct ast_channel ast  )  [static]
 

Definition at line 979 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_dsp_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_update_use_count(), ast_verbose(), mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_DEBUG, mgcp_subchannel::magic, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, 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, 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 }

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

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

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_best_codec(), ast_channel_alloc(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtp_fd(), ast_setstate(), ast_state2str(), ast_strlen_zero(), ast_update_use_count(), ast_verbose(), mgcp_endpoint::call_forward, ast_channel::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_name, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, mgcp_endpoint::context, ast_channel::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DTMF_DETECT, mgcp_endpoint::dtmfmode, mgcp_endpoint::exten, ast_channel::exten, ast_channel::fds, fmt, mgcp_subchannel::id, ast_channel::language, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_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, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, usecnt, 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       if (!ast_strlen_zero(i->cid_num))
01432          tmp->cid.cid_num = strdup(i->cid_num);
01433       if (!ast_strlen_zero(i->cid_name))
01434          tmp->cid.cid_name = strdup(i->cid_name);
01435       if (!i->adsi)
01436          tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01437       tmp->priority = 1;
01438       if (state != AST_STATE_DOWN) {
01439          if (ast_pbx_start(tmp)) {
01440             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01441             ast_hangup(tmp);
01442             tmp = NULL;
01443          }
01444       }
01445       /* SC: verbose level check */
01446       if (option_verbose > 2) {
01447          ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
01448             tmp->name, ast_state2str(state));
01449       }
01450    } else {
01451       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01452    }
01453    return tmp;
01454 }

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

Definition at line 3969 of file chan_mgcp.c.

References ast_cli(), and mgcpdebug.

03970 {
03971    if (argc != 3)
03972       return RESULT_SHOWUSAGE;
03973    mgcpdebug = 0;
03974    ast_cli(fd, "MGCP Debugging Disabled\n");
03975    return RESULT_SUCCESS;
03976 }

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, sched, mgcp_message::seqno, and tv.

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 }

void mgcp_queue_control struct mgcp_subchannel sub,
int  control
[static]
 

Definition at line 665 of file chan_mgcp.c.

References 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 }

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 }

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 }

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 }

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

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

04307 {
04308    ast_mutex_lock(&mgcp_reload_lock);
04309    if (mgcp_reloading) {
04310       ast_verbose("Previous mgcp reload not yet done\n");
04311    } else
04312       mgcp_reloading = 1;
04313    ast_mutex_unlock(&mgcp_reload_lock);
04314    restart_monitor();
04315    return 0;
04316 }

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

Definition at line 3499 of file chan_mgcp.c.

References ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strlen_zero(), ast_verbose(), mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, mgcp_endpoint::dnd, find_subchannel_and_lock(), has_voicemail(), mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), mgcp_subchannel::next, option_verbose, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), transmit_notify_request(), and VERBOSE_PREFIX_3.

Referenced by send_request().

03500 {
03501    int oldformat;
03502    struct mgcp_subchannel *sub;
03503    struct ast_channel *tmpc = NULL;
03504    char tmp[256];
03505    char *dest = data;
03506 
03507    oldformat = format;
03508    format &= capability;
03509    if (!format) {
03510       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03511       return NULL;
03512    }
03513    strncpy(tmp, dest, sizeof(tmp) - 1);
03514    if (ast_strlen_zero(tmp)) {
03515       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03516       return NULL;
03517    }
03518    sub = find_subchannel_and_lock(tmp, 0, NULL);
03519    if (!sub) {
03520       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03521       *cause = AST_CAUSE_UNREGISTERED;
03522       return NULL;
03523    }
03524    
03525    if (option_verbose > 2) {
03526       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
03527       ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 
03528          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03529    }
03530    /* Must be busy */
03531    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03532       ((!sub->parent->callwaiting) && (sub->owner)) ||
03533        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03534       if (sub->parent->hookstate == MGCP_ONHOOK) {
03535          if (has_voicemail(sub->parent)) {
03536             transmit_notify_request(sub,"L/vmwi(+)");
03537          } else {
03538             transmit_notify_request(sub,"L/vmwi(-)");
03539          }
03540       }
03541       *cause = AST_CAUSE_BUSY;
03542       ast_mutex_unlock(&sub->lock);
03543       return NULL;
03544    }
03545    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03546    ast_mutex_unlock(&sub->lock);
03547    if (!tmpc)
03548       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03549    restart_monitor();
03550    return tmpc;
03551 }

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_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, 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 }

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 }

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

References ast_channel::tech_pvt, and transmit_modify_with_sdp().

03943 {
03944    /* XXX Is there such thing as video support with MGCP? XXX */
03945    struct mgcp_subchannel *sub;
03946    sub = chan->tech_pvt;
03947    if (sub) {
03948       transmit_modify_with_sdp(sub, rtp, codecs);
03949       return 0;
03950    }
03951    return -1;
03952 }

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, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, mgcp_subchannel::owner, 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 }

void* mgcp_ss void *  data  )  [static]
 

Definition at line 2566 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_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_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmfmode, ast_channel::exten, free, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_channel::language, mgcp_endpoint::lastcallerid, LOG_DEBUG, LOG_WARNING, ast_channel::name, mgcp_subchannel::next, option_verbose, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), strdup, ast_channel::tech_pvt, transmit_notify_request(), and VERBOSE_PREFIX_3.

Referenced by handle_hd_hf().

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

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

Definition at line 1254 of file chan_mgcp.c.

References 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 }

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

Definition at line 3293 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(), mgcp_request::data, find_and_retrans(), find_subchannel_and_lock(), free, handle_request(), handle_response(), mgcp_request::len, mgcp_subchannel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_endpoint::parent, mgcp_subchannel::parent, parse(), result, mgcp_gateway::retransid, and sched.

Referenced by do_monitor().

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

void parse struct mgcp_request req  )  [static]
 

Definition at line 1660 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, mgcp_request::verb, and mgcp_request::version.

Referenced by mgcpsock_read().

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

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

Definition at line 1761 of file chan_mgcp.c.

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

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

void prune_gateways void   )  [static]
 

Definition at line 4050 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

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

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

References mgcp_reload().

04319 {
04320    mgcp_reload(0, 0, NULL);
04321    return 0;
04322 }

int reload_config void   )  [static]
 

Definition at line 4093 of file chan_mgcp.c.

References __ourip, ahp, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_variable_browse(), ast_verbose(), bindaddr, build_gateway(), capability, cfg, config, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, dtmfmode, mgcp_gateway::endpoints, gateways, hp, io, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcpsock_read_id, monitor_thread, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, mgcp_gateway::next, mgcp_endpoint::next, ast_variable::next, option_verbose, ourhost, ourport, prune_gateways(), sched, tos, transmit_audit_endpoint(), ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

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

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

Definition at line 1938 of file chan_mgcp.c.

References init_req(), and oseq.

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

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

Definition at line 563 of file chan_mgcp.c.

References __mgcp_xmit(), mgcp_gateway::addr, ast_inet_ntoa(), ast_verbose(), mgcp_response::buf, mgcp_response::len, mgcp_endpoint::parent, 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 }

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

Definition at line 1931 of file chan_mgcp.c.

References init_resp().

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

int restart_monitor void   )  [static]
 

Definition at line 3470 of file chan_mgcp.c.

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

03471 {
03472    /* If we're supposed to be stopped -- stay stopped */
03473    if (monitor_thread == AST_PTHREADT_STOP)
03474       return 0;
03475    if (ast_mutex_lock(&monlock)) {
03476       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03477       return -1;
03478    }
03479    if (monitor_thread == pthread_self()) {
03480       ast_mutex_unlock(&monlock);
03481       ast_log(LOG_WARNING, "Cannot kill myself\n");
03482       return -1;
03483    }
03484    if (monitor_thread != AST_PTHREADT_NULL) {
03485       /* Wake up the thread */
03486       pthread_kill(monitor_thread, SIGURG);
03487    } else {
03488       /* Start a new monitor */
03489       if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03490          ast_mutex_unlock(&monlock);
03491          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03492          return -1;
03493       }
03494    }
03495    ast_mutex_unlock(&monlock);
03496    return 0;
03497 }

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, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::retrans, and mgcp_gateway::retransid.

Referenced by 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 }

void sdpLineNum_iterator_init int *  iterator  )  [static]
 

Definition at line 1479 of file chan_mgcp.c.

01480 {
01481    *iterator = 0;
01482 }

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_t, 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(), mgcp_request(), mgcp_request::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.

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 }

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

Definition at line 577 of file chan_mgcp.c.

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

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 }

void start_rtp struct mgcp_subchannel sub  )  [static]
 

Definition at line 2541 of file chan_mgcp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_callback(), ast_rtp_set_data(), ast_rtp_setnat(), bindaddr, mgcp_subchannel::callid, ast_channel::fds, io, mgcp_subchannel::lock, mgcp_subchannel::nat, mgcp_subchannel::owner, mgcp_subchannel::rtp, sched, transmit_connect_with_sdp(), and mgcp_subchannel::txident.

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

int transmit_audit_endpoint struct mgcp_endpoint p  )  [static]
 

Definition at line 2251 of file chan_mgcp.c.

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

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

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

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

Definition at line 2106 of file chan_mgcp.c.

References add_header(), add_sdp(), 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_cxmodes, 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().

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

int transmit_connection_del struct mgcp_subchannel sub  )  [static]
 

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

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

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

Definition at line 2288 of file chan_mgcp.c.

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

Referenced by handle_response().

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

int transmit_modify_request struct mgcp_subchannel sub  )  [static]
 

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

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

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

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

Definition at line 2065 of file chan_mgcp.c.

References add_header(), add_sdp(), 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_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().

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

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

Definition at line 2140 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_cxmodes, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, send_request(), mgcp_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().

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

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

Definition at line 2169 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_cxmodes, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, send_request(), mgcp_request::trid, and VERBOSE_PREFIX_3.

Referenced by mgcp_call(), and mgcp_hangup().

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

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

Definition at line 1948 of file chan_mgcp.c.

References mgcp_response::buf, mgcp_request::data, mgcp_request::identifier, mgcp_response::len, mgcp_request::len, malloc, mgcp_response::next, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_gateway::responses, respprep(), send_response(), mgcp_response::seqno, and mgcp_response::whensent.

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

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

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 4324 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_rtp_proto_unregister(), cli_audit_endpoint, cli_debug, cli_mgcp_reload, cli_no_debug, cli_show_endpoints, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, LOG_WARNING, mgcp_reload(), mgcp_reloading, mgcp_rtp, mgcp_tech, mgcpsock, monitor_thread, mgcp_gateway::next, mgcp_endpoint::next, prune_gateways(), sched, and sched_context_destroy().

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

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

04397 {
04398    return usecnt;
04399 }


Variable Documentation

struct in_addr __ourip [static]
 

Definition at line 272 of file chan_mgcp.c.

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

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]
 

Definition at line 234 of file chan_mgcp.c.

Referenced by build_gateway().

int adsi = 0 [static]
 

Definition at line 240 of file chan_mgcp.c.

Referenced by build_gateway().

int amaflags = 0 [static]
 

Definition at line 238 of file chan_mgcp.c.

Referenced by build_gateway().

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.

Referenced by reload_config(), and start_rtp().

int callreturn = 0 [static]
 

Definition at line 215 of file chan_mgcp.c.

Referenced by build_gateway().

int callwaiting = 0 [static]
 

Definition at line 207 of file chan_mgcp.c.

Referenced by build_gateway().

int cancallforward = 0 [static]
 

Definition at line 224 of file chan_mgcp.c.

Referenced by build_gateway().

int canreinvite = CANREINVITE [static]
 

Definition at line 228 of file chan_mgcp.c.

Referenced by build_gateway().

int capability = AST_FORMAT_ULAW [static]
 

Definition at line 268 of file chan_mgcp.c.

Referenced by process_sdp(), reload_config(), and transmit_modify_with_sdp().

char cid_name[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 184 of file chan_mgcp.c.

Referenced by build_gateway().

char cid_num[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 183 of file chan_mgcp.c.

Referenced by build_gateway().

struct ast_cli_entry cli_audit_endpoint [static]
 

Initial value:

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

Definition at line 1180 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_debug [static]
 

Initial value:

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

Definition at line 3990 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_mgcp_reload [static]
 

Initial value:

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

Definition at line 3994 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_no_debug [static]
 

Initial value:

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

Definition at line 3992 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_show_endpoints [static]
 

Initial value:

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

Definition at line 1119 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

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

Definition at line 139 of file chan_mgcp.c.

Referenced by reload_config().

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

Definition at line 179 of file chan_mgcp.c.

Referenced by build_gateway().

ast_group_t cur_callergroup = 0 [static]
 

Definition at line 195 of file chan_mgcp.c.

Referenced by build_gateway().

ast_group_t cur_pickupgroup = 0 [static]
 

Definition at line 196 of file chan_mgcp.c.

Referenced by build_gateway().

char debug_usage[] [static]
 

Initial value:

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

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

int firstdigittimeout = 16000 [static]
 

Definition at line 248 of file chan_mgcp.c.

struct mgcp_gateway * gateways [static]
 

Referenced by prune_gateways(), and reload_config().

int gendigittimeout = 8000 [static]
 

Definition at line 251 of file chan_mgcp.c.

int immediate = 0 [static]
 

Definition at line 205 of file chan_mgcp.c.

Referenced by build_gateway().

struct io_context* io [static]
 

Definition at line 278 of file chan_mgcp.c.

Referenced by do_monitor(), load_module(), reload_config(), and start_rtp().

char language[MAX_LANGUAGE] = "" [static]
 

Definition at line 181 of file chan_mgcp.c.

Referenced by build_gateway().

char mailbox[AST_MAX_EXTENSION] [static]
 

Definition at line 236 of file chan_mgcp.c.

Referenced by build_gateway().

int matchdigittimeout = 3000 [static]
 

Definition at line 254 of file chan_mgcp.c.

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

Referenced by load_module(), and unload_module().

const struct ast_channel_tech mgcp_tech [static]
 

Definition at line 500 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

int mgcpdebug = 0 [static]
 

Definition at line 275 of file chan_mgcp.c.

Referenced by mgcp_do_debug(), and mgcp_no_debug().

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

Referenced by reload_config(), restart_monitor(), and unload_module().

char musicclass[MAX_MUSICCLASS] = "" [static]
 

Definition at line 182 of file chan_mgcp.c.

Referenced by build_gateway().

int nat = 0 [static]
 

Definition at line 187 of file chan_mgcp.c.

Referenced by build_gateway().

char no_debug_usage[] [static]
 

Initial value:

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

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

int ourport [static]
 

Definition at line 273 of file chan_mgcp.c.

Referenced by reload_config().

struct sched_context* sched [static]
 

Definition at line 277 of file chan_mgcp.c.

Referenced by build_gateway(), do_monitor(), load_module(), mgcp_postrequest(), mgcpsock_read(), reload_config(), start_rtp(), and unload_module().

char show_endpoints_usage[] [static]
 

Initial value:

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

Definition at line 1115 of file chan_mgcp.c.

int singlepath = 0 [static]
 

Definition at line 226 of file chan_mgcp.c.

Referenced by build_gateway().

int slowsequence = 0 [static]
 

Definition at line 217 of file chan_mgcp.c.

Referenced by build_gateway().

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

Definition at line 138 of file chan_mgcp.c.

int threewaycalling = 0 [static]
 

Definition at line 219 of file chan_mgcp.c.

Referenced by build_gateway().

int tos = 0 [static]
 

Definition at line 203 of file chan_mgcp.c.

Referenced by reload_config().

int transfer = 0 [static]
 

Definition at line 222 of file chan_mgcp.c.

Referenced by build_gateway().

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.

Referenced by mgcp_hangup(), and mgcp_new().


Generated on Mon Mar 20 08:25:52 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1