Wed Aug 18 22:34:10 2010

Asterisk developer's documentation


chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/signal.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.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/netsock.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/event.h"

Go to the source code of this file.

Data Structures

struct  mgcp_endpoint
struct  mgcp_gateway
struct  mgcp_message
 mgcp_message: MGCP message for queuing up More...
struct  mgcp_request
struct  mgcp_response
struct  mgcp_subchannel

Defines

#define CANREINVITE   1
#define DEFAULT_EXPIRY   120
#define DEFAULT_MGCP_CA_PORT   2727
#define DEFAULT_MGCP_GW_PORT   2427
#define DEFAULT_RETRANS   1000
#define INADDR_NONE   (in_addr_t)(-1)
#define MAX_EXPIRY   3600
#define MAX_RETRANS   5
#define MAX_SUBS   2
#define MGCP_CX_CONF   3
#define MGCP_CX_CONFERENCE   3
#define MGCP_CX_INACTIVE   4
#define MGCP_CX_MUTE   4
#define MGCP_CX_RECVONLY   1
#define MGCP_CX_SENDONLY   0
#define MGCP_CX_SENDRECV   2
#define MGCP_DTMF_HYBRID   (1 << 2)
#define MGCP_DTMF_INBAND   (1 << 1)
#define MGCP_DTMF_RFC2833   (1 << 0)
#define MGCP_MAX_HEADERS   64
#define MGCP_MAX_LINES   64
#define MGCP_MAX_PACKET   1500
#define MGCP_OFFHOOK   2
#define MGCP_ONHOOK   1
#define MGCP_SUBCHANNEL_MAGIC   "!978!"
#define MGCPDUMPER
#define RESPONSE_TIMEOUT   30
#define SUB_ALT   1
#define SUB_REAL   0
#define TYPE_LINE   2
#define TYPE_TRUNK   1

Enumerations

enum  {
  MGCP_CMD_EPCF, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_CMD_DLCX,
  MGCP_CMD_RQNT, MGCP_CMD_NTFY, MGCP_CMD_AUEP, MGCP_CMD_AUCX,
  MGCP_CMD_RSIP
}

Functions

static char * __get_header (struct mgcp_request *req, char *name, int *start)
static int __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len)
static void __reg_module (void)
static void __unreg_module (void)
static int add_header (struct mgcp_request *req, char *var, char *value)
static void add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp)
static int add_line (struct mgcp_request *req, char *line)
static int add_sdp (struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
static int attempt_transfer (struct mgcp_endpoint *p)
static struct mgcp_gatewaybuild_gateway (char *cat, struct ast_variable *v)
 build_gateway: parse mgcp.conf and create gateway/endpoint structures
static char * control2str (int ind)
static void destroy_endpoint (struct mgcp_endpoint *e)
static void destroy_gateway (struct mgcp_gateway *g)
static void * do_monitor (void *data)
static void dump_cmd_queues (struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
 dump_cmd_queues: (SC:) cleanup pending commands
static void dump_queue (struct mgcp_gateway *gw, struct mgcp_endpoint *p)
static int find_and_retrans (struct mgcp_subchannel *sub, struct mgcp_request *req)
static struct mgcp_requestfind_command (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request **queue, ast_mutex_t *l, int ident)
 find_command: (SC:) remove command transaction from queue
static struct mgcp_subchannelfind_subchannel_and_lock (char *name, int msgid, struct sockaddr_in *sin)
static char * get_csv (char *c, int *len, char **next)
 get_csv: (SC:) get comma separated value
static char * get_header (struct mgcp_request *req, char *name)
static char * get_sdp (struct mgcp_request *req, char *name)
static char * get_sdp_by_line (char *line, char *name, int nameLen)
static char * get_sdp_iterate (int *iterator, struct mgcp_request *req, char *name)
static void handle_hd_hf (struct mgcp_subchannel *sub, char *ev)
static char * handle_mgcp_audit_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mgcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mgcp_set_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_mgcp_show_endpoints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
static void handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp)
static int has_voicemail (struct mgcp_endpoint *p)
static int init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
static int init_resp (struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
static int load_module (void)
 load_module: PBX load module - initialization ---
static int mgcp_answer (struct ast_channel *ast)
static int mgcp_call (struct ast_channel *ast, char *dest, int timeout)
static int mgcp_devicestate (void *data)
 mgcp_devicestate: channel callback for device status monitoring
static int mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_get_result mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static int mgcp_hangup (struct ast_channel *ast)
static int mgcp_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelmgcp_new (struct mgcp_subchannel *sub, int state)
static int mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
static void mgcp_queue_control (struct mgcp_subchannel *sub, int control)
static void mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f)
static void mgcp_queue_hangup (struct mgcp_subchannel *sub)
static struct ast_framemgcp_read (struct ast_channel *ast)
static char * mgcp_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_channelmgcp_request (const char *type, int format, void *data, int *cause)
static struct ast_framemgcp_rtp_read (struct mgcp_subchannel *sub)
static int mgcp_senddigit_begin (struct ast_channel *ast, char digit)
static int mgcp_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int mgcp_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
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 mwi_event_cb (const struct ast_event *event, void *userdata)
static void parse (struct mgcp_request *req)
static int process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req)
static void prune_gateways (void)
static int reload (void)
static int reload_config (int reload)
static int reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
static int resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp)
static int respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
static int restart_monitor (void)
static int retrans_pkt (const void *data)
static void sdpLineNum_iterator_init (int *iterator)
static int send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno)
static int send_response (struct mgcp_subchannel *sub, struct mgcp_request *req)
static void start_rtp (struct mgcp_subchannel *sub)
static int transmit_audit_endpoint (struct mgcp_endpoint *p)
static int transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp)
static int transmit_connection_del (struct mgcp_subchannel *sub)
static int transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident)
static int transmit_modify_request (struct mgcp_subchannel *sub)
static int transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
static int transmit_notify_request (struct mgcp_subchannel *sub, char *tone)
static int transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
static int transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
static int unalloc_sub (struct mgcp_subchannel *sub)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static char accountcode [AST_MAX_ACCOUNT_CODE] = ""
static int adsi = 0
static int amaflags = 0
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static int callreturn = 0
static int callwaiting = 0
static int cancallforward = 0
static int canreinvite = CANREINVITE
static int capability = AST_FORMAT_ULAW
static char cid_name [AST_MAX_EXTENSION] = ""
static char cid_num [AST_MAX_EXTENSION] = ""
static struct ast_cli_entry cli_mgcp []
static struct ast_cli_entry cli_mgcp_set_debug_deprecated = { .handler = handle_mgcp_set_debug_deprecated , .summary = "Enable/Disable MGCP debugging" ,__VA_ARGS__ }
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 struct ast_jb_conf default_jbconf
static int dtmfmode = 0
static int firstdigittimeout = 16000
static ast_mutex_t gatelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 gatelock: mutex for gateway/endpoint lists
static struct mgcp_gatewaygateways
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
static int immediate = 0
static struct io_contextio
static char language [MAX_LANGUAGE] = ""
static char mailbox [AST_MAX_EXTENSION]
static int matchdigittimeout = 3000
static char * mgcp_cxmodes []
static ast_mutex_t mgcp_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int mgcp_reloading = 0
static struct ast_rtp_protocol mgcp_rtp
static struct ast_channel_tech mgcp_tech
static int mgcpdebug = 0
static int mgcpsock = -1
static int * mgcpsock_read_id = NULL
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int nonCodecCapability = AST_RTP_DTMF
static unsigned int oseq
static char ourhost [MAXHOSTNAMELEN]
static int ourport
static char parkinglot [AST_MAX_CONTEXT]
struct {
   unsigned int   cos
   unsigned int   cos_audio
   unsigned int   tos
   unsigned int   tos_audio
qos
static struct sched_contextsched
static int singlepath = 0
static int slowsequence = 0
static const char tdesc [] = "Media Gateway Control Protocol (MGCP)"
static int threewaycalling = 0
static int transfer = 0


Detailed Description

Implementation of Media Gateway Control Protocol.

Author:
Mark Spencer <markster@digium.com>
See also

Definition in file chan_mgcp.c.


Define Documentation

#define CANREINVITE   1

Definition at line 83 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_EXPIRY   120

Definition at line 81 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 108 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 107 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS   1000

How frequently to retransmit

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

Referenced by build_gateway().

#define MAX_EXPIRY   3600

Definition at line 82 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 111 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 269 of file chan_mgcp.c.

Referenced by build_gateway(), destroy_endpoint(), reload_config(), and unistim_info().

#define MGCP_CX_CONF   3

Definition at line 117 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 118 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 120 of file chan_mgcp.c.

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

#define MGCP_CX_MUTE   4

Definition at line 119 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

Definition at line 115 of file chan_mgcp.c.

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

#define MGCP_CX_SENDONLY   0

MGCP rtp stream modes {

Definition at line 114 of file chan_mgcp.c.

#define MGCP_CX_SENDRECV   2

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

Referenced by add_header_offhook(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().

#define MGCP_DTMF_INBAND   (1 << 1)

Definition at line 104 of file chan_mgcp.c.

Referenced by add_header_offhook(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().

#define MGCP_DTMF_RFC2833   (1 << 0)

Definition at line 103 of file chan_mgcp.c.

Referenced by build_gateway(), mgcp_rtp_read(), mgcp_senddigit_begin(), and mgcp_senddigit_end().

#define MGCP_MAX_HEADERS   64

The private structures of the mgcp channels are linked for ! selecting outgoing channels

Definition at line 228 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

Definition at line 229 of file chan_mgcp.c.

Referenced by add_line(), and parse().

#define MGCP_MAX_PACKET   1500

Also from RFC 2543, should sub headers tho

Definition at line 109 of file chan_mgcp.c.

#define MGCP_OFFHOOK   2

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

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

#define MGCP_SUBCHANNEL_MAGIC   "!978!"

subchannel magic string. Needed to prove that any subchannel pointer passed by asterisk really points to a valid subchannel memory area. Ugly.. But serves the purpose for the time being.

Definition at line 280 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 80 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 259 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 272 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 271 of file chan_mgcp.c.

#define TYPE_LINE   2

Definition at line 306 of file chan_mgcp.c.

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

#define TYPE_TRUNK   1

Definition at line 305 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().


Enumeration Type Documentation

anonymous enum

Enumerator:
MGCP_CMD_EPCF 
MGCP_CMD_CRCX 
MGCP_CMD_MDCX 
MGCP_CMD_DLCX 
MGCP_CMD_RQNT 
MGCP_CMD_NTFY 
MGCP_CMD_AUEP 
MGCP_CMD_AUCX 
MGCP_CMD_RSIP 

Definition at line 131 of file chan_mgcp.c.

00131      {
00132    MGCP_CMD_EPCF,
00133    MGCP_CMD_CRCX,
00134    MGCP_CMD_MDCX,
00135    MGCP_CMD_DLCX,
00136    MGCP_CMD_RQNT,
00137    MGCP_CMD_NTFY,
00138    MGCP_CMD_AUEP,
00139    MGCP_CMD_AUCX,
00140    MGCP_CMD_RSIP
00141 };


Function Documentation

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

Definition at line 1607 of file chan_mgcp.c.

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

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

01608 {
01609    int x;
01610    int len = strlen(name);
01611    char *r;
01612    for (x=*start;x<req->headers;x++) {
01613       if (!strncasecmp(req->header[x], name, len) && 
01614           (req->header[x][len] == ':')) {
01615          r = req->header[x] + len + 1;
01616          while(*r && (*r < 33))
01617             r++;
01618          *start = x+1;
01619          return r;
01620       }
01621    }
01622    /* Don't return NULL, so get_header is always a valid pointer */
01623    return "";
01624 }

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

Definition at line 515 of file chan_mgcp.c.

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

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

00516 {
00517    int res;
00518    if (gw->addr.sin_addr.s_addr)
00519       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00520    else 
00521       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00522    if (res != len) {
00523       ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00524    }
00525    return res;
00526 }

static void __reg_module ( void   )  [static]

Definition at line 4419 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

Definition at line 4419 of file chan_mgcp.c.

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

Definition at line 1953 of file chan_mgcp.c.

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

Referenced by __transmit_response(), add_digit(), add_header_contentLength(), add_header_offhook(), add_route(), add_sdp(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), initreqprep(), reqprep(), respprep(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_invite(), transmit_modify_request(), transmit_notify_custom(), 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_response_with_allow(), transmit_response_with_auth(), transmit_response_with_minse(), transmit_response_with_unsupported(), and transmit_state_notify().

01954 {
01955    if (req->len >= sizeof(req->data) - 4) {
01956       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01957       return -1;
01958    }
01959    if (req->lines) {
01960       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
01961       return -1;
01962    }
01963    req->header[req->headers] = req->data + req->len;
01964    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
01965    req->len += strlen(req->header[req->headers]);
01966    if (req->headers < MGCP_MAX_HEADERS)
01967       req->headers++;
01968    else {
01969       ast_log(LOG_WARNING, "Out of header space\n");
01970       return -1;
01971    }
01972    return 0;   
01973 }

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

Definition at line 2348 of file chan_mgcp.c.

References ast_channel::_state, add_header(), AST_STATE_RINGING, mgcp_endpoint::dtmfmode, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_subchannel::owner, mgcp_subchannel::parent, and mgcp_endpoint::sub.

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

02349 {
02350    struct mgcp_endpoint *p = sub->parent;
02351 
02352    if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)))
02353       add_header(resp, "R", "L/hu(N),L/hf(N)");
02354    else
02355       add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
02356 }

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

Definition at line 1975 of file chan_mgcp.c.

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

01976 {
01977    if (req->len >= sizeof(req->data) - 4) {
01978       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
01979       return -1;
01980    }
01981    if (!req->lines) {
01982       /* Add extra empty return */
01983       ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
01984       req->len += strlen(req->data + req->len);
01985    }
01986    req->line[req->lines] = req->data + req->len;
01987    snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
01988    req->len += strlen(req->line[req->lines]);
01989    if (req->lines < MGCP_MAX_LINES)
01990       req->lines++;
01991    else {
01992       ast_log(LOG_WARNING, "Out of line space\n");
01993       return -1;
01994    }
01995    return 0;   
01996 }

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

Definition at line 2076 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_verbose, mgcp_endpoint::capability, len(), LOG_WARNING, mgcpdebug, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.

Referenced by transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), and transmit_response_with_t38_sdp().

02077 {
02078    int len;
02079    int codec;
02080    char costr[80];
02081    struct sockaddr_in sin;
02082    char v[256];
02083    char s[256];
02084    char o[256];
02085    char c[256];
02086    char t[256];
02087    char m[256] = "";
02088    char a[1024] = "";
02089    int x;
02090    struct sockaddr_in dest;
02091    struct mgcp_endpoint *p = sub->parent;
02092    /* XXX We break with the "recommendation" and send our IP, in order that our
02093           peer doesn't have to ast_gethostbyname() us XXX */
02094    len = 0;
02095    if (!sub->rtp) {
02096       ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02097       return -1;
02098    }
02099    ast_rtp_get_us(sub->rtp, &sin);
02100    if (rtp) {
02101       ast_rtp_get_peer(rtp, &dest);
02102    } else {
02103       if (sub->tmpdest.sin_addr.s_addr) {
02104          dest.sin_addr = sub->tmpdest.sin_addr;
02105          dest.sin_port = sub->tmpdest.sin_port;
02106          /* Reset temporary destination */
02107          memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02108       } else {
02109          dest.sin_addr = p->parent->ourip;
02110          dest.sin_port = sin.sin_port;
02111       }
02112    }
02113    if (mgcpdebug) {
02114       ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02115    }
02116    ast_copy_string(v, "v=0\r\n", sizeof(v));
02117    snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02118    ast_copy_string(s, "s=session\r\n", sizeof(s));
02119    snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02120    ast_copy_string(t, "t=0 0\r\n", sizeof(t));
02121    snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02122    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02123       if (p->capability & x) {
02124          if (mgcpdebug) {
02125             ast_verbose("Answering with capability %d\n", x);
02126          }
02127          codec = ast_rtp_lookup_code(sub->rtp, 1, x);
02128          if (codec > -1) {
02129             snprintf(costr, sizeof(costr), " %d", codec);
02130             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02131             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
02132             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02133          }
02134       }
02135    }
02136    for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
02137       if (p->nonCodecCapability & x) {
02138          if (mgcpdebug) {
02139             ast_verbose("Answering with non-codec capability %d\n", x);
02140          }
02141          codec = ast_rtp_lookup_code(sub->rtp, 0, x);
02142          if (codec > -1) {
02143             snprintf(costr, sizeof(costr), " %d", codec);
02144             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02145             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
02146             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02147             if (x == AST_RTP_DTMF) {
02148                /* Indicate we support DTMF...  Not sure about 16,
02149                   but MSN supports it so dang it, we will too... */
02150                snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02151                strncat(a, costr, sizeof(a) - strlen(a) - 1);
02152             }
02153          }
02154       }
02155    }
02156    strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02157    len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02158    snprintf(costr, sizeof(costr), "%d", len);
02159    add_line(resp, v);
02160    add_line(resp, o);
02161    add_line(resp, s);
02162    add_line(resp, c);
02163    add_line(resp, t);
02164    add_line(resp, m);
02165    add_line(resp, a);
02166    return 0;
02167 }

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

