Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:31 2009

## Asterisk developer's documentation

# chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

`#include <stdio.h>`
`#include <string.h>`
`#include <unistd.h>`
`#include <sys/socket.h>`
`#include <sys/ioctl.h>`
`#include <net/if.h>`
`#include <errno.h>`
`#include <stdlib.h>`
`#include <fcntl.h>`
`#include <netdb.h>`
`#include <sys/signal.h>`
`#include <signal.h>`
`#include <netinet/in.h>`
`#include <netinet/in_systm.h>`
`#include <netinet/ip.h>`
`#include <arpa/inet.h>`
`#include <ctype.h>`
`#include "asterisk.h"`
`#include "asterisk/lock.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/config.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/module.h"`
`#include "asterisk/pbx.h"`
`#include "asterisk/options.h"`
`#include "asterisk/sched.h"`
`#include "asterisk/io.h"`
`#include "asterisk/rtp.h"`
`#include "asterisk/acl.h"`
`#include "asterisk/callerid.h"`
`#include "asterisk/cli.h"`
`#include "asterisk/say.h"`
`#include "asterisk/cdr.h"`
`#include "asterisk/astdb.h"`
`#include "asterisk/features.h"`
`#include "asterisk/app.h"`
`#include "asterisk/musiconhold.h"`
`#include "asterisk/utils.h"`
`#include "asterisk/causes.h"`
`#include "asterisk/dsp.h"`

Include dependency graph for chan_mgcp.c:

Go to the source code of this file.

## Data Structures

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

## Defines

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

## Functions

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

## Variables

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

## Detailed Description

Implementation of Media Gateway Control Protocol.

See also
  - MGCP configuration

Definition in file chan_mgcp.c.

## Define Documentation

#define CANREINVITE 1

Definition at line 130 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_EXPIRY 120

Definition at line 128 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_CA_PORT 2727

Definition at line 146 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT 2427

Definition at line 145 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS 1000

Definition at line 148 of file chan_mgcp.c.

Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt().

#define INADDR_NONE (in_addr_t)(-1)

Definition at line 133 of file chan_mgcp.c.

Referenced by build_gateway().

#define IPTOS_MINCOST 0x02

Definition at line 118 of file chan_mgcp.c.

#define MAX_EXPIRY 3600

Definition at line 129 of file chan_mgcp.c.

#define MAX_RETRANS 5

Definition at line 149 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS 2

Definition at line 333 of file chan_mgcp.c.

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

#define MGCP_CMD_AUCX 7

Definition at line 176 of file chan_mgcp.c.

#define MGCP_CMD_AUEP 6

Definition at line 175 of file chan_mgcp.c.

Referenced by handle_response(), and transmit_audit_endpoint().

#define MGCP_CMD_CRCX 1

Definition at line 170 of file chan_mgcp.c.

Referenced by handle_response(), send_request(), and transmit_connect_with_sdp().

#define MGCP_CMD_DLCX 3

Definition at line 172 of file chan_mgcp.c.

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

#define MGCP_CMD_EPCF 0

Definition at line 169 of file chan_mgcp.c.

#define MGCP_CMD_MDCX 2

Definition at line 171 of file chan_mgcp.c.

Referenced by send_request(), transmit_modify_request(), and transmit_modify_with_sdp().

#define MGCP_CMD_NTFY 5

Definition at line 174 of file chan_mgcp.c.

#define MGCP_CMD_RQNT 4

Definition at line 173 of file chan_mgcp.c.

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

#define MGCP_CMD_RSIP 8

Definition at line 177 of file chan_mgcp.c.

#define MGCP_CX_CONF 3

Definition at line 155 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE 3

Definition at line 156 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE 4

Definition at line 158 of file chan_mgcp.c.

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

#define MGCP_CX_MUTE 4

Definition at line 157 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY 1

Definition at line 153 of file chan_mgcp.c.

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

#define MGCP_CX_SENDONLY 0

Definition at line 152 of file chan_mgcp.c.

#define MGCP_CX_SENDRECV 2

Definition at line 154 of file chan_mgcp.c.

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

#define MGCP_DTMF_HYBRID (1 << 2)

Definition at line 143 of file chan_mgcp.c.

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

#define MGCP_DTMF_INBAND (1 << 1)

Definition at line 142 of file chan_mgcp.c.

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

#define MGCP_DTMF_RFC2833 (1 << 0)

Definition at line 141 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_rtp_read().