Definition at line 2913 of file chan_mgcp.c.

References ast_channel::_softhangup, ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verb, mgcp_subchannel::id, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().

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

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

build_gateway: parse mgcp.conf and create gateway/endpoint structures

Definition at line 3581 of file chan_mgcp.c.

References __ourip, mgcp_endpoint::accountcode, accountcode, mgcp_endpoint::adsi, adsi, mgcp_endpoint::amaflags, amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free, ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verb, mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, callreturn, mgcp_endpoint::callwaiting, callwaiting, mgcp_endpoint::cancallforward, cancallforward, mgcp_endpoint::canreinvite, CANREINVITE, canreinvite, capability, mgcp_endpoint::capability, mgcp_endpoint::cid_name, cid_name, mgcp_endpoint::cid_num, cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, context, cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::dtmfmode, dtmfmode, gateways, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, immediate, INADDR_NONE, mgcp_endpoint::language, language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, mailbox, MAX_SUBS, mbox(), MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, musicclass, mwi_event_cb(), mgcp_endpoint::mwi_event_sub, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, nat, mgcp_endpoint::needaudit, ast_variable::next, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::parkinglot, parkinglot, mgcp_endpoint::pickupgroup, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, singlepath, mgcp_endpoint::slowsequence, slowsequence, strsep(), mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, threewaycalling, mgcp_endpoint::transfer, transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, and ast_variable::value.

Referenced by reload_config().

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

static char* control2str ( int  ind  )  [static]

Definition at line 1420 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(), skinny_indicate(), and unistim_indicate().

01420                                   {
01421    switch (ind) {
01422    case AST_CONTROL_HANGUP:
01423       return "Other end has hungup";
01424    case AST_CONTROL_RING:
01425       return "Local ring";
01426    case AST_CONTROL_RINGING:
01427       return "Remote end is ringing";
01428    case AST_CONTROL_ANSWER:
01429       return "Remote end has answered";
01430    case AST_CONTROL_BUSY:
01431       return "Remote end is busy";
01432    case AST_CONTROL_TAKEOFFHOOK:
01433       return "Make it go off hook";
01434    case AST_CONTROL_OFFHOOK:
01435       return "Line is off hook";
01436    case AST_CONTROL_CONGESTION:
01437       return "Congestion (circuits busy)";
01438    case AST_CONTROL_FLASH:
01439       return "Flash hook";
01440    case AST_CONTROL_WINK:
01441       return "Wink";
01442    case AST_CONTROL_OPTION:
01443       return "Set a low-level option";
01444    case AST_CONTROL_RADIO_KEY:
01445       return "Key Radio";
01446    case AST_CONTROL_RADIO_UNKEY:
01447       return "Un-Key Radio";
01448    }
01449    return "UNKNOWN";
01450 }

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

Definition at line 4006 of file chan_mgcp.c.

References ast_mutex_lock(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::cxident, mgcp_subchannel::lock, MAX_SUBS, mgcp_subchannel::next, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and transmit_connection_del().

Referenced by prune_gateways().

04007 {
04008    struct mgcp_subchannel *sub = e->sub->next, *s;
04009    int i;
04010 
04011    for (i = 0; i < MAX_SUBS; i++) {
04012       ast_mutex_lock(&sub->lock);
04013       if (!ast_strlen_zero(sub->cxident)) {
04014          transmit_connection_del(sub);
04015       }
04016       if (sub->rtp) {
04017          ast_rtp_destroy(sub->rtp);
04018          sub->rtp = NULL;
04019       }
04020       memset(sub->magic, 0, sizeof(sub->magic));
04021       mgcp_queue_hangup(sub);
04022       dump_cmd_queues(NULL, sub);
04023       ast_mutex_unlock(&sub->lock);
04024       sub = sub->next;
04025    }
04026 
04027    if (e->dsp) {
04028       ast_dsp_free(e->dsp);
04029    }
04030 
04031    dump_queue(e->parent, e);
04032    dump_cmd_queues(e, NULL);
04033 
04034    sub = e->sub;
04035    for (i = 0; (i < MAX_SUBS) && sub; i++) {
04036       s = sub;
04037       sub = sub->next;
04038       ast_mutex_destroy(&s->lock);
04039       ast_mutex_destroy(&s->cx_queue_lock);
04040       ast_free(s);
04041    }
04042 
04043    if (e->mwi_event_sub)
04044       ast_event_unsubscribe(e->mwi_event_sub);
04045 
04046    ast_mutex_destroy(&e->lock);
04047    ast_mutex_destroy(&e->rqnt_queue_lock);
04048    ast_mutex_destroy(&e->cmd_queue_lock);
04049    ast_free(e);
04050 }

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4052 of file chan_mgcp.c.

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

04053 {
04054    if (g->ha)
04055       ast_free_ha(g->ha);
04056 
04057    dump_queue(g, NULL);
04058 
04059    ast_free(g);
04060 }

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

Definition at line 3412 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_verb, mgcp_gateway::endpoints, gateways, has_voicemail(), io, MGCP_ONHOOK, mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), monlock, netlock, reload_config(), transmit_notify_request(), and TYPE_LINE.

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

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

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2417 of file chan_mgcp.c.

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

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

02418 {
02419    struct mgcp_request *t, *q;
02420 
02421    if (p) {
02422       ast_mutex_lock(&p->rqnt_queue_lock);
02423       for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
02424       p->rqnt_queue = NULL;
02425       ast_mutex_unlock(&p->rqnt_queue_lock);
02426 
02427       ast_mutex_lock(&p->cmd_queue_lock);
02428       for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
02429       p->cmd_queue = NULL;
02430       ast_mutex_unlock(&p->cmd_queue_lock);
02431 
02432       ast_mutex_lock(&p->sub->cx_queue_lock);
02433       for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02434       p->sub->cx_queue = NULL;
02435       ast_mutex_unlock(&p->sub->cx_queue_lock);
02436 
02437       ast_mutex_lock(&p->sub->next->cx_queue_lock);
02438       for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
02439       p->sub->next->cx_queue = NULL;
02440       ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02441    } else if (sub) {
02442       ast_mutex_lock(&sub->cx_queue_lock);
02443       for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02444       sub->cx_queue = NULL;
02445       ast_mutex_unlock(&sub->cx_queue_lock);
02446    }
02447 }

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

Definition at line 555 of file chan_mgcp.c.

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

Referenced by destroy_gateway(), and handle_request().

00556 {
00557    struct mgcp_message *cur, *q = NULL, *w, *prev;
00558 
00559    ast_mutex_lock(&gw->msgs_lock);
00560    prev = NULL, cur = gw->msgs;
00561    while (cur) {
00562       if (!p || cur->owner_ep == p) {
00563          if (prev)
00564             prev->next = cur->next;
00565          else
00566             gw->msgs = cur->next;
00567 
00568          ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 
00569             gw->name, cur->seqno);
00570 
00571          w = cur;
00572          cur = cur->next;
00573          if (q) {
00574             w->next = q;
00575          } else {
00576             w->next = NULL;
00577          }
00578          q = w;
00579       } else {
00580          prev = cur, cur=cur->next;
00581       }
00582    }
00583    ast_mutex_unlock(&gw->msgs_lock);
00584 
00585    while (q) {
00586       cur = q;
00587       q = q->next;
00588       ast_free(cur);
00589    }
00590 }

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

Definition at line 3291 of file chan_mgcp.c.

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

03292 {
03293    int seqno=0;
03294    time_t now;
03295    struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
03296    time(&now);
03297    if (sscanf(req->identifier, "%30d", &seqno) != 1) 
03298       seqno = 0;
03299    cur = sub->parent->parent->responses;
03300    while(cur) {
03301       next = cur->next;
03302       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03303          /* Delete this entry */
03304          if (prev)
03305             prev->next = next;
03306          else
03307             sub->parent->parent->responses = next;
03308          ast_free(cur);
03309       } else {
03310          if (seqno == cur->seqno)
03311             answer = cur;
03312          prev = cur;
03313       }
03314       cur = next;
03315    }
03316    if (answer) {
03317       resend_response(sub, answer);
03318       return 1;
03319    }
03320    return 0;
03321 }

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

find_command: (SC:) remove command transaction from queue

Definition at line 2451 of file chan_mgcp.c.

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

Referenced by agi_handle_command(), ast_agi_register(), handle_cli_agi_show(), and handle_response().

02453 {
02454    struct mgcp_request *prev, *req;
02455 
02456    ast_mutex_lock(l);
02457    for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02458       if (req->trid == ident) {
02459          /* remove from queue */
02460          if (!prev)
02461             *queue = req->next;
02462          else
02463             prev->next = req->next;
02464 
02465          /* send next pending command */
02466          if (*queue) {
02467             if (mgcpdebug) {
02468                ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 
02469                   ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02470             }
02471 
02472             mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02473          }
02474          break;
02475       }
02476    }
02477    ast_mutex_unlock(l);
02478    return req;
02479 }

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

Definition at line 1654 of file chan_mgcp.c.

References __ourip, mgcp_gateway::addr, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_ouraddrfor(), ast_verb, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_subchannel::next, mgcp_gateway::next, mgcp_gateway::ourip, and mgcp_endpoint::sub.

Referenced by mgcp_request(), and mgcpsock_read().

01655 {
01656    struct mgcp_endpoint *p = NULL;
01657    struct mgcp_subchannel *sub = NULL;
01658    struct mgcp_gateway *g;
01659    char tmp[256] = "";
01660    char *at = NULL, *c;
01661    int found = 0;
01662    if (name) {
01663       ast_copy_string(tmp, name, sizeof(tmp));
01664       at = strchr(tmp, '@');
01665       if (!at) {
01666          ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01667          return NULL;
01668       }
01669       *at++ = '\0';
01670    }
01671    ast_mutex_lock(&gatelock);
01672    if (at && (at[0] == '[')) {
01673       at++;
01674       c = strrchr(at, ']');
01675       if (c)
01676          *c = '\0';
01677    }
01678    g = gateways;
01679    while(g) {
01680       if ((!name || !strcasecmp(g->name, at)) && 
01681           (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01682          /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
01683          if (sin && g->dynamic && name) {
01684             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01685                (g->addr.sin_port != sin->sin_port)) {
01686                memcpy(&g->addr, sin, sizeof(g->addr));
01687                if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
01688                   memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01689                ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
01690             }
01691          }
01692          /* not dynamic, check if the name matches */
01693          else if (name) {
01694             if (strcasecmp(g->name, at)) {
01695                g = g->next;
01696                continue;
01697             }
01698          }
01699          /* not dynamic, no name, check if the addr matches */
01700          else if (!name && sin) {
01701             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01702                 (g->addr.sin_port != sin->sin_port)) {
01703                g = g->next;
01704                continue;
01705             }
01706          } else {
01707             g = g->next;
01708             continue;
01709          }
01710          /* SC */
01711          p = g->endpoints;
01712          while(p) {
01713             ast_debug(1, "Searching on %s@%s for subchannel\n",
01714                p->name, g->name);
01715             if (msgid) {
01716 #if 0 /* new transport mech */
01717                sub = p->sub;
01718                do {
01719                   ast_debug(1, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
01720                      p->name, g->name, sub->id, msgid);
01721                   if (sub->lastout == msgid) {
01722                      ast_debug(1, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
01723                         sub->id, msgid, sub->lastout);
01724                      found = 1;
01725                      break;
01726                   }
01727                   sub = sub->next;
01728                } while (sub != p->sub);
01729                if (found) {
01730                   break;
01731                }
01732 #endif
01733                /* SC */
01734                sub = p->sub;
01735                found = 1;
01736                /* SC */
01737                break;
01738             } else if (name && !strcasecmp(p->name, tmp)) {
01739                ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
01740                   p->name, g->name, p->sub->id);
01741                sub = p->sub;
01742                found = 1;
01743                break;
01744             }
01745             p = p->next;
01746          }
01747          if (sub && found) {
01748             ast_mutex_lock(&sub->lock);
01749             break;
01750          }
01751       }
01752       g = g->next;
01753    }
01754    ast_mutex_unlock(&gatelock);
01755    if (!sub) {
01756       if (name) {
01757          if (g)
01758             ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01759          else
01760             ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01761       } 
01762    }
01763    return sub;
01764 }

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

get_csv: (SC:) get comma separated value

Definition at line 1633 of file chan_mgcp.c.

References s.

Referenced by handle_response().

01634 {
01635    char *s;
01636 
01637    *next = NULL, *len = 0;
01638    if (!c) return NULL;
01639 
01640    while (*c && (*c < 33 || *c == ','))
01641       c++;
01642 
01643    s = c;
01644    while (*c && (*c >= 33 && *c != ','))
01645       c++, (*len)++;
01646    *next = c;
01647 
01648    if (*len == 0)
01649       s = NULL, *next = NULL;
01650 
01651    return s;
01652 }

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

Definition at line 1626 of file chan_mgcp.c.

References __get_header().

Referenced by __transmit_response(), _sip_tcp_helper_thread(), build_route(), check_auth(), check_user_full(), check_via(), check_via_response(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), gettag(), handle_incoming(), handle_request(), handle_request_bye(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_refer(), handle_response_register(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), proc_422_rsp(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_sipredirect(), transmit_fake_auth_response(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_state_notify().

01627 {
01628    int start = 0;
01629    return __get_header(req, name, &start);
01630 }

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

Definition at line 1578 of file chan_mgcp.c.

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

Referenced by process_sdp().

01579 {
01580    int x;
01581    int len = strlen(name);
01582    char *r;
01583 
01584    for (x=0; x<req->lines; x++) {
01585       r = get_sdp_by_line(req->line[x], name, len);
01586       if (r[0] != '\0') return r;
01587    }
01588    return "";
01589 }

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

Definition at line 1568 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01569 {
01570    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01571       char* r = line + nameLen + 1;
01572       while (*r && (*r < 33)) ++r;
01573       return r;
01574    }
01575    return "";
01576 }

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

Definition at line 1596 of file chan_mgcp.c.

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

Referenced by get_ip_and_port_from_sdp(), and process_sdp().

01597 {
01598    int len = strlen(name);
01599    char *r;
01600    while (*iterator < req->lines) {
01601       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01602       if (r[0] != '\0') return r;
01603    }
01604    return "";
01605 }

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

Definition at line 2967 of file chan_mgcp.c.

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

Referenced by handle_request().

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

static char* handle_mgcp_audit_endpoint ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1077 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcpdebug, mgcp_gateway::name, mgcp_gateway::next, transmit_audit_endpoint(), and ast_cli_entry::usage.

01078 {
01079    struct mgcp_gateway  *mg;
01080    struct mgcp_endpoint *me;
01081    int found = 0;
01082    char *ename,*gname, *c;
01083 
01084    switch (cmd) {
01085    case CLI_INIT:
01086       e->command = "mgcp audit endpoint";
01087       e->usage =
01088          "Usage: mgcp audit endpoint <endpointid>\n"
01089          "       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
01090          "       mgcp debug MUST be on to see the results of this command.\n";
01091       return NULL;
01092    case CLI_GENERATE:
01093       return NULL;
01094    }
01095 
01096    if (!mgcpdebug) {
01097       return CLI_SHOWUSAGE;
01098    }
01099    if (a->argc != 4)
01100       return CLI_SHOWUSAGE;
01101    /* split the name into parts by null */
01102    ename = a->argv[3];
01103    gname = ename;
01104    while (*gname) {
01105       if (*gname == '@') {
01106          *gname = 0;
01107          gname++;
01108          break;
01109       }
01110       gname++;
01111    }
01112    if (gname[0] == '[')
01113       gname++;
01114    if ((c = strrchr(gname, ']')))
01115       *c = '\0';
01116    ast_mutex_lock(&gatelock);
01117    mg = gateways;
01118    while(mg) {
01119       if (!strcasecmp(mg->name, gname)) {
01120          me = mg->endpoints;
01121          while(me) {
01122             if (!strcasecmp(me->name, ename)) {
01123                found = 1;
01124                transmit_audit_endpoint(me);
01125                break;
01126             }
01127             me = me->next;
01128          }
01129          if (found) {
01130             break;
01131          }
01132       }
01133       mg = mg->next;
01134    }
01135    if (!found) {
01136       ast_cli(a->fd, "   << Could not find endpoint >>     ");
01137    }
01138    ast_mutex_unlock(&gatelock);
01139    return CLI_SUCCESS;
01140 }

static char* handle_mgcp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1167 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mgcpdebug, and ast_cli_entry::usage.

01168 {
01169    switch (cmd) {
01170    case CLI_INIT:
01171       e->command = "mgcp set debug {on|off}";
01172       e->usage =
01173          "Usage: mgcp set debug {on|off}\n"
01174          "       Enables/Disables dumping of MGCP packets for debugging purposes\n";   
01175       return NULL;
01176    case CLI_GENERATE:
01177       return NULL;
01178    }
01179 
01180    if (a->argc != e->args)
01181       return CLI_SHOWUSAGE;
01182 
01183    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
01184       mgcpdebug = 1;
01185       ast_cli(a->fd, "MGCP Debugging Enabled\n");
01186    } else if (!strncasecmp(a->argv[3], "off", 3)) {
01187       mgcpdebug = 0;
01188       ast_cli(a->fd, "MGCP Debugging Disabled\n");
01189    } else {
01190       return CLI_SHOWUSAGE;
01191    }
01192    return CLI_SUCCESS;
01193 }

static char* handle_mgcp_set_debug_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1142 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mgcpdebug, and ast_cli_entry::usage.

01143 {
01144    switch (cmd) {
01145    case CLI_INIT:
01146       e->command = "mgcp set debug [off]";
01147       e->usage =
01148          "Usage: mgcp set debug [off]\n"
01149          "       Enables/Disables dumping of MGCP packets for debugging purposes\n";   
01150       return NULL;
01151    case CLI_GENERATE:
01152       return NULL;
01153    }
01154 
01155    if (a->argc < 3 || a->argc > 4)
01156       return CLI_SHOWUSAGE;
01157    if (a->argc == 3) {
01158       mgcpdebug = 1;
01159       ast_cli(a->fd, "MGCP Debugging Enabled\n");
01160    } else if (!strncasecmp(a->argv[3], "off", 3)) {
01161       mgcpdebug = 0;
01162       ast_cli(a->fd, "MGCP Debugging Disabled\n");
01163    }
01164    return CLI_SUCCESS;
01165 }

static char* handle_mgcp_show_endpoints ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1037 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcp_gateway::name, mgcp_gateway::next, ast_cli_entry::usage, and mgcp_gateway::wcardep.

01038 {
01039    struct mgcp_gateway  *mg;
01040    struct mgcp_endpoint *me;
01041    int hasendpoints = 0;
01042 
01043    switch (cmd) {
01044    case CLI_INIT:
01045       e->command = "mgcp show endpoints";
01046       e->usage =
01047          "Usage: mgcp show endpoints\n"
01048          "       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
01049       return NULL;
01050    case CLI_GENERATE:
01051       return NULL;
01052    }
01053 
01054    if (a->argc != 3) 
01055       return CLI_SHOWUSAGE;
01056    ast_mutex_lock(&gatelock);
01057    mg = gateways;
01058    while(mg) {
01059       me = mg->endpoints;
01060       ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static");
01061       while(me) {
01062          /* Don't show wilcard endpoint */
01063          if (strcmp(me->name, mg->wcardep) != 0)
01064             ast_cli(a->fd, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
01065          hasendpoints = 1;
01066          me = me->next;
01067       }
01068       if (!hasendpoints) {
01069          ast_cli(a->fd, "   << No Endpoints Defined >>     ");
01070       }
01071       mg = mg->next;
01072    }
01073    ast_mutex_unlock(&gatelock);
01074    return CLI_SUCCESS;
01075 }

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

Definition at line 3049 of file chan_mgcp.c.

References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_DOWN, AST_STATE_UP, ast_verb, ast_verbose, attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmf_buf, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, f, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_CONF, MGCP_CX_MUTE, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_frame(), mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, transmit_audit_endpoint(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_response(), mgcp_request::verb, and mgcp_gateway::wcardep.

Referenced by mgcpsock_read().

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

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

References ast_copy_string(), ast_free, ast_log(), ast_strlen_zero(), ast_verb, 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(), get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, len(), mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, 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(), and transmit_notify_request().

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

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

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

Definition at line 462 of file chan_mgcp.c.

References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), mgcp_endpoint::mailbox, mbox(), and strsep().

00463 {
00464    int new_msgs;
00465    struct ast_event *event;
00466    char *mbox, *cntx;
00467 
00468    cntx = mbox = ast_strdupa(p->mailbox);
00469    strsep(&cntx, "@");
00470    if (ast_strlen_zero(cntx))
00471       cntx = "default";
00472 
00473    event = ast_event_get_cached(AST_EVENT_MWI,
00474       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
00475       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
00476       AST_EVENT_IE_END);
00477 
00478    if (event) {
00479       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
00480       ast_event_destroy(event);
00481    } else
00482       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
00483 
00484    return new_msgs;
00485 }

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

Definition at line 2015 of file chan_mgcp.c.

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

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

02016 {
02017    /* Initialize a response */
02018    if (req->headers || req->len) {
02019       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02020       return -1;
02021    }
02022    req->header[req->headers] = req->data + req->len;
02023    /* check if we need brackets around the gw name */
02024    if (p->parent->isnamedottedip)
02025       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);
02026    else
02027       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);
02028    req->len += strlen(req->header[req->headers]);
02029    if (req->headers < MGCP_MAX_HEADERS)
02030       req->headers++;
02031    else
02032       ast_log(LOG_WARNING, "Out of header space\n");
02033    return 0;
02034 }

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

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