#define MGCP_MAX_HEADERS 64

Definition at line 282 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES 64

Definition at line 283 of file chan_mgcp.c.

Referenced by add_line(), and parse().

#define MGCP_MAX_PACKET 1500

Definition at line 147 of file chan_mgcp.c.

#define MGCP_OFFHOOK 2

Definition at line 375 of file chan_mgcp.c.

Referenced by handle_hd_hf(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

#define MGCP_ONHOOK 1

Definition at line 374 of file chan_mgcp.c.

Referenced by build_gateway(), do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_request(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

#define MGCP_SUBCHANNEL_MAGIC "!978!"

Definition at line 344 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 127 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT 30

Definition at line 323 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT 1

Definition at line 336 of file chan_mgcp.c.

#define SUB_REAL 0

Definition at line 335 of file chan_mgcp.c.

#define TYPE_LINE 2

Definition at line 378 of file chan_mgcp.c.

Referenced by build_device(), build_gateway(), do_monitor(), mgcp_call(), and skinny_hangup().

#define TYPE_TRUNK 1

Definition at line 377 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().

## Function Documentation

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

Definition at line 1497 of file chan_mgcp.c.

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

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

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

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

Definition at line 550 of file chan_mgcp.c.

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

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

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

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

Definition at line 1849 of file chan_mgcp.c.

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

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

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

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

Definition at line 1871 of file chan_mgcp.c.

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

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

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

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

Definition at line 1973 of file chan_mgcp.c.

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

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

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

AST_MUTEX_DEFINE_STATIC | ( | gatelock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | mgcp_reload_lock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | monlock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | netlock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | usecnt_lock |  | ) |

static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | `[static]`

Definition at line 2825 of file chan_mgcp.c.

References ast_channel::_softhangup, ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, ast_indicate(), ast_log(), ast_moh_stop(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verbose(), mgcp_subchannel::id, LOG_DEBUG, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, option_verbose, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, unalloc_sub(), and VERBOSE_PREFIX_3.

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

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

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

Definition at line 3536 of file chan_mgcp.c.

References __ourip, mgcp_endpoint::accountcode, mgcp_gateway::addr, mgcp_endpoint::adsi, mgcp_endpoint::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, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::canreinvite, CANREINVITE, mgcp_endpoint::capability, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, free, gateways, mgcp_gateway::ha, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, INADDR_NONE, mgcp_gateway::isnamedottedip, mgcp_endpoint::language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, malloc, MAX_SUBS, MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::msgs_lock, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::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, mgcp_endpoint::singlepath, mgcp_endpoint::slowsequence, mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, VERBOSE_PREFIX_3, and mgcp_gateway::wcardep.

Referenced by reload_config().

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

static char* control2str | ( | int | ind | ) | `[static]`

Definition at line 1315 of file chan_mgcp.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, and AST_CONTROL_WINK.

Referenced by mgcp_indicate(), and skinny_indicate().

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

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 4388 of file chan_mgcp.c.

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

static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | `[static]`

Definition at line 3980 of file chan_mgcp.c.

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

Referenced by prune_gateways().

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

static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | `[static]`

Definition at line 4022 of file chan_mgcp.c.

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

Referenced by prune_gateways().

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

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

Definition at line 3366 of file chan_mgcp.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_verbose(), mgcp_gateway::endpoints, gateways, has_voicemail(), mgcp_do_reload(), MGCP_ONHOOK, mgcpsock_read(), option_verbose, transmit_notify_request(), TYPE_LINE, and VERBOSE_PREFIX_1.

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

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

Definition at line 2312 of file chan_mgcp.c.

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

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

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

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

Definition at line 592 of file chan_mgcp.c.

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

Referenced by destroy_endpoint(), destroy_gateway(), and handle_request().

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

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

Definition at line 3243 of file chan_mgcp.c.

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

Referenced by mgcpsock_read().

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

static struct mgcp_request* find_command | ( | struct mgcp_endpoint * | p,
|  | struct mgcp_subchannel * | sub,
|  | struct mgcp_request ** | queue,
|  | ast_mutex_t * | l,
|  | int | ident |
| ) |  |  | `[static, read]`

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

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

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

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

Definition at line 1544 of file chan_mgcp.c.

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

Referenced by mgcp_request(), and mgcpsock_read().

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

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

Definition at line 1523 of file chan_mgcp.c.

References s.

Referenced by handle_response().

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

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

Definition at line 1516 of file chan_mgcp.c.

References __get_header().

Referenced by __transmit_response(), build_route(), check_auth(), check_user_full(), check_via(), copy_header(), extract_uri(), find_call(), find_sdp(), func_header_read(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), gettag(), handle_request(), handle_request_bye(), handle_request_info(), handle_request_invite(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_register(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_getheader(), sip_sipredirect(), sipsock_read(), transmit_fake_auth_response(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), and transmit_state_notify().

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

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

Definition at line 1468 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

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

Definition at line 1458 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

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

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

Definition at line 1486 of file chan_mgcp.c.

References get_sdp_by_line(), and mgcp_request::line.

Referenced by process_sdp().

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

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

Definition at line 2881 of file chan_mgcp.c.

References ast_bridged_channel(), AST_CONTROL_ANSWER, ast_hangup(), ast_log(), ast_moh_stop(), ast_pthread_create, AST_STATE_DOWN, AST_STATE_RING, mgcp_subchannel::cxmode, has_voicemail(), mgcp_endpoint::hookstate, mgcp_endpoint::immediate, LOG_WARNING, MGCP_CX_SENDRECV, mgcp_new(), MGCP_OFFHOOK, mgcp_queue_control(), mgcp_ss(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), t, transmit_modify_request(), and transmit_notify_request().

Referenced by handle_request().

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

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

Definition at line 2969 of file chan_mgcp.c.

References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, AST_STATE_UP, ast_verbose(), attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, ast_frame::frametype, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MGCP_CX_CONF, MGCP_CX_MUTE, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_frame(), mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_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.

Referenced by mgcpsock_read(), and sipsock_read().

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

static void handle_response | ( | struct mgcp_endpoint * | p,
|  | struct mgcp_subchannel * | sub,
|  | int | result,
|  | unsigned int | ident,
|  | struct mgcp_request * | resp |
| ) |  |  | `[static]`

Definition at line 2378 of file chan_mgcp.c.

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

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

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

static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | `[static]`

Definition at line 517 of file chan_mgcp.c.

References ast_app_has_voicemail(), and mgcp_endpoint::mailbox.

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

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

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

Definition at line 1911 of file chan_mgcp.c.

References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_gateway::isnamedottedip, mgcp_request::len, LOG_WARNING, MGCP_MAX_HEADERS, mgcp_gateway::name, mgcp_endpoint::name, and mgcp_endpoint::parent.

Referenced by initreqprep(), reqprep(), and transmit_register().

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

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

Definition at line 1894 of file chan_mgcp.c.

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

Referenced by respprep().

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

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

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

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 4383 of file chan_mgcp.c.

References ASTERISK_GPL_KEY.

    04384 {
    04385    return ASTERISK_GPL_KEY;
    04386 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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

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

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

static int mgcp_answer | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 1183 of file chan_mgcp.c.

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

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

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

Definition at line 1122 of file chan_mgcp.c.

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

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

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

Definition at line 886 of file chan_mgcp.c.

References ast_channel::_state, AST_CONTROL_RINGING, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_verbose(), mgcp_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, ast_channel::varshead, and VERBOSE_PREFIX_3.

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

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

Definition at line 3942 of file chan_mgcp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

static int mgcp_do_reload | ( | void |  | ) | `[static]`

Definition at line 4282 of file chan_mgcp.c.

References reload_config().

Referenced by do_monitor().

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

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

Definition at line 1284 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, ast_channel::name, mgcp_subchannel::owner, and ast_channel::tech_pvt.

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

static struct ast_rtp* mgcp_get_rtp_peer | ( | struct ast_channel * | chan | ) | `[static, read]`

Definition at line 3915 of file chan_mgcp.c.

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

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

static int mgcp_hangup | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 979 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_dsp_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_update_use_count(), ast_verbose(), mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_DEBUG, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, option_debug, option_verbose, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), usecnt_lock, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

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

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

Definition at line 1347 of file chan_mgcp.c.

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

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

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

Definition at line 1382 of file chan_mgcp.c.

References ast_channel::accountcode, mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtp_fd(), ast_setstate(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), ast_verbose(), mgcp_endpoint::call_forward, ast_channel::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_name, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, mgcp_endpoint::context, ast_channel::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DTMF_DETECT, mgcp_endpoint::dtmfmode, mgcp_endpoint::exten, ast_channel::exten, ast_channel::fds, fmt, mgcp_subchannel::id, ast_channel::language, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_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_lock, VERBOSE_PREFIX_3, and ast_channel::writeformat.

Referenced by handle_hd_hf(), and mgcp_request().

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

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

Definition at line 3951 of file chan_mgcp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 734 of file chan_mgcp.c.

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

Referenced by find_command(), and send_request().

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

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

Definition at line 665 of file chan_mgcp.c.

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

Referenced by handle_hd_hf().

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

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

Definition at line 629 of file chan_mgcp.c.

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

Referenced by handle_request(), and mgcp_queue_control().

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

static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | `[static]`

Definition at line 647 of file chan_mgcp.c.

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

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

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

static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | `[static, read]`

Definition at line 1244 of file chan_mgcp.c.

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

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

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

Definition at line 4288 of file chan_mgcp.c.

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

Referenced by reload(), and unload_module().

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

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

Definition at line 3481 of file chan_mgcp.c.

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

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

static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | `[static, read]`

Definition at line 1212 of file chan_mgcp.c.

References ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, ast_frame::frametype, LOG_DEBUG, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, ast_frame::subclass, and ast_channel::writeformat.

Referenced by mgcp_read().

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

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

Definition at line 1300 of file chan_mgcp.c.

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

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

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

Definition at line 3924 of file chan_mgcp.c.

References ast_channel::tech_pvt, and transmit_modify_with_sdp().

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

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

Definition at line 1085 of file chan_mgcp.c.

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

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

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

Definition at line 2570 of file chan_mgcp.c.

References ast_bridged_channel(), ast_canmatch_extension(), ast_db_put(), ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strlen_zero(), ast_verbose(), ast_waitfordigit(), mgcp_endpoint::call_forward, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, ast_channel::cid, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmfmode, ast_channel::exten, exten, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_channel::language, mgcp_endpoint::lastcallerid, LOG_DEBUG, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_subchannel::next, option_debug, option_verbose, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), ast_channel::tech_pvt, transmit_notify_request(), and VERBOSE_PREFIX_3.

Referenced by handle_hd_hf().

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

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

Definition at line 1254 of file chan_mgcp.c.

References AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.

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

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

Definition at line 3275 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, mgcp_request::endpoint, find_and_retrans(), find_subchannel_and_lock(), free, handle_request(), handle_response(), mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, mgcp_subchannel::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_subchannel::parent, parse(), result, mgcp_gateway::retransid, mgcp_message::seqno, mgcp_request::verb, and mgcp_request::version.

Referenced by do_monitor().

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

static void parse | ( | struct mgcp_request * | req | ) | `[static]`

Definition at line 1662 of file chan_mgcp.c.

References ast_log(), ast_strlen_zero(), ast_verbose(), mgcp_request::data, mgcp_request::endpoint, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::line, mgcp_request::lines, LOG_WARNING, MGCP_MAX_HEADERS, MGCP_MAX_LINES, mgcp_request::verb, and mgcp_request::version.

Referenced by __login_exec(), aqm_exec(), ast_hint_state_changed(), ast_parse_allow_disallow(), dial_exec_full(), enumlookup_exec(), get_in_brackets(), group_check_exec(), mgcpsock_read(), mixmonitor_exec(), pbx_builtin_background(), pqm_exec(), privacy_exec(), reload_agents(), rqm_exec(), sendimage_exec(), sendtext_exec(), transfer_exec(), txtcidname_exec(), and upqm_exec().

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

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

Definition at line 1763 of file chan_mgcp.c.

References 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(), mgcp_endpoint::capability, get_sdp(), get_sdp_iterate(), host, hp, LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_subchannel::parent, portno, mgcp_subchannel::rtp, and sdpLineNum_iterator_init().

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

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

static void prune_gateways | ( | void |  | ) | `[static]`

Definition at line 4032 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

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

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

References mgcp_reload().

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

static int reload_config | ( | void |  | ) | `[static]`

Definition at line 4075 of file chan_mgcp.c.

References __ourip, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_variable_browse(), ast_verbose(), bindaddr, build_gateway(), cfg, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, format, gateways, hp, IPTOS_MINCOST, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, mgcp_gateway::next, mgcp_endpoint::next, ast_variable::next, option_verbose, prune_gateways(), transmit_audit_endpoint(), ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

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

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

Definition at line 1940 of file chan_mgcp.c.

References init_req().

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

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

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

Definition at line 563 of file chan_mgcp.c.

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

Referenced by find_and_retrans().

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

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

Definition at line 1933 of file chan_mgcp.c.

References init_resp().

Referenced by __transmit_response(), transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_sdp(), and transmit_response_with_unsupported().

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

static int restart_monitor | ( | void |  | ) | `[static]`

Definition at line 3452 of file chan_mgcp.c.

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

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

static int retrans_pkt | ( | void * | data | ) | `[static]`

Definition at line 672 of file chan_mgcp.c.

References __mgcp_xmit(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, handle_response(), LOG_WARNING, MAX_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::retrans, and mgcp_gateway::retransid.

Referenced by __sip_reliable_xmit(), and mgcp_postrequest().

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

static void sdpLineNum_iterator_init | ( | int * | iterator | ) | `[static]`

Definition at line 1481 of file chan_mgcp.c.

Referenced by process_sdp().

    01482 {
    01483    *iterator = 0;
    01484 }

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

Definition at line 800 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::data, free, mgcp_request::len, LOG_DEBUG, LOG_WARNING, malloc, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcp_request::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_endpoint::slowsequence, and t.

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

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

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

Definition at line 577 of file chan_mgcp.c.

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

Referenced by __transmit_response(), transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_sdp(), and transmit_response_with_unsupported().

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

static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | `[static]`

Definition at line 2545 of file chan_mgcp.c.

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

Referenced by handle_hd_hf(), handle_message(), handle_response(), mgcp_answer(), mgcp_call(), mgcp_ss(), and skinny_answer().

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

static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | `[static]`

Definition at line 2253 of file chan_mgcp.c.

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

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

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

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

Definition at line 2108 of file chan_mgcp.c.

References add_header(), add_sdp(), AST_FORMAT_MAX_AUDIO, ast_rtp_lookup_mime_subtype(), ast_rtp_offered_from_local(), ast_verbose(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_gateway::name, mgcp_endpoint::name, 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().

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

static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | `[static]`

Definition at line 2266 of file chan_mgcp.c.

References add_header(), ast_verbose(), mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, 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().

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

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

Definition at line 2290 of file chan_mgcp.c.

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

Referenced by handle_response().

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

static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | `[static]`

Definition at line 2218 of file chan_mgcp.c.

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

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

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

Definition at line 2067 of file chan_mgcp.c.

References add_header(), add_sdp(), AST_FORMAT_MAX_AUDIO, ast_rtp_get_peer(), ast_rtp_lookup_mime_subtype(), ast_rtp_offered_from_local(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, MGCP_CMD_MDCX, 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().

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

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

Definition at line 2142 of file chan_mgcp.c.

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

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

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

Definition at line 2171 of file chan_mgcp.c.

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

Referenced by mgcp_call(), and mgcp_hangup().

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

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

Definition at line 1950 of file chan_mgcp.c.

References mgcp_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.

Referenced by handle_message(), handle_request(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_refer(), handle_request_subscribe(), receive_message(), register_verify(), sip_indicate(), transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_diallednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), and transmit_tone().

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

static int unalloc_sub | ( | struct mgcp_subchannel * | sub | ) | `[static]`

Definition at line 522 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_log(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_DEBUG, LOG_WARNING, MGCP_CX_INACTIVE, mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_subchannel::tmpdest, and transmit_connection_del().

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

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

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

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

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

Definition at line 4306 of file chan_mgcp.c.

References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gateways, LOG_WARNING, mgcp_reload(), mgcp_gateway::next, mgcp_endpoint::next, prune_gateways(), and sched_context_destroy().

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

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

    04379 {
    04380    return usecnt;
    04381 }

## Variable Documentation

struct in_addr __ourip`[static]`

Definition at line 272 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = ""`[static]`

Definition at line 234 of file chan_mgcp.c.

int adsi = 0`[static]`

Definition at line 240 of file chan_mgcp.c.

int amaflags = 0`[static]`

Definition at line 238 of file chan_mgcp.c.

char audit_endpoint_usage[]`[static]`

Initial value:

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

Definition at line 1175 of file chan_mgcp.c.

struct sockaddr_in bindaddr`[static]`

Definition at line 473 of file chan_mgcp.c.

int callreturn = 0`[static]`

Definition at line 215 of file chan_mgcp.c.

int callwaiting = 0`[static]`

Definition at line 207 of file chan_mgcp.c.

int cancallforward = 0`[static]`

Definition at line 224 of file chan_mgcp.c.

int canreinvite = CANREINVITE`[static]`

Definition at line 228 of file chan_mgcp.c.

int capability = AST_FORMAT_ULAW`[static]`

Definition at line 268 of file chan_mgcp.c.

Referenced by add_sdp(), iax2_call(), set_config(), and set_local_capabilities().

char cid_name[AST_MAX_EXTENSION] = ""`[static]`

Definition at line 184 of file chan_mgcp.c.

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

char cid_num[AST_MAX_EXTENSION] = ""`[static]`

Definition at line 183 of file chan_mgcp.c.

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

struct ast_cli_entry cli_audit_endpoint`[static]`

Initial value:

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

Definition at line 1180 of file chan_mgcp.c.

struct ast_cli_entry cli_debug`[static]`

Initial value:

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

Definition at line 3972 of file chan_mgcp.c.

struct ast_cli_entry cli_mgcp_reload`[static]`

Initial value:

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

Definition at line 3976 of file chan_mgcp.c.

struct ast_cli_entry cli_no_debug`[static]`

Initial value:

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

Definition at line 3974 of file chan_mgcp.c.

struct ast_cli_entry cli_show_endpoints`[static]`

Initial value:

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

Definition at line 1119 of file chan_mgcp.c.

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

Definition at line 139 of file chan_mgcp.c.

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

Definition at line 179 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0`[static]`

Definition at line 195 of file chan_mgcp.c.

ast_group_t cur_pickupgroup = 0`[static]`

Definition at line 196 of file chan_mgcp.c.

char debug_usage[]`[static]`

Initial value:

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

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

int firstdigittimeout = 16000`[static]`

Definition at line 248 of file chan_mgcp.c.

Referenced by disa_exec().

struct mgcp_gateway * gateways`[static]`

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

int gendigittimeout = 8000`[static]`

Definition at line 251 of file chan_mgcp.c.

int immediate = 0`[static]`

Definition at line 205 of file chan_mgcp.c.

struct io_context* io`[static]`

Definition at line 278 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = ""`[static]`

Definition at line 181 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION]`[static]`

Definition at line 236 of file chan_mgcp.c.

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

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.

char mgcp_reload_usage[]`[static]`

Initial value:

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

Definition at line 3968 of file chan_mgcp.c.

int mgcp_reloading = 0`[static]`

Definition at line 467 of file chan_mgcp.c.

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

struct ast_channel_tech mgcp_tech`[static]`

Definition at line 500 of file chan_mgcp.c.

int mgcpdebug = 0`[static]`

Definition at line 275 of file chan_mgcp.c.

int mgcpsock = -1`[static]`

Definition at line 471 of file chan_mgcp.c.

int* mgcpsock_read_id = NULL`[static]`

Definition at line 3364 of file chan_mgcp.c.

pthread_t monitor_thread = AST_PTHREADT_NULL`[static]`

Definition at line 264 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = ""`[static]`

Definition at line 182 of file chan_mgcp.c.

Referenced by read_config().

int nat = 0`[static]`

Definition at line 187 of file chan_mgcp.c.

char no_debug_usage[]`[static]`

Initial value:

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

Definition at line 3964 of file chan_mgcp.c.

int nonCodecCapability = AST_RTP_DTMF`[static]`

Definition at line 269 of file chan_mgcp.c.

unsigned int oseq`[static]`

Definition at line 245 of file chan_mgcp.c.

char ourhost[MAXHOSTNAMELEN]`[static]`

Definition at line 271 of file chan_mgcp.c.

Referenced by ast_find_ourip().

int ourport`[static]`

Definition at line 273 of file chan_mgcp.c.

struct sched_context* sched`[static]`

Definition at line 277 of file chan_mgcp.c.

char show_endpoints_usage[]`[static]`

Initial value:

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

Definition at line 1115 of file chan_mgcp.c.

int singlepath = 0`[static]`

Definition at line 226 of file chan_mgcp.c.

int slowsequence = 0`[static]`

Definition at line 217 of file chan_mgcp.c.

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.

int tos = 0`[static]`

Definition at line 203 of file chan_mgcp.c.

int transfer = 0`[static]`

Definition at line 222 of file chan_mgcp.c.

Referenced by leave_voicemail().

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

Definition at line 137 of file chan_mgcp.c.

int usecnt = 0`[static]`

Definition at line 242 of file chan_mgcp.c.