01999 {
02000    /* Initialize a response */
02001    if (req->headers || req->len) {
02002       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02003       return -1;
02004    }
02005    req->header[req->headers] = req->data + req->len;
02006    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
02007    req->len += strlen(req->header[req->headers]);
02008    if (req->headers < MGCP_MAX_HEADERS)
02009       req->headers++;
02010    else
02011       ast_log(LOG_WARNING, "Out of header space\n");
02012    return 0;
02013 }

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

Definition at line 4281 of file chan_mgcp.c.

References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), cli_mgcp, io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, mgcp_rtp, mgcp_tech, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().

04282 {
04283    if (!(sched = sched_context_create())) {
04284       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04285       return AST_MODULE_LOAD_FAILURE;
04286    }
04287 
04288    if (!(io = io_context_create())) {
04289       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04290       sched_context_destroy(sched);
04291       return AST_MODULE_LOAD_FAILURE;
04292    }
04293 
04294    if (reload_config(0))
04295       return AST_MODULE_LOAD_DECLINE;
04296 
04297    /* Make sure we can register our mgcp channel type */
04298    if (ast_channel_register(&mgcp_tech)) {
04299       ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04300       io_context_destroy(io);
04301       sched_context_destroy(sched);
04302       return AST_MODULE_LOAD_FAILURE;
04303    }
04304 
04305    ast_rtp_proto_register(&mgcp_rtp);
04306    ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04307    
04308    /* And start the monitor for the first time */
04309    restart_monitor();
04310 
04311    return AST_MODULE_LOAD_SUCCESS;
04312 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

Definition at line 1203 of file chan_mgcp.c.

References ast_channel::_state, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verb, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_subchannel::lock, MGCP_CX_SENDRECV, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().

01204 {
01205    int res = 0;
01206    struct mgcp_subchannel *sub = ast->tech_pvt;
01207    struct mgcp_endpoint *p = sub->parent;
01208 
01209    ast_mutex_lock(&sub->lock);
01210    sub->cxmode = MGCP_CX_SENDRECV;
01211    if (!sub->rtp) {
01212       start_rtp(sub);
01213    } else {
01214       transmit_modify_request(sub);
01215    }
01216    ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
01217          ast->name, p->name, p->parent->name, sub->id);
01218    if (ast->_state != AST_STATE_UP) {
01219       ast_setstate(ast, AST_STATE_UP);
01220       ast_debug(1, "mgcp_answer(%s)\n", ast->name);
01221       transmit_notify_request(sub, "");
01222       transmit_modify_request(sub);
01223    }
01224    ast_mutex_unlock(&sub->lock);
01225    return res;
01226 }

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

Definition at line 843 of file chan_mgcp.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_copy_string(), 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_verb, mgcp_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcpdebug, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, and ast_channel::varshead.

00844 {
00845    int res;
00846    struct mgcp_endpoint *p;
00847    struct mgcp_subchannel *sub;
00848    char tone[50] = "";
00849    const char *distinctive_ring = NULL;
00850    struct varshead *headp;
00851    struct ast_var_t *current;
00852 
00853    if (mgcpdebug) {
00854       ast_verb(3, "MGCP mgcp_call(%s)\n", ast->name);
00855    }
00856    sub = ast->tech_pvt;
00857    p = sub->parent;
00858    headp = &ast->varshead;
00859    AST_LIST_TRAVERSE(headp,current,entries) {
00860       /* Check whether there is an ALERT_INFO variable */
00861       if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
00862          distinctive_ring = ast_var_value(current);
00863       }
00864    }
00865 
00866    ast_mutex_lock(&sub->lock);
00867    switch (p->hookstate) {
00868    case MGCP_OFFHOOK:
00869       if (!ast_strlen_zero(distinctive_ring)) {
00870          snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
00871          if (mgcpdebug) {
00872             ast_verb(3, "MGCP distinctive callwait %s\n", tone);
00873          }
00874       } else {
00875          ast_copy_string(tone, "L/wt", sizeof(tone));
00876          if (mgcpdebug) {
00877             ast_verb(3, "MGCP normal callwait %s\n", tone);
00878          }
00879       }
00880       break;
00881    case MGCP_ONHOOK:
00882    default:
00883       if (!ast_strlen_zero(distinctive_ring)) {
00884          snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
00885          if (mgcpdebug) {
00886             ast_verb(3, "MGCP distinctive ring %s\n", tone);
00887          }
00888       } else {
00889          ast_copy_string(tone, "L/rg", sizeof(tone));
00890          if (mgcpdebug) {
00891             ast_verb(3, "MGCP default ring\n");
00892          }
00893       }
00894       break;
00895    }
00896 
00897    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00898       ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
00899       ast_mutex_unlock(&sub->lock);
00900       return -1;
00901    }
00902 
00903    res = 0;
00904    sub->outgoing = 1;
00905    sub->cxmode = MGCP_CX_RECVONLY;
00906    if (p->type == TYPE_LINE) {
00907       if (!sub->rtp) {
00908          start_rtp(sub);
00909       } else {
00910          transmit_modify_request(sub);
00911       }
00912 
00913       if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00914          /* try to prevent a callwait from disturbing the other connection */
00915          sub->next->cxmode = MGCP_CX_RECVONLY;
00916          transmit_modify_request(sub->next);
00917       }
00918 
00919       transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
00920       ast_setstate(ast, AST_STATE_RINGING);
00921 
00922       if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
00923          /* Put the connection back in sendrecv */
00924          sub->next->cxmode = MGCP_CX_SENDRECV;
00925          transmit_modify_request(sub->next);
00926       }
00927    } else {
00928       ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
00929       res = -1;
00930    }
00931    ast_mutex_unlock(&sub->lock);
00932    ast_queue_control(ast, AST_CONTROL_RINGING);
00933    return res;
00934 }

static int mgcp_devicestate ( void *  data  )  [static]

mgcp_devicestate: channel callback for device status monitoring

Parameters:
data tech/resource name of MGCP device to query
Callback for device state management in channel subsystem to obtain device status (up/down) of a specific MGCP endpoint

Returns:
device status result (from devicestate.h) AST_DEVICE_INVALID (not available) or AST_DEVICE_UNKNOWN (available but unknown state)

Definition at line 1372 of file chan_mgcp.c.

References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, and mgcp_gateway::next.

01373 {
01374    struct mgcp_gateway  *g;
01375    struct mgcp_endpoint *e = NULL;
01376    char *tmp, *endpt, *gw;
01377    int ret = AST_DEVICE_INVALID;
01378 
01379    endpt = ast_strdupa(data);
01380    if ((tmp = strchr(endpt, '@'))) {
01381       *tmp++ = '\0';
01382       gw = tmp;
01383    } else
01384       goto error;
01385 
01386    ast_mutex_lock(&gatelock);
01387    g = gateways;
01388    while (g) {
01389       if (strcasecmp(g->name, gw) == 0) {
01390          e = g->endpoints;
01391          break;
01392       }
01393       g = g->next;
01394    }
01395 
01396    if (!e)
01397       goto error;
01398 
01399    while (e) {
01400       if (strcasecmp(e->name, endpt) == 0)
01401          break;
01402       e = e->next;
01403    }
01404 
01405    if (!e)
01406       goto error;
01407 
01408    /*
01409     * As long as the gateway/endpoint is valid, we'll
01410     * assume that the device is available and its state
01411     * can be tracked.
01412     */
01413    ret = AST_DEVICE_UNKNOWN;
01414 
01415 error:
01416    ast_mutex_unlock(&gatelock);
01417    return ret;
01418 }

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

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

01300 {
01301    struct mgcp_subchannel *sub = newchan->tech_pvt;
01302 
01303    ast_mutex_lock(&sub->lock);
01304    ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
01305    if (sub->owner != oldchan) {
01306       ast_mutex_unlock(&sub->lock);
01307       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
01308       return -1;
01309    }
01310    sub->owner = newchan;
01311    ast_mutex_unlock(&sub->lock);
01312    return 0;
01313 }

static enum ast_rtp_get_result mgcp_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 3973 of file chan_mgcp.c.

References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, mgcp_endpoint::canreinvite, chan, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.

03974 {
03975    struct mgcp_subchannel *sub = NULL;
03976 
03977    if (!(sub = chan->tech_pvt) || !(sub->rtp))
03978       return AST_RTP_GET_FAILED;
03979 
03980    *rtp = sub->rtp;
03981 
03982    if (sub->parent->canreinvite)
03983       return AST_RTP_TRY_NATIVE;
03984    else
03985       return AST_RTP_TRY_PARTIAL;
03986 }

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 936 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_debug, ast_dsp_free(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, 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(), and transmit_notify_request_with_callerid().

00937 {
00938    struct mgcp_subchannel *sub = ast->tech_pvt;
00939    struct mgcp_endpoint *p = sub->parent;
00940 
00941    ast_debug(1, "mgcp_hangup(%s)\n", ast->name);
00942    if (!ast->tech_pvt) {
00943       ast_debug(1, "Asked to hangup channel not connected\n");
00944       return 0;
00945    }
00946    if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00947       ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
00948       return 0;
00949    }
00950    ast_mutex_lock(&sub->lock);
00951    if (mgcpdebug) {
00952       ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00953    }
00954 
00955    if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00956       /* check whether other channel is active. */
00957       if (!sub->next->owner) {
00958          if (p->dtmfmode & MGCP_DTMF_HYBRID)
00959             p->dtmfmode &= ~MGCP_DTMF_INBAND;
00960          if (mgcpdebug) {
00961             ast_verb(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00962          }
00963          ast_dsp_free(p->dsp);
00964          p->dsp = NULL;
00965       }
00966    }
00967 
00968    sub->owner = NULL;
00969    if (!ast_strlen_zero(sub->cxident)) {
00970       transmit_connection_del(sub);
00971    }
00972    sub->cxident[0] = '\0';
00973    if ((sub == p->sub) && sub->next->owner) {
00974       if (p->hookstate == MGCP_OFFHOOK) {
00975          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00976             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);
00977          }
00978       } else {
00979          /* set our other connection as the primary and swith over to it */
00980          p->sub = sub->next;
00981          p->sub->cxmode = MGCP_CX_RECVONLY;
00982          transmit_modify_request(p->sub);
00983          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00984             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);
00985          }
00986       }
00987 
00988    } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00989       transmit_notify_request(sub, "L/v");
00990    } else if (p->hookstate == MGCP_OFFHOOK) {
00991       transmit_notify_request(sub, "L/ro");
00992    } else {
00993       transmit_notify_request(sub, "");
00994    }
00995 
00996    ast->tech_pvt = NULL;
00997    sub->alreadygone = 0;
00998    sub->outgoing = 0;
00999    sub->cxmode = MGCP_CX_INACTIVE;
01000    sub->callid[0] = '\0';
01001    if (p) {
01002       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
01003    }
01004    /* Reset temporary destination */
01005    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
01006    if (sub->rtp) {
01007       ast_rtp_destroy(sub->rtp);
01008       sub->rtp = NULL;
01009    }
01010 
01011    ast_module_unref(ast_module_info->self);
01012 
01013    if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
01014       p->hidecallerid = 0;
01015       if (p->hascallwaiting && !p->callwaiting) {
01016          ast_verb(3, "Enabling call waiting on %s\n", ast->name);
01017          p->callwaiting = -1;
01018       }
01019       if (has_voicemail(p)) {
01020          if (mgcpdebug) {
01021             ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
01022                ast->name, p->name, p->parent->name);
01023          }
01024          transmit_notify_request(sub, "L/vmwi(+)");
01025       } else {
01026          if (mgcpdebug) {
01027             ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
01028                ast->name, p->name, p->parent->name);
01029          }
01030          transmit_notify_request(sub, "L/vmwi(-)");
01031       }
01032    }
01033    ast_mutex_unlock(&sub->lock);
01034    return 0;
01035 }

static int mgcp_indicate ( struct ast_channel ast,
int  ind,
const void *  data,
size_t  datalen 
) [static]

Definition at line 1452 of file chan_mgcp.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_change_source(), ast_rtp_new_source(), ast_verb, control2str(), mgcp_subchannel::lock, LOG_WARNING, mgcpdebug, ast_channel::name, ast_channel::tech_pvt, and transmit_notify_request().

01453 {
01454    struct mgcp_subchannel *sub = ast->tech_pvt;
01455    int res = 0;
01456 
01457    if (mgcpdebug) {
01458       ast_verb(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
01459          ind, control2str(ind), ast->name);
01460    }
01461    ast_mutex_lock(&sub->lock);
01462    switch(ind) {
01463    case AST_CONTROL_RINGING:
01464 #ifdef DLINK_BUGGY_FIRMWARE   
01465       transmit_notify_request(sub, "rt");
01466 #else
01467       transmit_notify_request(sub, "G/rt");
01468 #endif      
01469       break;
01470    case AST_CONTROL_BUSY:
01471       transmit_notify_request(sub, "L/bz");
01472       break;
01473    case AST_CONTROL_CONGESTION:
01474       transmit_notify_request(sub, "G/cg");
01475       break;
01476    case AST_CONTROL_HOLD:
01477       ast_moh_start(ast, data, NULL);
01478       break;
01479    case AST_CONTROL_UNHOLD:
01480       ast_moh_stop(ast);
01481       break;
01482    case AST_CONTROL_SRCUPDATE:
01483       ast_rtp_new_source(sub->rtp);
01484       break;
01485    case AST_CONTROL_SRCCHANGE:
01486       ast_rtp_change_source(sub->rtp);
01487       break;
01488    case -1:
01489       transmit_notify_request(sub, "");
01490       break;
01491    default:
01492       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01493       res = -1;
01494    }
01495    ast_mutex_unlock(&sub->lock);
01496    return res;
01497 }

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

Definition at line 1499 of file chan_mgcp.c.

References accountcode, mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, ast_channel::exten, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, language, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_tech, ast_channel::name, name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by handle_hd_hf(), and mgcp_request().

01500 {
01501    struct ast_channel *tmp;
01502    struct mgcp_endpoint *i = sub->parent;
01503    int fmt;
01504 
01505    tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01506    if (tmp) {
01507       tmp->tech = &mgcp_tech;
01508       tmp->nativeformats = i->capability;
01509       if (!tmp->nativeformats)
01510          tmp->nativeformats = capability;
01511       fmt = ast_best_codec(tmp->nativeformats);
01512       ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
01513       if (sub->rtp)
01514          ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
01515       if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01516          i->dsp = ast_dsp_new();
01517          ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
01518          /* this is to prevent clipping of dtmf tones during dsp processing */
01519          ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01520       } else {
01521          i->dsp = NULL;
01522       }
01523       if (state == AST_STATE_RING)
01524          tmp->rings = 1;
01525       tmp->writeformat = fmt;
01526       tmp->rawwriteformat = fmt;
01527       tmp->readformat = fmt;
01528       tmp->rawreadformat = fmt;
01529       tmp->tech_pvt = sub;
01530       if (!ast_strlen_zero(i->language))
01531          ast_string_field_set(tmp, language, i->language);
01532       if (!ast_strlen_zero(i->accountcode))
01533          ast_string_field_set(tmp, accountcode, i->accountcode);
01534       if (i->amaflags)
01535          tmp->amaflags = i->amaflags;
01536       sub->owner = tmp;
01537       ast_module_ref(ast_module_info->self);
01538       tmp->callgroup = i->callgroup;
01539       tmp->pickupgroup = i->pickupgroup;
01540       ast_string_field_set(tmp, call_forward, i->call_forward);
01541       ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
01542       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
01543 
01544       /* Don't use ast_set_callerid() here because it will
01545        * generate a needless NewCallerID event */
01546       tmp->cid.cid_ani = ast_strdup(i->cid_num);
01547       
01548       if (!i->adsi)
01549          tmp->adsicpe = AST_ADSI_UNAVAILABLE;
01550       tmp->priority = 1;
01551       if (sub->rtp)
01552          ast_jb_configure(tmp, &global_jbconf);
01553       if (state != AST_STATE_DOWN) {
01554          if (ast_pbx_start(tmp)) {
01555             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
01556             ast_hangup(tmp);
01557             tmp = NULL;
01558          }
01559       }
01560       ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
01561             tmp->name, ast_state2str(state));
01562    } else {
01563       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01564    }
01565    return tmp;
01566 }

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

Definition at line 693 of file chan_mgcp.c.

References __mgcp_xmit(), ast_free, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_tvnow(), DEFAULT_RETRANS, msg, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, mgcp_endpoint::next, mgcp_endpoint::parent, retrans_pkt(), and mgcp_gateway::retransid.

Referenced by find_command(), and send_request().

00695 {
00696    struct mgcp_message *msg;
00697    struct mgcp_message *cur;
00698    struct mgcp_gateway *gw;
00699    struct timeval now;
00700 
00701    msg = ast_malloc(sizeof(*msg) + len);
00702    if (!msg) {
00703       return -1;
00704    }
00705    gw = ((p && p->parent) ? p->parent : NULL);
00706    if (!gw) {
00707       ast_free(msg);
00708       return -1;
00709    }
00710 /* SC
00711    time(&t);
00712    if (gw->messagepending && (gw->lastouttime + 20 < t)) {
00713       ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
00714          gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
00715       dump_queue(sub->parent);
00716    }
00717 */
00718    msg->owner_sub = sub;
00719    msg->owner_ep = p;
00720    msg->seqno = seqno;
00721    msg->next = NULL;
00722    msg->len = len;
00723    msg->retrans = 0;
00724    memcpy(msg->buf, data, msg->len);
00725 
00726    ast_mutex_lock(&gw->msgs_lock);
00727    cur = gw->msgs;
00728    if (cur) {
00729       while(cur->next)
00730          cur = cur->next;
00731       cur->next = msg;
00732    } else {
00733       gw->msgs = msg;
00734    }
00735 
00736    now = ast_tvnow();
00737    msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS;
00738 
00739    if (gw->retransid == -1)
00740       gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00741    ast_mutex_unlock(&gw->msgs_lock);
00742 /* SC
00743    if (!gw->messagepending) {
00744       gw->messagepending = 1;
00745       gw->lastout = seqno;
00746       gw->lastouttime = t;
00747 */
00748    __mgcp_xmit(gw, msg->buf, msg->len);
00749       /* XXX Should schedule retransmission XXX */
00750 /* SC
00751    } else
00752       ast_debug(1, "Deferring transmission of transaction %d\n", seqno);
00753 */
00754    return 0;
00755 }

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

Definition at line 624 of file chan_mgcp.c.

References AST_FRAME_CONTROL, f, and mgcp_queue_frame().

Referenced by handle_hd_hf().

00625 {
00626    struct ast_frame f = { AST_FRAME_CONTROL, };
00627    f.subclass = control;
00628    return mgcp_queue_frame(sub, &f);
00629 }

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

Definition at line 592 of file chan_mgcp.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, mgcp_subchannel::lock, and mgcp_subchannel::owner.

Referenced by handle_request(), and mgcp_queue_control().

00593 {
00594    for(;;) {
00595       if (sub->owner) {
00596          if (!ast_channel_trylock(sub->owner)) {
00597             ast_queue_frame(sub->owner, f);
00598             ast_channel_unlock(sub->owner);
00599             break;
00600          } else {
00601             DEADLOCK_AVOIDANCE(&sub->lock);
00602          }
00603       } else
00604          break;
00605    }
00606 }

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

Definition at line 608 of file chan_mgcp.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.

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

00609 {
00610    for(;;) {
00611       if (sub->owner) {
00612          if (!ast_channel_trylock(sub->owner)) {
00613             ast_queue_hangup(sub->owner);
00614             ast_channel_unlock(sub->owner);
00615             break;
00616          } else {
00617             DEADLOCK_AVOIDANCE(&sub->lock);
00618          }
00619       } else
00620          break;
00621    }
00622 }

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

Definition at line 1259 of file chan_mgcp.c.

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

01260 {
01261    struct ast_frame *f;
01262    struct mgcp_subchannel *sub = ast->tech_pvt;
01263    ast_mutex_lock(&sub->lock);
01264    f = mgcp_rtp_read(sub);
01265    ast_mutex_unlock(&sub->lock);
01266    return f;
01267 }

static char * mgcp_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4314 of file chan_mgcp.c.

References ast_cli_args::argc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, LOG_WARNING, mgcp_reload_lock, mgcp_reloading, restart_monitor(), and ast_cli_entry::usage.

Referenced by reload(), and unload_module().

04315 {
04316    static int deprecated = 0;
04317 
04318    if (e) {
04319       switch (cmd) {
04320       case CLI_INIT:
04321          e->command = "mgcp reload";
04322          e->usage =
04323             "Usage: mgcp reload\n"
04324             "       'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n";
04325          return NULL;
04326       case CLI_GENERATE:
04327          return NULL;
04328       }
04329    }
04330 
04331    if (!deprecated && a && a->argc > 0) {
04332       ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
04333       deprecated = 1;
04334    }
04335 
04336    ast_mutex_lock(&mgcp_reload_lock);
04337    if (mgcp_reloading) {
04338       ast_verbose("Previous mgcp reload not yet done\n");
04339    } else
04340       mgcp_reloading = 1;
04341    ast_mutex_unlock(&mgcp_reload_lock);
04342    restart_monitor();
04343    return CLI_SUCCESS;
04344 }

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

Definition at line 3527 of file chan_mgcp.c.

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

03528 {
03529    int oldformat;
03530    struct mgcp_subchannel *sub;
03531    struct ast_channel *tmpc = NULL;
03532    char tmp[256];
03533    char *dest = data;
03534 
03535    oldformat = format;
03536    format &= capability;
03537    if (!format) {
03538       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03539       return NULL;
03540    }
03541    ast_copy_string(tmp, dest, sizeof(tmp));
03542    if (ast_strlen_zero(tmp)) {
03543       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03544       return NULL;
03545    }
03546    sub = find_subchannel_and_lock(tmp, 0, NULL);
03547    if (!sub) {
03548       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03549       *cause = AST_CAUSE_UNREGISTERED;
03550       return NULL;
03551    }
03552    
03553    ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
03554    ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03555          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03556    /* Must be busy */
03557    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03558       ((!sub->parent->callwaiting) && (sub->owner)) ||
03559        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03560       if (sub->parent->hookstate == MGCP_ONHOOK) {
03561          if (has_voicemail(sub->parent)) {
03562             transmit_notify_request(sub,"L/vmwi(+)");
03563          } else {
03564             transmit_notify_request(sub,"L/vmwi(-)");
03565          }
03566       }
03567       *cause = AST_CAUSE_BUSY;
03568       ast_mutex_unlock(&sub->lock);
03569       return NULL;
03570    }
03571    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03572    ast_mutex_unlock(&sub->lock);
03573    if (!tmpc)
03574       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03575    restart_monitor();
03576    return tmpc;
03577 }

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

Definition at line 1228 of file chan_mgcp.c.

References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, f, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, and ast_channel::writeformat.

Referenced by mgcp_read().

01229 {
01230    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
01231    struct ast_frame *f;
01232 
01233    f = ast_rtp_read(sub->rtp);
01234    /* Don't send RFC2833 if we're not supposed to */
01235    if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01236       return &ast_null_frame;
01237    if (sub->owner) {
01238       /* We already hold the channel lock */
01239       if (f->frametype == AST_FRAME_VOICE) {
01240          if (f->subclass != sub->owner->nativeformats) {
01241             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
01242             sub->owner->nativeformats = f->subclass;
01243             ast_set_read_format(sub->owner, sub->owner->readformat);
01244             ast_set_write_format(sub->owner, sub->owner->writeformat);
01245          }
01246          /* Courtesy fearnor aka alex@pilosoft.com */
01247          if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01248 #if 0
01249             ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01250 #endif
01251             f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01252          }
01253       }
01254    }
01255    return f;
01256 }

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

Definition at line 1315 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, and ast_channel::tech_pvt.

01316 {
01317    struct mgcp_subchannel *sub = ast->tech_pvt;
01318    struct mgcp_endpoint *p = sub->parent;
01319    int res = 0;
01320 
01321    ast_mutex_lock(&sub->lock);
01322    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01323       ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n");
01324       res = -1; /* Let asterisk play inband indications */
01325    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01326       ast_log(LOG_DEBUG, "Sending DTMF using RFC2833");
01327       ast_rtp_senddigit_begin(sub->rtp, digit);
01328    } else {
01329       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01330    }
01331    ast_mutex_unlock(&sub->lock);
01332 
01333    return res;
01334 }

static int mgcp_senddigit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 1336 of file chan_mgcp.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_end(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, and transmit_notify_request().

01337 {
01338    struct mgcp_subchannel *sub = ast->tech_pvt;
01339    struct mgcp_endpoint *p = sub->parent;
01340    int res = 0;
01341    char tmp[4];
01342 
01343    ast_mutex_lock(&sub->lock);
01344    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01345       ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n");
01346       res = -1; /* Tell Asterisk to stop inband indications */
01347    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01348       ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n");
01349       tmp[0] = 'D';
01350       tmp[1] = '/';
01351       tmp[2] = digit;
01352       tmp[3] = '\0';
01353       transmit_notify_request(sub, tmp);
01354                 ast_rtp_senddigit_end(sub->rtp, digit);
01355    } else {
01356       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01357    }
01358    ast_mutex_unlock(&sub->lock);
01359 
01360    return res;
01361 }

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

Definition at line 3988 of file chan_mgcp.c.

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

03989 {
03990    /* XXX Is there such thing as video support with MGCP? XXX */
03991    struct mgcp_subchannel *sub;
03992    sub = chan->tech_pvt;
03993    if (sub && !sub->alreadygone) {
03994       transmit_modify_with_sdp(sub, rtp, codecs);
03995       return 0;
03996    }
03997    return -1;
03998 }

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

Definition at line 2666 of file chan_mgcp.c.

References ast_bridged_channel(), ast_canmatch_extension(), ast_copy_string(), ast_db_put(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strlen_zero(), ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, chan, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, and transmit_notify_request().

Referenced by handle_hd_hf().

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

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

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

01270 {
01271    struct mgcp_subchannel *sub = ast->tech_pvt;
01272    int res = 0;
01273    if (frame->frametype != AST_FRAME_VOICE) {
01274       if (frame->frametype == AST_FRAME_IMAGE)
01275          return 0;
01276       else {
01277          ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01278          return 0;
01279       }
01280    } else {
01281       if (!(frame->subclass & ast->nativeformats)) {
01282          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
01283             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
01284          return -1;
01285       }
01286    }
01287    if (sub) {
01288       ast_mutex_lock(&sub->lock);
01289       if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01290          if (sub->rtp) {
01291             res =  ast_rtp_write(sub->rtp, frame);
01292          }
01293       }
01294       ast_mutex_unlock(&sub->lock);
01295    }
01296    return res;
01297 }

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

Definition at line 3323 of file chan_mgcp.c.

References ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, ast_strlen_zero(), ast_verbose, errno, find_and_retrans(), find_subchannel_and_lock(), handle_request(), handle_response(), len(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_subchannel::parent, parse(), mgcp_gateway::retransid, and mgcp_message::seqno.

Referenced by do_monitor().

03324 {
03325    struct mgcp_request req;
03326    struct sockaddr_in sin;
03327    struct mgcp_subchannel *sub;
03328    int res;
03329    socklen_t len;
03330    int result;
03331    int ident;
03332    len = sizeof(sin);
03333    memset(&req, 0, sizeof(req));
03334    res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03335    if (res < 0) {
03336       if (errno != ECONNREFUSED)
03337          ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03338       return 1;
03339    }
03340    req.data[res] = '\0';
03341    req.len = res;
03342    if (mgcpdebug) {
03343       ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03344    }
03345    parse(&req);
03346    if (req.headers < 1) {
03347       /* Must have at least one header */
03348       return 1;
03349    }
03350    if (ast_strlen_zero(req.identifier)) {
03351       ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03352       return 1;
03353    }
03354 
03355    if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
03356       /* Try to find who this message is for, if it's important */
03357       sub = find_subchannel_and_lock(NULL, ident, &sin);
03358       if (sub) {
03359          struct mgcp_gateway *gw = sub->parent->parent;
03360          struct mgcp_message *cur, *prev;
03361 
03362          ast_mutex_unlock(&sub->lock);
03363          ast_mutex_lock(&gw->msgs_lock);
03364          for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03365             if (cur->seqno == ident) {
03366                ast_debug(1, "Got response back on transaction %d\n", ident);
03367                if (prev)
03368                   prev->next = cur->next;
03369                else
03370                   gw->msgs = cur->next;
03371                break;
03372             }
03373          }
03374 
03375          /* stop retrans timer if the queue is empty */
03376          if (!gw->msgs) {
03377             AST_SCHED_DEL(sched, gw->retransid);
03378          }
03379 
03380          ast_mutex_unlock(&gw->msgs_lock);
03381          if (cur) {
03382             handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03383             ast_free(cur);
03384             return 1;
03385          }
03386 
03387          ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 
03388             gw->name, ident);
03389       }
03390    } else {
03391       if (ast_strlen_zero(req.endpoint) || 
03392             ast_strlen_zero(req.version) || 
03393          ast_strlen_zero(req.verb)) {
03394          ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03395          return 1;
03396       }
03397       /* Process request, with iflock held */
03398       sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03399       if (sub) {
03400          /* look first to find a matching response in the queue */
03401          if (!find_and_retrans(sub, &req))
03402             /* pass the request off to the currently mastering subchannel */
03403             handle_request(sub, &req, &sin);
03404          ast_mutex_unlock(&sub->lock);
03405       }
03406    }
03407    return 1;
03408 }

static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 454 of file chan_mgcp.c.

00455 {
00456    /* This module does not handle MWI in an event-based manner.  However, it
00457     * subscribes to MWI for each mailbox that is configured so that the core
00458     * knows that we care about it.  Then, chan_mgcp will get the MWI from the
00459     * event cache instead of checking the mailbox directly. */
00460 }

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1766 of file chan_mgcp.c.

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

Referenced by acf_channel_read(), acf_meetme_info(), add_agent(), app_exec(), aqm_exec(), ast_parse_allow_disallow(), astman_get_variables(), conf_exec(), conf_run(), config_function_read(), cut_internal(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), find_conf(), function_agent(), get_in_brackets(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), mgcpsock_read(), misdn_check_l2l1(), misdn_facility_exec(), misdn_set_opt_exec(), mixmonitor_exec(), oss_call(), oss_request(), park_call_exec(), pbx_builtin_background(), pbx_builtin_waitexten(), play_moh_exec(), pqm_exec(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), rcvfax_exec(), record_exec(), reload_agents(), reload_queues(), retrydial_exec(), rqm_exec(), sayunixtime_exec(), sendtext_exec(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), start_moh_exec(), start_monitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), and zapateller_exec().

01767 {
01768    /* Divide fields by NULL's */
01769    char *c;
01770    int f = 0;
01771    c = req->data;
01772 
01773    /* First header starts immediately */
01774    req->header[f] = c;
01775    while(*c) {
01776       if (*c == '\n') {
01777          /* We've got a new header */
01778          *c = 0;
01779 #if 0
01780          printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
01781 #endif         
01782          if (ast_strlen_zero(req->header[f])) {
01783             /* Line by itself means we're now in content */
01784             c++;
01785             break;
01786          }
01787          if (f >= MGCP_MAX_HEADERS - 1) {
01788             ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01789          } else
01790             f++;
01791          req->header[f] = c + 1;
01792       } else if (*c == '\r') {
01793          /* Ignore but eliminate \r's */
01794          *c = 0;
01795       }
01796       c++;
01797    }
01798    /* Check for last header */
01799    if (!ast_strlen_zero(req->header[f])) 
01800       f++;
01801    req->headers = f;
01802    /* Now we process any mime content */
01803    f = 0;
01804    req->line[f] = c;
01805    while(*c) {
01806       if (*c == '\n') {
01807          /* We've got a new line */
01808          *c = 0;
01809 #if 0
01810          printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
01811 #endif         
01812          if (f >= MGCP_MAX_LINES - 1) {
01813             ast_log(LOG_WARNING, "Too many SDP lines...\n");
01814          } else
01815             f++;
01816          req->line[f] = c + 1;
01817       } else if (*c == '\r') {
01818          /* Ignore and eliminate \r's */
01819          *c = 0;
01820       }
01821       c++;
01822    }
01823    /* Check for last line */
01824    if (!ast_strlen_zero(req->line[f])) 
01825       f++;
01826    req->lines = f;
01827    /* Parse up the initial header */
01828    c = req->header[0];
01829    while(*c && *c < 33) c++;
01830    /* First the verb */
01831    req->verb = c;
01832    while(*c && (*c > 32)) c++;
01833    if (*c) {
01834       *c = '\0';
01835       c++;
01836       while(*c && (*c < 33)) c++;
01837       req->identifier = c;
01838       while(*c && (*c > 32)) c++;
01839       if (*c) {
01840          *c = '\0';
01841          c++;
01842          while(*c && (*c < 33)) c++;
01843          req->endpoint = c;
01844          while(*c && (*c > 32)) c++;
01845          if (*c) {
01846             *c = '\0';
01847             c++;
01848             while(*c && (*c < 33)) c++;
01849             req->version = c;
01850             while(*c && (*c > 32)) c++;
01851             while(*c && (*c < 33)) c++;
01852             while(*c && (*c > 32)) c++;
01853             *c = '\0';
01854          }
01855       }
01856    }
01857       
01858    if (mgcpdebug) {
01859       ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01860          req->verb, req->identifier, req->endpoint, req->version);
01861       ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
01862    }
01863    if (*c) 
01864       ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01865 }

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

Definition at line 1867 of file chan_mgcp.c.

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

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

01868 {
01869    char *m;
01870    char *c;
01871    char *a;
01872    char host[258];
01873    int len;
01874    int portno;
01875    int peercapability, peerNonCodecCapability;
01876    struct sockaddr_in sin;
01877    char *codecs;
01878    struct ast_hostent ahp; struct hostent *hp;
01879    int codec, codec_count=0;
01880    int iterator;
01881    struct mgcp_endpoint *p = sub->parent;
01882 
01883    /* Get codec and RTP info from SDP */
01884    m = get_sdp(req, "m");
01885    c = get_sdp(req, "c");
01886    if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01887       ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01888       return -1;
01889    }
01890    if (sscanf(c, "IN IP4 %256s", host) != 1) {
01891       ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01892       return -1;
01893    }
01894    /* XXX This could block for a long time, and block the main thread! XXX */
01895    hp = ast_gethostbyname(host, &ahp);
01896    if (!hp) {
01897       ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01898       return -1;
01899    }
01900    if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) {
01901       ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
01902       return -1;
01903    }
01904    sin.sin_family = AF_INET;
01905    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01906    sin.sin_port = htons(portno);
01907    ast_rtp_set_peer(sub->rtp, &sin);
01908 #if 0
01909    printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01910 #endif   
01911    /* Scan through the RTP payload types specified in a "m=" line: */
01912    ast_rtp_pt_clear(sub->rtp);
01913    codecs = ast_strdupa(m + len);
01914    while (!ast_strlen_zero(codecs)) {
01915       if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
01916          if (codec_count)
01917             break;
01918          ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
01919          return -1;
01920       }
01921       ast_rtp_set_m_type(sub->rtp, codec);
01922       codec_count++;
01923       codecs += len;
01924    }
01925 
01926    /* Next, scan through each "a=rtpmap:" line, noting each */
01927    /* specified RTP payload type (with corresponding MIME subtype): */
01928    sdpLineNum_iterator_init(&iterator);
01929    while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
01930       char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
01931       if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2)
01932          continue;
01933       /* Note: should really look at the 'freq' and '#chans' params too */
01934       ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
01935    }
01936 
01937    /* Now gather all of the codecs that were asked for: */
01938    ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
01939    p->capability = capability & peercapability;
01940    if (mgcpdebug) {
01941       ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
01942          capability, peercapability, p->capability);
01943       ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
01944          nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
01945    }
01946    if (!p->capability) {
01947       ast_log(LOG_WARNING, "No compatible codecs!\n");
01948       return -1;
01949    }
01950    return 0;
01951 }

static void prune_gateways ( void   )  [static]

Definition at line 4062 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

04063 {
04064    struct mgcp_gateway *g, *z, *r;
04065    struct mgcp_endpoint *e, *p, *t;
04066 
04067    ast_mutex_lock(&gatelock);
04068 
04069    /* prune gateways */
04070    for (z = NULL, g = gateways; g;) {
04071       /* prune endpoints */
04072       for (p = NULL, e = g->endpoints; e; ) {
04073          if (e->delme || g->delme) {
04074             t = e;
04075             e = e->next;
04076             if (!p)
04077                g->endpoints = e;
04078             else
04079                p->next = e;
04080             destroy_endpoint(t);
04081          } else {
04082             p = e;
04083             e = e->next;
04084          }
04085       }
04086 
04087       if (g->delme) {
04088          r = g;
04089          g = g->next;
04090          if (!z)
04091             gateways = g;
04092          else
04093             z->next = g;
04094 
04095          destroy_gateway(r);
04096       } else {
04097          z = g;
04098          g = g->next;
04099       }
04100    }
04101 
04102    ast_mutex_unlock(&gatelock);
04103 }

static int reload ( void   )  [static]

Definition at line 4346 of file chan_mgcp.c.

References mgcp_reload().

04347 {
04348    mgcp_reload(NULL, 0, NULL);
04349    return 0;
04350 }

static int reload_config ( int  reload  )  [static]

Definition at line 4105 of file chan_mgcp.c.

References __ourip, ahp, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_jb_read_conf(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_set_qos(), ast_sched_runq(), ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_gateway(), capability, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, default_jbconf, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, dtmfmode, mgcp_gateway::endpoints, errno, format, gatelock, gateways, global_jbconf, hp, io, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcpsock_read_id, monitor_thread, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, netlock, mgcp_gateway::next, mgcp_endpoint::next, ast_variable::next, ourhost, ourport, prune_gateways(), qos, transmit_audit_endpoint(), and ast_variable::value.

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

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

Definition at line 2044 of file chan_mgcp.c.

References init_req(), and oseq.

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

02045 {
02046    memset(req, 0, sizeof(struct mgcp_request));
02047    oseq++;
02048    if (oseq > 999999999)
02049       oseq = 1;
02050    init_req(p, req, verb);
02051    return 0;
02052 }

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

Definition at line 528 of file chan_mgcp.c.

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

Referenced by find_and_retrans().

00529 {
00530    struct mgcp_endpoint *p = sub->parent;
00531    int res;
00532    if (mgcpdebug) {
00533       ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00534    }
00535    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00536    if (res > 0)
00537       res = 0;
00538    return res;
00539 }

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

Definition at line 2037 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_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().

02038 {
02039    memset(resp, 0, sizeof(*resp));
02040    init_resp(resp, msg, req, msgrest);
02041    return 0;
02042 }

static int restart_monitor ( void   )  [static]

Definition at line 3498 of file chan_mgcp.c.

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

03499 {
03500    /* If we're supposed to be stopped -- stay stopped */
03501    if (monitor_thread == AST_PTHREADT_STOP)
03502       return 0;
03503    if (ast_mutex_lock(&monlock)) {
03504       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03505       return -1;
03506    }
03507    if (monitor_thread == pthread_self()) {
03508       ast_mutex_unlock(&monlock);
03509       ast_log(LOG_WARNING, "Cannot kill myself\n");
03510       return -1;
03511    }
03512    if (monitor_thread != AST_PTHREADT_NULL) {
03513       /* Wake up the thread */
03514       pthread_kill(monitor_thread, SIGURG);
03515    } else {
03516       /* Start a new monitor */
03517       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03518          ast_mutex_unlock(&monlock);
03519          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03520          return -1;
03521       }
03522    }
03523    ast_mutex_unlock(&monlock);
03524    return 0;
03525 }

static int retrans_pkt ( const void *  data  )  [static]

Definition at line 631 of file chan_mgcp.c.

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

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

00632 {
00633    struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00634    struct mgcp_message *cur, *exq = NULL, *w, *prev;
00635    int res = 0;
00636 
00637    /* find out expired msgs */
00638    ast_mutex_lock(&gw->msgs_lock);
00639 
00640    prev = NULL, cur = gw->msgs;
00641    while (cur) {
00642       if (cur->retrans < MAX_RETRANS) {
00643          cur->retrans++;
00644          if (mgcpdebug) {
00645             ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
00646                cur->retrans, cur->seqno, gw->name);
00647          }
00648          __mgcp_xmit(gw, cur->buf, cur->len);
00649 
00650          prev = cur;
00651          cur = cur->next;
00652       } else {
00653          if (prev)
00654             prev->next = cur->next;
00655          else
00656             gw->msgs = cur->next;
00657 
00658          ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00659             cur->seqno, gw->name);
00660 
00661          w = cur;
00662          cur = cur->next;
00663 
00664          if (exq) {
00665             w->next = exq;
00666          } else {
00667             w->next = NULL;
00668          }
00669          exq = w;
00670       }
00671    }
00672 
00673    if (!gw->msgs) {
00674       gw->retransid = -1;
00675       res = 0;
00676    } else {
00677       res = 1;
00678    }
00679    ast_mutex_unlock(&gw->msgs_lock);
00680 
00681    while (exq) {
00682       cur = exq;
00683       /* time-out transaction */
00684       handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
00685       exq = exq->next;
00686       ast_free(cur);
00687    }
00688 
00689    return res;
00690 }

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1591 of file chan_mgcp.c.

Referenced by process_sdp().

01592 {
01593    *iterator = 0;
01594 }

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

Definition at line 758 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_malloc, 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, mgcp_request::len, LOG_WARNING, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcpdebug, mgcp_request::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.

Referenced by transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_modify_request(), transmit_notify_custom(), 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(), and transmit_state_notify().

00760 {
00761    int res = 0;
00762    struct mgcp_request **queue, *q, *r, *t;
00763    ast_mutex_t *l;
00764 
00765    ast_debug(1, "Slow sequence is %d\n", p->slowsequence);
00766    if (p->slowsequence) {
00767       queue = &p->cmd_queue;
00768       l = &p->cmd_queue_lock;
00769       ast_mutex_lock(l);
00770    } else {
00771       switch (req->cmd) {
00772       case MGCP_CMD_DLCX:
00773          queue = &sub->cx_queue;
00774          l = &sub->cx_queue_lock;
00775          ast_mutex_lock(l);
00776          q = sub->cx_queue;
00777          /* delete pending cx cmds */
00778          while (q) {
00779             r = q->next;
00780             ast_free(q);
00781             q = r;
00782          }
00783          *queue = NULL;
00784          break;
00785 
00786       case MGCP_CMD_CRCX:
00787       case MGCP_CMD_MDCX:
00788          queue = &sub->cx_queue;
00789          l = &sub->cx_queue_lock;
00790          ast_mutex_lock(l);
00791          break;
00792 
00793       case MGCP_CMD_RQNT:
00794          queue = &p->rqnt_queue;
00795          l = &p->rqnt_queue_lock;
00796          ast_mutex_lock(l);
00797          break;
00798 
00799       default:
00800          queue = &p->cmd_queue;
00801          l = &p->cmd_queue_lock;
00802          ast_mutex_lock(l);
00803          break;
00804       }
00805    }
00806 
00807    r = ast_malloc(sizeof(*r));
00808    if (!r) {
00809       ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00810       ast_mutex_unlock(l);
00811       return -1;
00812    }
00813    memcpy(r, req, sizeof(*r));
00814 
00815    if (!(*queue)) {
00816       if (mgcpdebug) {
00817          ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
00818             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00819       }
00820 
00821       res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00822    } else {
00823       if (mgcpdebug) {
00824          ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
00825             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00826       }
00827    }
00828 
00829    /* XXX find tail. We could also keep tail in the data struct for faster access */
00830    for (t = *queue; t && t->next; t = t->next);
00831 
00832    r->next = NULL;
00833    if (t)
00834       t->next = r;
00835    else
00836       *queue = r;
00837 
00838    ast_mutex_unlock(l);
00839 
00840    return res;
00841 }

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

Definition at line 541 of file chan_mgcp.c.

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

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

00542 {
00543    struct mgcp_endpoint *p = sub->parent;
00544    int res;
00545    if (mgcpdebug) {
00546       ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00547    }
00548    res = __mgcp_xmit(p->parent, req->data, req->len);
00549    if (res > 0)
00550       res = 0;
00551    return res;
00552 }

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2639 of file chan_mgcp.c.

References ast_channel_set_fd(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_destroy(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_callback(), ast_rtp_set_data(), ast_rtp_setnat(), ast_rtp_setqos(), bindaddr, mgcp_subchannel::callid, io, mgcp_subchannel::lock, mgcp_subchannel::nat, mgcp_subchannel::owner, qos, mgcp_subchannel::rtp, transmit_connect_with_sdp(), and mgcp_subchannel::txident.

Referenced by handle_hd_hf(), handle_offhook_message(), handle_response(), handle_soft_key_event_message(), handle_stimulus_message(), HandleCallIncoming(), HandleCallOutgoing(), mgcp_answer(), mgcp_call(), mgcp_ss(), skinny_answer(), skinny_newcall(), and unistim_answer().

02640 {
02641    ast_mutex_lock(&sub->lock);
02642    /* check again to be on the safe side */
02643    if (sub->rtp) {
02644       ast_rtp_destroy(sub->rtp);
02645       sub->rtp = NULL;
02646    }
02647    /* Allocate the RTP now */
02648    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02649    if (sub->rtp && sub->owner)
02650       ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
02651    if (sub->rtp) {
02652       ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
02653       ast_rtp_setnat(sub->rtp, sub->nat);
02654    }
02655 #if 0
02656    ast_rtp_set_callback(p->rtp, rtpready);
02657    ast_rtp_set_data(p->rtp, p);
02658 #endif      
02659    /* Make a call*ID */
02660         snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02661    /* Transmit the connection create */
02662    transmit_connect_with_sdp(sub, NULL);
02663    ast_mutex_unlock(&sub->lock);
02664 }

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

Definition at line 2358 of file chan_mgcp.c.

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

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

02359 {
02360    struct mgcp_request resp;
02361    reqprep(&resp, p, "AUEP");
02362    /* removed unknown param VS */
02363    /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
02364    add_header(&resp, "F", "A");
02365    /* fill in new fields */
02366    resp.cmd = MGCP_CMD_AUEP;
02367    resp.trid = oseq;
02368    return send_request(p, NULL, &resp, oseq);  /* SC */
02369 }

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

Definition at line 2205 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype(), mgcp_endpoint::capability, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by start_rtp().

02206 {
02207    struct mgcp_request resp;
02208    char local[256];
02209    char tmp[80];
02210    int x;
02211    struct mgcp_endpoint *p = sub->parent;
02212 
02213    ast_copy_string(local, "p:20", sizeof(local));
02214    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02215       if (p->capability & x) {
02216          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02217          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02218       }
02219    }
02220    if (mgcpdebug) {
02221       ast_verb(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02222          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02223    }
02224    reqprep(&resp, p, "CRCX");
02225    add_header(&resp, "C", sub->callid);
02226    add_header(&resp, "L", local);
02227    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02228    /* X header should not be sent. kept for compatibility */
02229    add_header(&resp, "X", sub->txident);
02230    /*add_header(&resp, "S", "");*/
02231    add_sdp(&resp, sub, rtp);
02232    /* fill in new fields */
02233    resp.cmd = MGCP_CMD_CRCX;
02234    resp.trid = oseq;
02235    return send_request(p, sub, &resp, oseq);  /* SC */
02236 }

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

Definition at line 2371 of file chan_mgcp.c.

References add_header(), ast_verb, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_DLCX, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_endpoint::sub, mgcp_request::trid, and mgcp_subchannel::txident.

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

02372 {
02373    struct mgcp_endpoint *p = sub->parent;
02374    struct mgcp_request resp;
02375 
02376    if (mgcpdebug) {
02377       ast_verb(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02378          sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02379    }
02380    reqprep(&resp, p, "DLCX");
02381    /* check if call id is avail */
02382    if (sub->callid[0])
02383       add_header(&resp, "C", sub->callid);
02384    /* X header should not be sent. kept for compatibility */
02385    add_header(&resp, "X", sub->txident);
02386    /* check if cxident is avail */
02387    if (sub->cxident[0])
02388       add_header(&resp, "I", sub->cxident);
02389    /* fill in new fields */
02390    resp.cmd = MGCP_CMD_DLCX;
02391    resp.trid = oseq;
02392    return send_request(p, sub, &resp, oseq);  /* SC */
02393 }

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

Definition at line 2395 of file chan_mgcp.c.

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

Referenced by handle_response().

02396 {
02397    struct mgcp_request resp;
02398 
02399    if (mgcpdebug) {
02400       ast_verb(3, "Delete connection %s %s@%s on callid: %s\n",
02401          cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02402    }
02403    reqprep(&resp, p, "DLCX");
02404    /* check if call id is avail */
02405    if (callid && *callid)
02406       add_header(&resp, "C", callid);
02407    /* check if cxident is avail */
02408    if (cxident && *cxident)
02409       add_header(&resp, "I", cxident);
02410    /* fill in new fields */
02411    resp.cmd = MGCP_CMD_DLCX;
02412    resp.trid = oseq;
02413    return send_request(p, p->sub, &resp, oseq);
02414 }

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2313 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_endpoint::sub, mgcp_request::trid, and mgcp_subchannel::txident.

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

02314 {
02315    struct mgcp_request resp;
02316    struct mgcp_endpoint *p = sub->parent;
02317 
02318    if (ast_strlen_zero(sub->cxident)) {
02319       /* We don't have a CXident yet, store the destination and
02320          wait a bit */
02321       return 0;
02322    }
02323    if (mgcpdebug) {
02324       ast_verb(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02325          p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02326    }
02327    reqprep(&resp, p, "MDCX");
02328    add_header(&resp, "C", sub->callid);
02329    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02330    /* X header should not be sent. kept for compatibility */
02331    add_header(&resp, "X", sub->txident);
02332    add_header(&resp, "I", sub->cxident);
02333    switch (sub->parent->hookstate) {
02334    case MGCP_ONHOOK:
02335       add_header(&resp, "R", "L/hd(N)");
02336       break;
02337    case MGCP_OFFHOOK:
02338       add_header_offhook(sub, &resp);
02339       break;
02340    }
02341    /* fill in new fields */
02342    resp.cmd = MGCP_CMD_MDCX;
02343    resp.trid = oseq;
02344    return send_request(p, sub, &resp, oseq); /* SC */
02345 }

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

Definition at line 2169 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_get_peer(), ast_rtp_lookup_mime_subtype(), ast_strlen_zero(), mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::parent, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.

Referenced by handle_response(), and mgcp_set_rtp_peer().

02170 {
02171    struct mgcp_request resp;
02172    char local[256];
02173    char tmp[80];
02174    int x;
02175    struct mgcp_endpoint *p = sub->parent;
02176 
02177    if (ast_strlen_zero(sub->cxident) && rtp) {
02178       /* We don't have a CXident yet, store the destination and
02179          wait a bit */
02180       ast_rtp_get_peer(rtp, &sub->tmpdest);
02181       return 0;
02182    }
02183    ast_copy_string(local, "p:20", sizeof(local));
02184    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02185       if (p->capability & x) {
02186          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
02187          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02188       }
02189    }
02190    reqprep(&resp, p, "MDCX");
02191    add_header(&resp, "C", sub->callid);
02192    add_header(&resp, "L", local);
02193    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02194    /* X header should not be sent. kept for compatibility */
02195    add_header(&resp, "X", sub->txident);
02196    add_header(&resp, "I", sub->cxident);
02197    /*add_header(&resp, "S", "");*/
02198    add_sdp(&resp, sub, rtp);
02199    /* fill in new fields */
02200    resp.cmd = MGCP_CMD_MDCX;
02201    resp.trid = oseq;
02202    return send_request(p, sub, &resp, oseq); /* SC */
02203 }

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

Definition at line 2238 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), mgcp_endpoint::sub, and mgcp_request::trid.

Referenced by do_monitor(), handle_hd_hf(), handle_request(), handle_response(), mgcp_answer(), mgcp_hangup(), mgcp_indicate(), mgcp_request(), mgcp_senddigit_end(), and mgcp_ss().

02239 {
02240    struct mgcp_request resp;
02241    struct mgcp_endpoint *p = sub->parent;
02242 
02243    if (mgcpdebug) {
02244       ast_verb(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
02245          tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02246    }
02247    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02248    reqprep(&resp, p, "RQNT");
02249    add_header(&resp, "X", p->rqnt_ident); /* SC */
02250    switch (p->hookstate) {
02251    case MGCP_ONHOOK:
02252       add_header(&resp, "R", "L/hd(N)");
02253       break;
02254    case MGCP_OFFHOOK:
02255       add_header_offhook(sub, &resp);
02256       break;
02257    }
02258    if (!ast_strlen_zero(tone)) {
02259       add_header(&resp, "S", tone);
02260    }
02261    /* fill in new fields */
02262    resp.cmd = MGCP_CMD_RQNT;
02263    resp.trid = oseq;
02264    return send_request(p, NULL, &resp, oseq); /* SC */
02265 }

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

Definition at line 2267 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_verb, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::lastcallerid, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), mgcp_endpoint::sub, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and mgcp_request::trid.

Referenced by mgcp_call(), and mgcp_hangup().

02268 {
02269    struct mgcp_request resp;
02270    char tone2[256];
02271    char *l, *n;
02272    struct timeval t = ast_tvnow();
02273    struct ast_tm tm;
02274    struct mgcp_endpoint *p = sub->parent;
02275    
02276    ast_localtime(&t, &tm, NULL);
02277    n = callername;
02278    l = callernum;
02279    if (!n)
02280       n = "";
02281    if (!l)
02282       l = "";
02283 
02284    /* Keep track of last callerid for blacklist and callreturn */
02285    ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02286 
02287    snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
02288       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02289    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02290    reqprep(&resp, p, "RQNT");
02291    add_header(&resp, "X", p->rqnt_ident); /* SC */
02292    switch (p->hookstate) {
02293    case MGCP_ONHOOK:
02294       add_header(&resp, "R", "L/hd(N)");
02295       break;
02296    case MGCP_OFFHOOK:
02297       add_header_offhook(sub, &resp);
02298       break;
02299    }
02300    if (!ast_strlen_zero(tone2)) {
02301       add_header(&resp, "S", tone2);
02302    }
02303    if (mgcpdebug) {
02304       ast_verb(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
02305          tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02306    }
02307    /* fill in new fields */
02308    resp.cmd = MGCP_CMD_RQNT;
02309    resp.trid = oseq;
02310    return send_request(p, NULL, &resp, oseq);  /* SC */
02311 }

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

Definition at line 2054 of file chan_mgcp.c.

References ast_calloc, mgcp_request::data, mgcp_request::identifier, mgcp_request::len, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_gateway::responses, respprep(), send_response(), and mgcp_endpoint::sub.

Referenced by handle_button_template_req_message(), handle_incoming(), handle_invite_replaces(), handle_keep_alive_message(), handle_line_state_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_request(), handle_request_bye(), handle_request_cancel(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), handle_server_request_message(), handle_skinny_reset(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), handle_version_req_message(), local_attended_transfer(), receive_message(), register_verify(), send_provisional_keepalive_full(), sip_indicate(), sip_park_thread(), sip_sendhtml(), skinny_set_rtp_peer(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_callstateonly(), transmit_cfwdstate(), transmit_closereceivechannel(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_provisional_response(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stopmediatransmission(), and transmit_tone().

02055 {
02056    struct mgcp_request resp;
02057    struct mgcp_endpoint *p = sub->parent;
02058    struct mgcp_response *mgr;
02059 
02060    respprep(&resp, p, msg, req, msgrest);
02061    mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1);
02062    if (mgr) {
02063       /* Store MGCP response in case we have to retransmit */
02064       sscanf(req->identifier, "%30d", &mgr->seqno);
02065       time(&mgr->whensent);
02066       mgr->len = resp.len;
02067       memcpy(mgr->buf, resp.data, resp.len);
02068       mgr->buf[resp.len] = '\0';
02069       mgr->next = p->parent->responses;
02070       p->parent->responses = mgr;
02071    }
02072    return send_response(sub, &resp);
02073 }

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

Definition at line 487 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, 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().

00488 {
00489    struct mgcp_endpoint *p = sub->parent;
00490    if (p->sub == sub) {
00491       ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00492       return -1;
00493    }
00494    ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00495 
00496    sub->owner = NULL;
00497    if (!ast_strlen_zero(sub->cxident)) {
00498       transmit_connection_del(sub);
00499    }
00500    sub->cxident[0] = '\0';
00501    sub->callid[0] = '\0';
00502    sub->cxmode = MGCP_CX_INACTIVE;
00503    sub->outgoing = 0;
00504    sub->alreadygone = 0;
00505    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00506    if (sub->rtp) {
00507       ast_rtp_destroy(sub->rtp);
00508       sub->rtp = NULL;
00509    }
00510    dump_cmd_queues(NULL, sub); /* SC */
00511    return 0;
00512 }

static int unload_module ( void   )  [static]

Definition at line 4352 of file chan_mgcp.c.

References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), cli_mgcp, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, LOG_WARNING, mgcp_reload(), mgcp_reload_lock, mgcp_reloading, mgcp_rtp, mgcp_tech, mgcpsock, monitor_thread, monlock, mgcp_endpoint::next, mgcp_gateway::next, prune_gateways(), and sched_context_destroy().

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 4419 of file chan_mgcp.c.

struct in_addr __ourip [static]

Definition at line 218 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 183 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 189 of file chan_mgcp.c.

int amaflags = 0 [static]

Definition at line 187 of file chan_mgcp.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4419 of file chan_mgcp.c.

struct sockaddr_in bindaddr [static]

Definition at line 405 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 168 of file chan_mgcp.c.

Referenced by build_gateway().

int callwaiting = 0 [static]

Definition at line 166 of file chan_mgcp.c.

Referenced by build_gateway().

int cancallforward = 0 [static]

Definition at line 177 of file chan_mgcp.c.

Referenced by build_gateway().

int canreinvite = CANREINVITE [static]

Definition at line 181 of file chan_mgcp.c.

Referenced by build_gateway().

int capability = AST_FORMAT_ULAW [static]

Definition at line 214 of file chan_mgcp.c.

Referenced by build_gateway(), build_setup(), iax2_call(), mgcp_new(), mgcp_request(), parse_setup(), process_sdp(), reload_config(), set_config(), and set_local_capabilities().

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 149 of file chan_mgcp.c.

Referenced by __oh323_new(), build_gateway(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_pvt_defaults(), sip_call(), sla_ring_station(), and store_callerid().

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 148 of file chan_mgcp.c.

Referenced by __oh323_new(), build_gateway(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_pvt_defaults(), sla_ring_station(), socket_process(), and store_callerid().

struct ast_cli_entry cli_mgcp[] [static]

Definition at line 1196 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_mgcp_set_debug_deprecated = { .handler = handle_mgcp_set_debug_deprecated , .summary = "Enable/Disable MGCP debugging" ,__VA_ARGS__ } [static]

Definition at line 1195 of file chan_mgcp.c.

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

Definition at line 101 of file chan_mgcp.c.

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

Definition at line 143 of file chan_mgcp.c.

unsigned int cos

Definition at line 160 of file chan_mgcp.c.

unsigned int cos_audio

Definition at line 161 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 154 of file chan_mgcp.c.

Referenced by build_gateway().

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 155 of file chan_mgcp.c.

Referenced by build_gateway().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 90 of file chan_mgcp.c.

int dtmfmode = 0 [static]

Definition at line 151 of file chan_mgcp.c.

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

int firstdigittimeout = 16000 [static]

Wait up to 16 seconds for first digit (FXO logic)

Definition at line 194 of file chan_mgcp.c.

ast_mutex_t gatelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

gatelock: mutex for gateway/endpoint lists

Definition at line 401 of file chan_mgcp.c.

Referenced by find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), reload_config(), and unload_module().

struct mgcp_gateway * gateways [static]

Referenced by build_gateway(), do_monitor(), find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), reload_config(), and unload_module().

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic)

Definition at line 197 of file chan_mgcp.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 98 of file chan_mgcp.c.

int immediate = 0 [static]

Definition at line 164 of file chan_mgcp.c.

Referenced by build_gateway().

struct io_context* io [static]

Definition at line 224 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 145 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 185 of file chan_mgcp.c.

Referenced by action_mailboxcount(), action_mailboxstatus(), add_peer_mailboxes(), add_peer_mwi_subs(), append_mailbox_mapping(), ast_event_hash_mwi(), build_gateway(), build_peer(), chanspy_exec(), clear_peer_mailboxes(), destroy_mailbox(), disa_exec(), extenspy_exec(), get_cached_mwi(), has_voicemail(), notify_message(), peer_mailboxes_to_str(), realtime_directory(), unistim_send_mwi_to_peer(), and update_registry().

int matchdigittimeout = 3000 [static]

How long to wait for an extra digit, if there is an ambiguous match

Definition at line 200 of file chan_mgcp.c.

char* mgcp_cxmodes[] [static]

}

Definition at line 123 of file chan_mgcp.c.

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

ast_mutex_t mgcp_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 397 of file chan_mgcp.c.

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

int mgcp_reloading = 0 [static]

Definition at line 398 of file chan_mgcp.c.

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

struct ast_rtp_protocol mgcp_rtp [static]

Initial value:

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

Definition at line 4000 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 435 of file chan_mgcp.c.

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

int mgcpdebug = 0 [static]

Definition at line 221 of file chan_mgcp.c.

Referenced by add_sdp(), handle_mgcp_audit_endpoint(), handle_mgcp_set_debug(), handle_mgcp_set_debug_deprecated(), mgcp_call(), mgcp_hangup(), mgcp_indicate(), parse(), process_sdp(), retrans_pkt(), and send_request().

int mgcpsock = -1 [static]

Definition at line 403 of file chan_mgcp.c.

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

int* mgcpsock_read_id = NULL [static]

Definition at line 3410 of file chan_mgcp.c.

Referenced by reload_config().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 210 of file chan_mgcp.c.

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 206 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

Definition at line 146 of file chan_mgcp.c.

Referenced by ast_do_masquerade(), begin_dial_channel(), build_gateway(), dial_exec_full(), findmeexec(), func_channel_write(), gtalk_new(), jingle_new(), local_call(), moh_handle_digit(), monitor_dial(), and set_moh_exec().

int nat = 0 [static]

Definition at line 152 of file chan_mgcp.c.

Referenced by build_gateway().

ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

Definition at line 204 of file chan_mgcp.c.

Referenced by do_monitor(), handle_request_do(), reload_config(), and unload_module().

int nonCodecCapability = AST_RTP_DTMF [static]

Definition at line 215 of file chan_mgcp.c.

Referenced by process_sdp().

unsigned int oseq [static]

Definition at line 191 of file chan_mgcp.c.

Referenced by init_req(), reqprep(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

char ourhost[MAXHOSTNAMELEN] [static]

Definition at line 217 of file chan_mgcp.c.

Referenced by ast_find_ourip(), and reload_config().

int ourport [static]

Definition at line 219 of file chan_mgcp.c.

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

char parkinglot[AST_MAX_CONTEXT] [static]

Definition at line 147 of file chan_mgcp.c.

struct { ... } qos [static]

struct sched_context* sched [static]

Definition at line 223 of file chan_mgcp.c.

int singlepath = 0 [static]

Definition at line 179 of file chan_mgcp.c.

Referenced by build_gateway().

int slowsequence = 0 [static]

Definition at line 170 of file chan_mgcp.c.

Referenced by build_gateway().

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

Definition at line 100 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 172 of file chan_mgcp.c.

Referenced by build_gateway().

unsigned int tos

Definition at line 158 of file chan_mgcp.c.

unsigned int tos_audio

Definition at line 159 of file chan_mgcp.c.

int transfer = 0 [static]

This is for flashhook transfers

Definition at line 175 of file chan_mgcp.c.

Referenced by build_gateway(), and leave_voicemail().


Generated on Wed Aug 18 22:34:11 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7