Wed Apr 6 11:29:57 2011

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_engine.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"
#include "asterisk/chanvars.h"
#include "asterisk/pktccops.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 DEFAULT_EXPIRY   120
#define DEFAULT_MGCP_CA_PORT   2727
#define DEFAULT_MGCP_GW_PORT   2427
#define DEFAULT_RETRANS   1000
#define DIRECTMEDIA   1
#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, char *def)
static int __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen)
static int add_header (struct mgcp_request *req, const char *var, const char *value)
static void add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
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_instance *rtp)
static struct ast_variableadd_var (const char *buf, struct ast_variable *list)
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 struct ast_variablecopy_vars (struct ast_variable *src)
 duplicate a list of channel variables,
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_gatewayfind_realtime_gw (char *name, char *at, struct sockaddr_in *sin)
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_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_alloc_pktcgate (struct mgcp_subchannel *sub)
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 format_t mgcp_get_codec (struct ast_channel *chan)
static enum ast_rtp_glue_result mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
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, const char *linkedid)
static int mgcp_pktcgate_open (struct cops_gate *gate)
static int mgcp_pktcgate_remove (struct cops_gate *gate)
static int mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno)
static int mgcp_prune_realtime_gateway (struct mgcp_gateway *g)
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, format_t format, const struct ast_channel *requestor, 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_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t 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 (struct mgcp_subchannel *sub)
static int transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp_instance *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_instance *rtp, format_t 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_LOAD_ORDER , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", }
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 format_t 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 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 directmedia = DIRECTMEDIA
static int dtmfmode = 0
static int firstdigittimeout = 16000
static ast_mutex_t gatelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, 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 hangupongateremove = 0
static int immediate = 0
static struct io_contextio
static char language [MAX_LANGUAGE] = ""
static char mailbox [AST_MAX_EXTENSION]
static int matchdigittimeout = 3000
static const char *const mgcp_cxmodes []
static ast_mutex_t mgcp_reload_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static int mgcp_reloading = 0
static struct ast_rtp_glue mgcp_rtp_glue
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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static int ncs = 0
static ast_mutex_t netlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, 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]
static int pktcgatealloc = 0
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 DEFAULT_EXPIRY   120

Definition at line 88 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 115 of file chan_mgcp.c.

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 114 of file chan_mgcp.c.

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 117 of file chan_mgcp.c.

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

#define DIRECTMEDIA   1

Definition at line 90 of file chan_mgcp.c.

Referenced by build_gateway().

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 93 of file chan_mgcp.c.

#define MAX_EXPIRY   3600

Definition at line 89 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 118 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 281 of file chan_mgcp.c.

Referenced by mgcp_prune_realtime_gateway(), reload_config(), and unistim_info().

#define MGCP_CX_CONF   3

Definition at line 124 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 125 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 127 of file chan_mgcp.c.

Referenced by mgcp_hangup(), and unalloc_sub().

#define MGCP_CX_MUTE   4

Definition at line 126 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

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

#define MGCP_CX_SENDRECV   2

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

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

#define MGCP_DTMF_INBAND   (1 << 1)

Definition at line 111 of file chan_mgcp.c.

Referenced by add_header_offhook(), 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 110 of file chan_mgcp.c.

Referenced by 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 240 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

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

#define MGCP_OFFHOOK   2

Definition at line 317 of file chan_mgcp.c.

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

#define MGCP_ONHOOK   1

Definition at line 316 of file chan_mgcp.c.

Referenced by do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_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 292 of file chan_mgcp.c.

Referenced by mgcp_hangup().

#define MGCPDUMPER

Definition at line 87 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 271 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 284 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 283 of file chan_mgcp.c.

#define TYPE_LINE   2

Definition at line 320 of file chan_mgcp.c.

Referenced by config_line(), config_parse_variables(), do_monitor(), and mgcp_call().

#define TYPE_TRUNK   1

Definition at line 319 of file chan_mgcp.c.


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

00138      {
00139    MGCP_CMD_EPCF,
00140    MGCP_CMD_CRCX,
00141    MGCP_CMD_MDCX,
00142    MGCP_CMD_DLCX,
00143    MGCP_CMD_RQNT,
00144    MGCP_CMD_NTFY,
00145    MGCP_CMD_AUEP,
00146    MGCP_CMD_AUCX,
00147    MGCP_CMD_RSIP
00148 };


Function Documentation

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

Definition at line 1609 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(), handle_incoming(), handle_request_subscribe(), handle_response_register(), and parse_register_contact().

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

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

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

00543 {
00544    int res;
00545    if (gw->addr.sin_addr.s_addr)
00546       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
00547    else
00548       res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
00549    if (res != len) {
00550       ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
00551    }
00552    return res;
00553 }

static void __reg_module ( void   )  [static]

Definition at line 4919 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

Definition at line 4919 of file chan_mgcp.c.

static int acf_channel_read ( struct ast_channel chan,
const char *  funcname,
char *  preparse,
char *  buf,
size_t  buflen 
) [static]

Definition at line 4440 of file chan_mgcp.c.

References ast_log(), LOG_ERROR, mgcp_tech, mgcp_endpoint::ncs, mgcp_subchannel::parent, ast_channel::tech, and ast_channel::tech_pvt.

04441 {
04442    struct mgcp_subchannel *sub = chan->tech_pvt;
04443    int res = 0;
04444 
04445    /* Sanity check */
04446    if (!chan || chan->tech != &mgcp_tech) {
04447       ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
04448       return -1;
04449    }
04450 
04451    if (!strcasecmp(args, "ncs")) {
04452       snprintf(buf, buflen, "%s", sub->parent->ncs ?  "yes":"no");
04453    } else {
04454       res = -1;
04455    }
04456    return res;
04457 }

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

Definition at line 2038 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_cc_call_info_to_response(), add_digit(), add_diversion_header(), add_header_max_forwards(), add_header_offhook(), add_route(), add_rpid(), add_sdp(), add_supported_header(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), finalize_content(), initreqprep(), reqprep(), respprep(), transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_invite(), 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_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sip_etag(), transmit_response_with_unsupported(), transmit_state_notify(), and update_connectedline().

02039 {
02040    if (req->len >= sizeof(req->data) - 4) {
02041       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
02042       return -1;
02043    }
02044    if (req->lines) {
02045       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
02046       return -1;
02047    }
02048    req->header[req->headers] = req->data + req->len;
02049    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
02050    req->len += strlen(req->header[req->headers]);
02051    if (req->headers < MGCP_MAX_HEADERS) {
02052       req->headers++;
02053    } else {
02054       ast_log(LOG_WARNING, "Out of header space\n");
02055       return -1;
02056    }
02057    return 0;
02058 }

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

Definition at line 2592 of file chan_mgcp.c.

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

Referenced by transmit_notify_request(), and transmit_notify_request_with_callerid().

02593 {
02594    struct mgcp_endpoint *p = sub->parent;
02595    char tone_indicate_end = 0;
02596 
02597    /* We also should check the tone to indicate, because it have no sense
02598       to request notify D/[0-9#*] (dtmf keys) if we are sending congestion
02599       tone for example G/cg */
02600    if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
02601       tone_indicate_end = 1;
02602    }
02603 
02604    if (p && p->sub && p->sub->owner &&
02605          p->sub->owner->_state >= AST_STATE_RINGING &&
02606          (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) {
02607        add_header(resp, "R", "L/hu(N),L/hf(N)");
02608 
02609    } else if (!tone_indicate_end){
02610        add_header(resp, "R", (p->ncs ? "L/hu(N),L/hf(N),L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)"));
02611    } else {
02612       ast_debug(1, "We don't want more digits if we will end the call\n");
02613       add_header(resp, "R", "L/hu(N),L/hf(N)");
02614    }
02615 }

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

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

02061 {
02062    if (req->len >= sizeof(req->data) - 4) {
02063       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
02064       return -1;
02065    }
02066    if (!req->lines) {
02067       /* Add extra empty return */
02068       ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
02069       req->len += strlen(req->data + req->len);
02070    }
02071    req->line[req->lines] = req->data + req->len;
02072    snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
02073    req->len += strlen(req->line[req->lines]);
02074    if (req->lines < MGCP_MAX_LINES) {
02075       req->lines++;
02076    } else {
02077       ast_log(LOG_WARNING, "Out of line space\n");
02078       return -1;
02079    }
02080    return 0;
02081 }

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

Definition at line 2170 of file chan_mgcp.c.

References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, mgcp_endpoint::capability, len(), LOG_WARNING, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.

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

02171 {
02172    int len;
02173    int codec;
02174    char costr[80];
02175    struct sockaddr_in sin;
02176    struct ast_sockaddr sin_tmp;
02177    char v[256];
02178    char s[256];
02179    char o[256];
02180    char c[256];
02181    char t[256];
02182    char m[256] = "";
02183    char a[1024] = "";
02184    format_t x;
02185    struct sockaddr_in dest = { 0, };
02186    struct ast_sockaddr dest_tmp;
02187    struct mgcp_endpoint *p = sub->parent;
02188    /* XXX We break with the "recommendation" and send our IP, in order that our
02189           peer doesn't have to ast_gethostbyname() us XXX */
02190    len = 0;
02191    if (!sub->rtp) {
02192       ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
02193       return -1;
02194    }
02195    ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
02196    ast_sockaddr_to_sin(&sin_tmp, &sin);
02197    if (rtp) {
02198       ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
02199       ast_sockaddr_to_sin(&dest_tmp, &dest);
02200    } else {
02201       if (sub->tmpdest.sin_addr.s_addr) {
02202          dest.sin_addr = sub->tmpdest.sin_addr;
02203          dest.sin_port = sub->tmpdest.sin_port;
02204          /* Reset temporary destination */
02205          memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
02206       } else {
02207          dest.sin_addr = p->parent->ourip;
02208          dest.sin_port = sin.sin_port;
02209       }
02210    }
02211    ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
02212    ast_copy_string(v, "v=0\r\n", sizeof(v));
02213    snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
02214    ast_copy_string(s, "s=session\r\n", sizeof(s));
02215    snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
02216    ast_copy_string(t, "t=0 0\r\n", sizeof(t));
02217    snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
02218    for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02219       if (!(x & AST_FORMAT_AUDIO_MASK)) {
02220          /* Audio is now discontiguous */
02221          continue;
02222       }
02223       if (p->capability & x) {
02224          ast_debug(1, "Answering with capability %s\n", ast_getformatname(x));
02225          codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x);
02226          if (codec > -1) {
02227             snprintf(costr, sizeof(costr), " %d", codec);
02228             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02229             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0));
02230             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02231          }
02232       }
02233    }
02234    for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
02235       if (p->nonCodecCapability & x) {
02236          ast_debug(1, "Answering with non-codec capability %d\n", (int) x);
02237          codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x);
02238          if (codec > -1) {
02239             snprintf(costr, sizeof(costr), " %d", codec);
02240             strncat(m, costr, sizeof(m) - strlen(m) - 1);
02241             snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0));
02242             strncat(a, costr, sizeof(a) - strlen(a) - 1);
02243             if (x == AST_RTP_DTMF) {
02244                /* Indicate we support DTMF...  Not sure about 16,
02245                   but MSN supports it so dang it, we will too... */
02246                snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
02247                strncat(a, costr, sizeof(a) - strlen(a) - 1);
02248             }
02249          }
02250       }
02251    }
02252    strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
02253    len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
02254    snprintf(costr, sizeof(costr), "%d", len);
02255    add_line(resp, v);
02256    add_line(resp, o);
02257    add_line(resp, s);
02258    add_line(resp, c);
02259    add_line(resp, t);
02260    add_line(resp, m);
02261    add_line(resp, a);
02262    return 0;
02263 }

static struct ast_variable * add_var ( const char *  buf,
struct ast_variable list 
) [static]

Definition at line 4570 of file chan_mgcp.c.

References ast_strdupa, ast_variable_new(), and ast_variable::next.

Referenced by build_peer(), and config_parse_variables().

04571 {
04572    struct ast_variable *tmpvar = NULL;
04573    char *varname = ast_strdupa(buf), *varval = NULL;
04574 
04575    if ((varval = strchr(varname, '='))) {
04576       *varval++ = '\0';
04577       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
04578          tmpvar->next = list;
04579          list = tmpvar;
04580       }
04581    }
04582    return list;
04583 }

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

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

03194 {
03195    /* *************************
03196     * I hope this works.
03197     * Copied out of chan_zap
03198     * Cross your fingers
03199     * *************************/
03200 
03201    /* In order to transfer, we need at least one of the channels to
03202       actually be in a call bridge.  We can't conference two applications
03203       together (but then, why would we want to?) */
03204    if (ast_bridged_channel(p->sub->owner)) {
03205       /* The three-way person we're about to transfer to could still be in MOH, so
03206          stop if now if appropriate */
03207       if (ast_bridged_channel(p->sub->next->owner))
03208          ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
03209       if (p->sub->owner->_state == AST_STATE_RINGING) {
03210          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
03211       }
03212       if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
03213          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03214             ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
03215          return -1;
03216       }
03217       /* Orphan the channel */
03218       unalloc_sub(p->sub->next);
03219    } else if (ast_bridged_channel(p->sub->next->owner)) {
03220       if (p->sub->owner->_state == AST_STATE_RINGING) {
03221          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
03222       }
03223       ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
03224       if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
03225          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03226             ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
03227          return -1;
03228       }
03229       /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
03230       ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03231       p->sub = p->sub->next;
03232       unalloc_sub(p->sub->next);
03233       /* Tell the caller not to hangup */
03234       return 1;
03235    } else {
03236       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03237          p->sub->owner->name, p->sub->next->owner->name);
03238       p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03239       if (p->sub->next->owner) {
03240          p->sub->next->alreadygone = 1;
03241          mgcp_queue_hangup(p->sub->next);
03242       }
03243    }
03244    return 0;
03245 }

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

References mgcp_gateway::delme, DIRECTMEDIA, directmedia, gateways, mgcp_gateway::name, and mgcp_gateway::next.

03956 {
03957    struct mgcp_gateway *gw;
03958    struct mgcp_endpoint *e;
03959    struct mgcp_subchannel *sub;
03960    struct ast_variable *chanvars = NULL;
03961 
03962    /*char txident[80];*/
03963    int i=0, y=0;
03964    int gw_reload = 0;
03965    int ep_reload = 0;
03966    directmedia = DIRECTMEDIA;
03967 
03968    /* locate existing gateway */
03969    for (gw = gateways; gw; gw = gw->next) {
03970       if (!strcasecmp(cat, gw->name)) {
03971          /* gateway already exists */
03972          gw->delme = 0;
03973          gw_reload = 1;
03974          break;
03975       }
03976    }
03977 
03978    if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) {
03979       return NULL;
03980    }
03981 
03982    if (!gw_reload) {
03983       gw->expire = -1;
03984       gw->realtime = 0;
03985       gw->retransid = -1;
03986       ast_mutex_init(&gw->msgs_lock);
03987       ast_copy_string(gw->name, cat, sizeof(gw->name));
03988       /* check if the name is numeric ip */
03989       if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
03990          gw->isnamedottedip = 1;
03991    }
03992    for (; v; v = v->next) {
03993       if (!strcasecmp(v->name, "host")) {
03994          if (!strcasecmp(v->value, "dynamic")) {
03995             /* They'll register with us */
03996             gw->dynamic = 1;
03997             memset(&gw->addr.sin_addr, 0, 4);
03998             if (gw->addr.sin_port) {
03999                /* If we've already got a port, make it the default rather than absolute */
04000                gw->defaddr.sin_port = gw->addr.sin_port;
04001                gw->addr.sin_port = 0;
04002             }
04003          } else {
04004             /* Non-dynamic.  Make sure we become that way if we're not */
04005             AST_SCHED_DEL(sched, gw->expire);
04006             gw->dynamic = 0;
04007             {
04008                struct ast_sockaddr tmp;
04009 
04010                ast_sockaddr_from_sin(&tmp, &gw->addr);
04011                if (ast_get_ip(&tmp, v->value)) {
04012                   if (!gw_reload) {
04013                      ast_mutex_destroy(&gw->msgs_lock);
04014                      ast_free(gw);
04015                   }
04016                   return NULL;
04017                }
04018                ast_sockaddr_to_sin(&tmp, &gw->addr);
04019             }
04020          }
04021       } else if (!strcasecmp(v->name, "defaultip")) {
04022          struct ast_sockaddr tmp;
04023 
04024          ast_sockaddr_from_sin(&tmp, &gw->defaddr);
04025          if (ast_get_ip(&tmp, v->value)) {
04026             if (!gw_reload) {
04027                ast_mutex_destroy(&gw->msgs_lock);
04028                ast_free(gw);
04029             }
04030             return NULL;
04031          }
04032          ast_sockaddr_to_sin(&tmp, &gw->defaddr);
04033       } else if (!strcasecmp(v->name, "permit") ||
04034          !strcasecmp(v->name, "deny")) {
04035          gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
04036       } else if (!strcasecmp(v->name, "port")) {
04037          gw->addr.sin_port = htons(atoi(v->value));
04038       } else if (!strcasecmp(v->name, "context")) {
04039          ast_copy_string(context, v->value, sizeof(context));
04040       } else if (!strcasecmp(v->name, "dtmfmode")) {
04041          if (!strcasecmp(v->value, "inband"))
04042             dtmfmode = MGCP_DTMF_INBAND;
04043          else if (!strcasecmp(v->value, "rfc2833"))
04044             dtmfmode = MGCP_DTMF_RFC2833;
04045          else if (!strcasecmp(v->value, "hybrid"))
04046             dtmfmode = MGCP_DTMF_HYBRID;
04047          else if (!strcasecmp(v->value, "none"))
04048             dtmfmode = 0;
04049          else
04050             ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
04051       } else if (!strcasecmp(v->name, "nat")) {
04052          nat = ast_true(v->value);
04053       } else if (!strcasecmp(v->name, "ncs")) {
04054          ncs = ast_true(v->value);
04055       } else if (!strcasecmp(v->name, "hangupongateremove")) {
04056          hangupongateremove = ast_true(v->value);
04057       } else if (!strcasecmp(v->name, "pktcgatealloc")) {
04058          pktcgatealloc = ast_true(v->value);
04059       } else if (!strcasecmp(v->name, "callerid")) {
04060          if (!strcasecmp(v->value, "asreceived")) {
04061             cid_num[0] = '\0';
04062             cid_name[0] = '\0';
04063          } else {
04064             ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
04065          }
04066       } else if (!strcasecmp(v->name, "language")) {
04067          ast_copy_string(language, v->value, sizeof(language));
04068       } else if (!strcasecmp(v->name, "accountcode")) {
04069          ast_copy_string(accountcode, v->value, sizeof(accountcode));
04070       } else if (!strcasecmp(v->name, "amaflags")) {
04071          y = ast_cdr_amaflags2int(v->value);
04072          if (y < 0) {
04073             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
04074          } else {
04075             amaflags = y;
04076          }
04077       } else if (!strcasecmp(v->name, "setvar")) {
04078          chanvars = add_var(v->value, chanvars);
04079       } else if (!strcasecmp(v->name, "clearvars")) {
04080          if (chanvars) {
04081             ast_variables_destroy(chanvars);
04082             chanvars = NULL;
04083          }
04084       } else if (!strcasecmp(v->name, "musiconhold")) {
04085          ast_copy_string(musicclass, v->value, sizeof(musicclass));
04086       } else if (!strcasecmp(v->name, "parkinglot")) {
04087          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
04088       } else if (!strcasecmp(v->name, "callgroup")) {
04089          cur_callergroup = ast_get_group(v->value);
04090       } else if (!strcasecmp(v->name, "pickupgroup")) {
04091          cur_pickupgroup = ast_get_group(v->value);
04092       } else if (!strcasecmp(v->name, "immediate")) {
04093          immediate = ast_true(v->value);
04094       } else if (!strcasecmp(v->name, "cancallforward")) {
04095          cancallforward = ast_true(v->value);
04096       } else if (!strcasecmp(v->name, "singlepath")) {
04097          singlepath = ast_true(v->value);
04098       } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
04099          directmedia = ast_true(v->value);
04100       } else if (!strcasecmp(v->name, "mailbox")) {
04101          ast_copy_string(mailbox, v->value, sizeof(mailbox));
04102       } else if (!strcasecmp(v->name, "hasvoicemail")) {
04103          if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
04104             ast_copy_string(mailbox, gw->name, sizeof(mailbox));
04105          }
04106       } else if (!strcasecmp(v->name, "adsi")) {
04107          adsi = ast_true(v->value);
04108       } else if (!strcasecmp(v->name, "callreturn")) {
04109          callreturn = ast_true(v->value);
04110       } else if (!strcasecmp(v->name, "callwaiting")) {
04111          callwaiting = ast_true(v->value);
04112       } else if (!strcasecmp(v->name, "slowsequence")) {
04113          slowsequence = ast_true(v->value);
04114       } else if (!strcasecmp(v->name, "transfer")) {
04115          transfer = ast_true(v->value);
04116       } else if (!strcasecmp(v->name, "threewaycalling")) {
04117          threewaycalling = ast_true(v->value);
04118       } else if (!strcasecmp(v->name, "wcardep")) {
04119          /* locate existing endpoint */
04120          for (e = gw->endpoints; e; e = e->next) {
04121             if (!strcasecmp(v->value, e->name)) {
04122                /* endpoint already exists */
04123                e->delme = 0;
04124                ep_reload = 1;
04125                break;
04126             }
04127          }
04128 
04129          if (!e) {
04130             /* Allocate wildcard endpoint */
04131             e = ast_calloc(1, sizeof(*e));
04132             ep_reload = 0;
04133          }
04134 
04135          if (e) {
04136             if (!ep_reload) {
04137                memset(e, 0, sizeof(struct mgcp_endpoint));
04138                ast_mutex_init(&e->lock);
04139                ast_mutex_init(&e->rqnt_queue_lock);
04140                ast_mutex_init(&e->cmd_queue_lock);
04141                ast_copy_string(e->name, v->value, sizeof(e->name));
04142                e->needaudit = 1;
04143             }
04144             ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
04145             /* XXX Should we really check for uniqueness?? XXX */
04146             ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
04147             ast_copy_string(e->context, context, sizeof(e->context));
04148             ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
04149             ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
04150             ast_copy_string(e->language, language, sizeof(e->language));
04151             ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
04152             ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
04153             ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
04154             if (!ast_strlen_zero(e->mailbox)) {
04155                char *mbox, *cntx;
04156                cntx = mbox = ast_strdupa(e->mailbox);
04157                strsep(&cntx, "@");
04158                if (ast_strlen_zero(cntx)) {
04159                   cntx = "default";
04160                }
04161                e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL,
04162                   AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
04163                   AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
04164                   AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
04165                   AST_EVENT_IE_END);
04166             }
04167             snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
04168             e->msgstate = -1;
04169             e->amaflags = amaflags;
04170             e->capability = capability;
04171             e->parent = gw;
04172             e->ncs = ncs;
04173             e->dtmfmode = dtmfmode;
04174             if (!ep_reload && e->sub && e->sub->rtp) {
04175                e->dtmfmode |= MGCP_DTMF_INBAND;
04176             }
04177             e->adsi = adsi;
04178             e->type = TYPE_LINE;
04179             e->immediate = immediate;
04180             e->callgroup=cur_callergroup;
04181             e->pickupgroup=cur_pickupgroup;
04182             e->callreturn = callreturn;
04183             e->cancallforward = cancallforward;
04184             e->singlepath = singlepath;
04185             e->directmedia = directmedia;
04186             e->callwaiting = callwaiting;
04187             e->hascallwaiting = callwaiting;
04188             e->slowsequence = slowsequence;
04189             e->transfer = transfer;
04190             e->threewaycalling = threewaycalling;
04191             e->onhooktime = time(NULL);
04192             /* ASSUME we're onhook */
04193             e->hookstate = MGCP_ONHOOK;
04194             e->chanvars = copy_vars(chanvars);
04195             if (!ep_reload) {
04196                /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
04197                for (i = 0; i < MAX_SUBS; i++) {
04198                   sub = ast_calloc(1, sizeof(*sub));
04199                   if (sub) {
04200                      ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
04201                      ast_mutex_init(&sub->lock);
04202                      ast_mutex_init(&sub->cx_queue_lock);
04203                      sub->parent = e;
04204                      sub->id = i;
04205                      snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
04206                      /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
04207                      sub->cxmode = MGCP_CX_INACTIVE;
04208                      sub->nat = nat;
04209                      sub->gate = NULL;
04210                      sub->sdpsent = 0;
04211                      sub->next = e->sub;
04212                      e->sub = sub;
04213                   } else {
04214                      /* XXX Should find a way to clean up our memory */
04215                      ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
04216                      return NULL;
04217                   }
04218                }
04219                /* Make out subs a circular linked list so we can always sping through the whole bunch */
04220                /* find the end of the list */
04221                for (sub = e->sub; sub && sub->next; sub = sub->next);
04222                /* set the last sub->next to the first sub */
04223                sub->next = e->sub;
04224 
04225                e->next = gw->endpoints;
04226                gw->endpoints = e;
04227             }
04228          }
04229       } else if (!strcasecmp(v->name, "trunk") ||
04230                  !strcasecmp(v->name, "line")) {
04231 
04232          /* locate existing endpoint */
04233          for (e = gw->endpoints; e; e = e->next) {
04234             if (!strcasecmp(v->value, e->name)) {
04235                /* endpoint already exists */
04236                e->delme = 0;
04237                ep_reload = 1;
04238                break;
04239             }
04240          }
04241 
04242          if (!e) {
04243             e = ast_calloc(1, sizeof(*e));
04244             ep_reload = 0;
04245          }
04246 
04247          if (e) {
04248             if (!ep_reload) {
04249                ast_mutex_init(&e->lock);
04250                ast_mutex_init(&e->rqnt_queue_lock);
04251                ast_mutex_init(&e->cmd_queue_lock);
04252                ast_copy_string(e->name, v->value, sizeof(e->name));
04253                e->needaudit = 1;
04254             }
04255             /* XXX Should we really check for uniqueness?? XXX */
04256             ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
04257             ast_copy_string(e->context, context, sizeof(e->context));
04258             ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
04259             ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
04260             ast_copy_string(e->language, language, sizeof(e->language));
04261             ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
04262             ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
04263             ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
04264             if (!ast_strlen_zero(mailbox)) {
04265                ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
04266             }
04267             if (!ep_reload) {
04268                /* XXX potential issue due to reload */
04269                e->msgstate = -1;
04270                e->parent = gw;
04271             }
04272             e->amaflags = amaflags;
04273             e->capability = capability;
04274             e->dtmfmode = dtmfmode;
04275             e->ncs = ncs;
04276             e->pktcgatealloc = pktcgatealloc;
04277             e->hangupongateremove = hangupongateremove;
04278             e->adsi = adsi;
04279             e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE;
04280             e->immediate = immediate;
04281             e->callgroup=cur_callergroup;
04282             e->pickupgroup=cur_pickupgroup;
04283             e->callreturn = callreturn;
04284             e->cancallforward = cancallforward;
04285             e->directmedia = directmedia;
04286             e->singlepath = singlepath;
04287             e->callwaiting = callwaiting;
04288             e->hascallwaiting = callwaiting;
04289             e->slowsequence = slowsequence;
04290             e->transfer = transfer;
04291             e->threewaycalling = threewaycalling;
04292 
04293             /* If we already have a valid chanvars, it's not a new endpoint (it's a reload),
04294                so first, free previous mem
04295              */
04296             if (e->chanvars) {
04297                ast_variables_destroy(e->chanvars);
04298                e->chanvars = NULL;
04299             }
04300             e->chanvars = copy_vars(chanvars);
04301 
04302             if (!ep_reload) {
04303                e->onhooktime = time(NULL);
04304                /* ASSUME we're onhook */
04305                e->hookstate = MGCP_ONHOOK;
04306                snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
04307             }
04308 
04309             for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
04310                if (!ep_reload) {
04311                   sub = ast_calloc(1, sizeof(*sub));
04312                } else {
04313                   if (!sub) {
04314                      sub = e->sub;
04315                   } else {
04316                      sub = sub->next;
04317                   }
04318                }
04319 
04320                if (sub) {
04321                   if (!ep_reload) {
04322                      ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
04323                      ast_mutex_init(&sub->lock);
04324                      ast_mutex_init(&sub->cx_queue_lock);
04325                      ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
04326                      sub->parent = e;
04327                      sub->id = i;
04328                      snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
04329                      sub->cxmode = MGCP_CX_INACTIVE;
04330                      sub->next = e->sub;
04331                      e->sub = sub;
04332                   }
04333                   sub->nat = nat;
04334                } else {
04335                   /* XXX Should find a way to clean up our memory */
04336                   ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
04337                   return NULL;
04338                }
04339             }
04340             if (!ep_reload) {
04341                /* Make out subs a circular linked list so we can always sping through the whole bunch */
04342                /* find the end of the list */
04343                for (sub = e->sub; sub && sub->next; sub = sub->next);
04344                /* set the last sub->next to the first sub */
04345                sub->next = e->sub;
04346 
04347                e->next = gw->endpoints;
04348                gw->endpoints = e;
04349             }
04350          }
04351       } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) {
04352          /* just eliminate realtime warnings */
04353       } else {
04354          ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
04355       }
04356    }
04357    if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
04358       ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
04359       if (!gw_reload) {
04360          ast_mutex_destroy(&gw->msgs_lock);
04361          ast_free(gw);
04362       }
04363 
04364       /* Return NULL */
04365       gw_reload = 1;
04366    } else {
04367       gw->defaddr.sin_family = AF_INET;
04368       gw->addr.sin_family = AF_INET;
04369       if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
04370          gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
04371       }
04372       if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
04373          gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
04374       }
04375       {
04376          struct ast_sockaddr tmp1, tmp2;
04377          struct sockaddr_in tmp3 = {0,};
04378 
04379          tmp3.sin_addr = gw->ourip;
04380          ast_sockaddr_from_sin(&tmp1, &gw->addr);
04381          ast_sockaddr_from_sin(&tmp2, &tmp3);
04382          if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
04383             memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
04384          } else {
04385             ast_sockaddr_to_sin(&tmp2, &tmp3);
04386             gw->ourip = tmp3.sin_addr;
04387          }
04388       }
04389    }
04390 
04391    if (chanvars) {
04392       ast_variables_destroy(chanvars);
04393       chanvars = NULL;
04394    }
04395    return (gw_reload ? NULL : gw);
04396 }

static char* control2str ( int  ind  )  [static]

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

01405                                   {
01406    switch (ind) {
01407    case AST_CONTROL_HANGUP:
01408       return "Other end has hungup";
01409    case AST_CONTROL_RING:
01410       return "Local ring";
01411    case AST_CONTROL_RINGING:
01412       return "Remote end is ringing";
01413    case AST_CONTROL_ANSWER:
01414       return "Remote end has answered";
01415    case AST_CONTROL_BUSY:
01416       return "Remote end is busy";
01417    case AST_CONTROL_TAKEOFFHOOK:
01418       return "Make it go off hook";
01419    case AST_CONTROL_OFFHOOK:
01420       return "Line is off hook";
01421    case AST_CONTROL_CONGESTION:
01422       return "Congestion (circuits busy)";
01423    case AST_CONTROL_FLASH:
01424       return "Flash hook";
01425    case AST_CONTROL_WINK:
01426       return "Wink";
01427    case AST_CONTROL_OPTION:
01428       return "Set a low-level option";
01429    case AST_CONTROL_RADIO_KEY:
01430       return "Key Radio";
01431    case AST_CONTROL_RADIO_UNKEY:
01432       return "Un-Key Radio";
01433    }
01434    return "UNKNOWN";
01435 }

static struct ast_variable * copy_vars ( struct ast_variable src  )  [static]

duplicate a list of channel variables,

Returns:
the copy.

Definition at line 4588 of file chan_mgcp.c.

References ast_variable_new(), and ast_variable::next.

Referenced by check_peer_ok(), and create_addr_from_peer().

04589 {
04590    struct ast_variable *res = NULL, *tmp, *v = NULL;
04591 
04592    for (v = src ; v ; v = v->next) {
04593       if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
04594          tmp->next = res;
04595          res = tmp;
04596       }
04597    }
04598    return res;
04599 }

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

Definition at line 4460 of file chan_mgcp.c.

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

Referenced by prune_gateways().

04461 {
04462    struct mgcp_subchannel *sub = e->sub->next, *s;
04463    int i;
04464 
04465    for (i = 0; i < MAX_SUBS; i++) {
04466       ast_mutex_lock(&sub->lock);
04467       if (!ast_strlen_zero(sub->cxident)) {
04468          transmit_connection_del(sub);
04469       }
04470       if (sub->rtp) {
04471          ast_rtp_instance_destroy(sub->rtp);
04472          sub->rtp = NULL;
04473       }
04474       memset(sub->magic, 0, sizeof(sub->magic));
04475       mgcp_queue_hangup(sub);
04476       dump_cmd_queues(NULL, sub);
04477       if(sub->gate) {
04478          sub->gate->tech_pvt = NULL;
04479          sub->gate->got_dq_gi = NULL;
04480          sub->gate->gate_remove = NULL;
04481          sub->gate->gate_open = NULL;
04482       }
04483       ast_mutex_unlock(&sub->lock);
04484       sub = sub->next;
04485    }
04486 
04487    if (e->dsp) {
04488       ast_dsp_free(e->dsp);
04489    }
04490 
04491    dump_queue(e->parent, e);
04492    dump_cmd_queues(e, NULL);
04493 
04494    sub = e->sub;
04495    for (i = 0; (i < MAX_SUBS) && sub; i++) {
04496       s = sub;
04497       sub = sub->next;
04498       ast_mutex_destroy(&s->lock);
04499       ast_mutex_destroy(&s->cx_queue_lock);
04500       ast_free(s);
04501    }
04502 
04503    if (e->mwi_event_sub)
04504       ast_event_unsubscribe(e->mwi_event_sub);
04505 
04506    if (e->chanvars) {
04507       ast_variables_destroy(e->chanvars);
04508       e->chanvars = NULL;
04509    }
04510 
04511    ast_mutex_destroy(&e->lock);
04512    ast_mutex_destroy(&e->rqnt_queue_lock);
04513    ast_mutex_destroy(&e->cmd_queue_lock);
04514    ast_free(e);
04515 }

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4517 of file chan_mgcp.c.

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

04518 {
04519    if (g->ha)
04520       ast_free_ha(g->ha);
04521 
04522    dump_queue(g, NULL);
04523 
04524    ast_free(g);
04525 }

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

Definition at line 3753 of file chan_mgcp.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, free, gatelock, gateways, has_voicemail(), io, MGCP_ONHOOK, mgcp_prune_realtime_gateway(), mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), mgcpsock_read_id, monlock, mgcp_gateway::msgs_lock, netlock, mgcp_gateway::next, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.

03754 {
03755    int res;
03756    int reloading;
03757    struct mgcp_gateway *g, *gprev, *gnext;
03758    /*struct mgcp_gateway *g;*/
03759    /*struct mgcp_endpoint *e;*/
03760    /*time_t thispass = 0, lastpass = 0;*/
03761    time_t lastrun = 0;
03762 
03763    /* Add an I/O event to our UDP socket */
03764    if (mgcpsock > -1) {
03765       mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03766    }
03767    /* This thread monitors all the frame relay interfaces which are not yet in use
03768       (and thus do not have a separate thread) indefinitely */
03769    /* From here on out, we die whenever asked */
03770    for (;;) {
03771       /* Check for a reload request */
03772       ast_mutex_lock(&mgcp_reload_lock);
03773       reloading = mgcp_reloading;
03774       mgcp_reloading = 0;
03775       ast_mutex_unlock(&mgcp_reload_lock);
03776       if (reloading) {
03777          ast_verb(1, "Reloading MGCP\n");
03778          reload_config(1);
03779          /* Add an I/O event to our UDP socket */
03780          if (mgcpsock > -1 && !mgcpsock_read_id) {
03781             mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
03782          }
03783       }
03784 
03785       /* Check for interfaces needing to be killed */
03786       /* Don't let anybody kill us right away.  Nobody should lock the interface list
03787          and wait for the monitor list, but the other way around is okay. */
03788       ast_mutex_lock(&monlock);
03789       /* Lock the network interface */
03790       ast_mutex_lock(&netlock);
03791 
03792 #if 0
03793       /* XXX THIS IS COMPLETELY HOSED */
03794       /* The gateway goes into a state of panic */
03795       /* If the vmwi indicator is sent while it is reseting interfaces */
03796       lastpass = thispass;
03797       thispass = time(NULL);
03798       g = gateways;
03799       while(g) {
03800          if (thispass != lastpass) {
03801             e = g->endpoints;
03802             while(e) {
03803                if (e->type == TYPE_LINE) {
03804                   res = has_voicemail(e);
03805                   if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
03806                      if (res) {
03807                         transmit_notify_request(e, "L/vmwi(+)");
03808                      } else {
03809                         transmit_notify_request(e, "L/vmwi(-)");
03810                      }
03811                      e->msgstate = res;
03812                      e->onhooktime = thispass;
03813                   }
03814                }
03815                e = e->next;
03816             }
03817          }
03818          g = g->next;
03819       }
03820 #endif
03821       /* pruning unused realtime gateways, running in every 60 seconds*/
03822       if(time(NULL) > (lastrun + 60)) {
03823          ast_mutex_lock(&gatelock);
03824          g = gateways;
03825          gprev = NULL;
03826          while(g) {
03827             gnext = g->next;
03828             if(g->realtime) {
03829                if(mgcp_prune_realtime_gateway(g)) {
03830                   if(gprev) {
03831                      gprev->next = gnext;
03832                      gprev = g;
03833                   } else {
03834                      gateways = g->next;
03835                   }
03836                   ast_mutex_unlock(&g->msgs_lock);
03837                   ast_mutex_destroy(&g->msgs_lock);
03838                   free(g);
03839                } else {
03840                   ast_mutex_unlock(&g->msgs_lock);
03841                   gprev = g;
03842                }
03843             } else {
03844                gprev = g;
03845             }
03846             g = gnext;
03847          }
03848          ast_mutex_unlock(&gatelock);
03849          lastrun = time(NULL);
03850       }
03851       /* Okay, now that we know what to do, release the network lock */
03852       ast_mutex_unlock(&netlock);
03853       /* And from now on, we're okay to be killed, so release the monitor lock as well */
03854       ast_mutex_unlock(&monlock);
03855       pthread_testcancel();
03856       /* Wait for sched or io */
03857       res = ast_sched_wait(sched);
03858       /* copied from chan_sip.c */
03859       if ((res < 0) || (res > 1000)) {
03860          res = 1000;
03861       }
03862       res = ast_io_wait(io, res);
03863       ast_mutex_lock(&monlock);
03864       if (res >= 0) {
03865          ast_sched_runq(sched);
03866       }
03867       ast_mutex_unlock(&monlock);
03868    }
03869    /* Never reached */
03870    return NULL;
03871 }

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

dump_cmd_queues: (SC:) cleanup pending commands

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

02676 {
02677    struct mgcp_request *t, *q;
02678 
02679    if (p) {
02680       ast_mutex_lock(&p->rqnt_queue_lock);
02681       for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
02682       p->rqnt_queue = NULL;
02683       ast_mutex_unlock(&p->rqnt_queue_lock);
02684 
02685       ast_mutex_lock(&p->cmd_queue_lock);
02686       for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
02687       p->cmd_queue = NULL;
02688       ast_mutex_unlock(&p->cmd_queue_lock);
02689 
02690       ast_mutex_lock(&p->sub->cx_queue_lock);
02691       for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02692       p->sub->cx_queue = NULL;
02693       ast_mutex_unlock(&p->sub->cx_queue_lock);
02694 
02695       ast_mutex_lock(&p->sub->next->cx_queue_lock);
02696       for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
02697       p->sub->next->cx_queue = NULL;
02698       ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02699    } else if (sub) {
02700       ast_mutex_lock(&sub->cx_queue_lock);
02701       for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02702       sub->cx_queue = NULL;
02703       ast_mutex_unlock(&sub->cx_queue_lock);
02704    }
02705 }

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

Definition at line 578 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, mgcp_message::next, mgcp_message::owner_ep, and mgcp_message::seqno.

Referenced by destroy_gateway(), and handle_request().

00579 {
00580    struct mgcp_message *cur, *q = NULL, *w, *prev;
00581 
00582    ast_mutex_lock(&gw->msgs_lock);
00583    for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
00584       if (!p || cur->owner_ep == p) {
00585          if (prev) {
00586             prev->next = cur->next;
00587          } else {
00588             gw->msgs = cur->next;
00589          }
00590 
00591          ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
00592             gw->name, cur->seqno);
00593 
00594          w = cur;
00595          if (q) {
00596             w->next = q;
00597          } else {
00598             w->next = NULL;
00599          }
00600          q = w;
00601       }
00602    }
00603    ast_mutex_unlock(&gw->msgs_lock);
00604 
00605    while (q) {
00606       cur = q;
00607       q = q->next;
00608       ast_free(cur);
00609    }
00610 }

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

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

03575 {
03576    int seqno=0;
03577    time_t now;
03578    struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
03579    time(&now);
03580    if (sscanf(req->identifier, "%30d", &seqno) != 1) {
03581       seqno = 0;
03582    }
03583    for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
03584       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03585          /* Delete this entry */
03586          if (prev)
03587             prev->next = next;
03588          else
03589             sub->parent->parent->responses = next;
03590          ast_free(cur);
03591       } else {
03592          if (seqno == cur->seqno)
03593             answer = cur;
03594          prev = cur;
03595       }
03596    }
03597    if (answer) {
03598       resend_response(sub, answer);
03599       return 1;
03600    }
03601    return 0;
03602 }

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

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

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

02711 {
02712    struct mgcp_request *prev, *req;
02713 
02714    ast_mutex_lock(l);
02715    for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02716       if (req->trid == ident) {
02717          /* remove from queue */
02718          if (!prev)
02719             *queue = req->next;
02720          else
02721             prev->next = req->next;
02722 
02723          /* send next pending command */
02724          if (*queue) {
02725             ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02726                ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02727 
02728             mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02729          }
02730          break;
02731       }
02732    }
02733    ast_mutex_unlock(l);
02734    return req;
02735 }

static struct mgcp_gateway* find_realtime_gw ( char *  name,
char *  at,
struct sockaddr_in *  sin 
) [static]

Definition at line 1660 of file chan_mgcp.c.

References ast_check_realtime(), ast_copy_string(), ast_debug, ast_load_realtime(), ast_strlen_zero(), ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by find_subchannel_and_lock().

01661 {
01662    struct mgcp_gateway *g = NULL;
01663    struct ast_variable *mgcpgwconfig = NULL;
01664    struct ast_variable *gwv, *epname = NULL;
01665    struct mgcp_endpoint *e;
01666    char lines[256];
01667    int i, j;
01668 
01669    ast_debug(1, "*** find Realtime MGCPGW\n");
01670 
01671    if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) {
01672       return NULL;
01673    }
01674 
01675    if (ast_strlen_zero(at)) {
01676       ast_debug(1, "null gw name\n");
01677       return NULL;
01678    }
01679 
01680    if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) {
01681       return NULL;
01682    }
01683 
01684    /*!
01685     * \note This is a fairly odd way of instantiating lines.  Instead of each
01686     * line created by virtue of being in the database (and loaded via
01687     * ast_load_realtime_multientry), this code forces a specific order with a
01688     * "lines" entry in the "mgcpgw" record.  This has benefits, because as with
01689     * chan_dahdi, values are inherited across definitions.  The downside is
01690     * that it's not as clear what the values will be simply by looking at a
01691     * single row in the database, and it's probable that the sanest configuration
01692     * should have the first column in the "mgcpep" table be "clearvars", with a
01693     * static value of "all", if any variables are set at all.  It may be worth
01694     * making this assumption explicit in the code in the future, and then just
01695     * using ast_load_realtime_multientry for the "mgcpep" records.
01696     */
01697    lines[0] = '\0';
01698    for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
01699       if (!strcasecmp(gwv->name, "lines")) {
01700          ast_copy_string(lines, gwv->value, sizeof(lines));
01701          break;
01702       }
01703    }
01704    /* Position gwv at the end of the list */
01705    for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next);
01706 
01707    if (!ast_strlen_zero(lines)) {
01708       AST_DECLARE_APP_ARGS(args,
01709          AST_APP_ARG(line)[100];
01710       );
01711       AST_STANDARD_APP_ARGS(args, lines);
01712       for (i = 0; i < args.argc; i++) {
01713          gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL);
01714 
01715          /* Remove "line" AND position gwv at the end of the list. */
01716          for (epname = NULL; gwv->next; gwv = gwv->next) {
01717             if (!strcasecmp(gwv->next->name, "line")) {
01718                /* Remove it from the list */
01719                epname = gwv->next;
01720                gwv->next = gwv->next->next;
01721             }
01722          }
01723          /* Since "line" instantiates the configuration, we have to move it to the end. */
01724          if (epname) {
01725             gwv->next = epname;
01726             epname->next = NULL;
01727             gwv = gwv->next;
01728          }
01729       }
01730    }
01731    for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
01732       ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value);
01733    }
01734 
01735    if (mgcpgwconfig) {
01736       g = build_gateway(at, mgcpgwconfig);
01737       ast_variables_destroy(mgcpgwconfig);
01738    }
01739    if (g) {
01740       g->next = gateways;
01741       g->realtime = 1;
01742       gateways = g;
01743       for (e = g->endpoints; e; e = e->next) {
01744          transmit_audit_endpoint(e);
01745          e->needaudit = 0;
01746       }
01747    }
01748    return g;
01749 }

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

Definition at line 1751 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_sockaddr_from_sin, ast_sockaddr_to_sin, ast_verb, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, find_realtime_gw(), gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, mgcp_gateway::ourip, and mgcp_endpoint::sub.

Referenced by mgcp_request(), and mgcpsock_read().

01752 {
01753    struct mgcp_endpoint *p = NULL;
01754    struct mgcp_subchannel *sub = NULL;
01755    struct mgcp_gateway *g;
01756    char tmp[256] = "";
01757    char *at = NULL, *c;
01758    int found = 0;
01759    if (name) {
01760       ast_copy_string(tmp, name, sizeof(tmp));
01761       at = strchr(tmp, '@');
01762       if (!at) {
01763          ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
01764          return NULL;
01765       }
01766       *at++ = '\0';
01767    }
01768    ast_mutex_lock(&gatelock);
01769    if (at && (at[0] == '[')) {
01770       at++;
01771       c = strrchr(at, ']');
01772       if (c) {
01773          *c = '\0';
01774       }
01775    }
01776    for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) {
01777       if ((!name || !strcasecmp(g->name, at)) &&
01778           (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
01779          /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
01780          if (sin && g->dynamic && name) {
01781             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01782                (g->addr.sin_port != sin->sin_port)) {
01783                memcpy(&g->addr, sin, sizeof(g->addr));
01784                {
01785                   struct ast_sockaddr tmp1, tmp2;
01786                   struct sockaddr_in tmp3 = {0,};
01787 
01788                   tmp3.sin_addr = g->ourip;
01789                   ast_sockaddr_from_sin(&tmp1, &g->addr);
01790                   ast_sockaddr_from_sin(&tmp2, &tmp3);
01791                   if (ast_ouraddrfor(&tmp1, &tmp2)) {
01792                      memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
01793                   }
01794                   ast_sockaddr_to_sin(&tmp2, &tmp3);
01795                   g->ourip = tmp3.sin_addr;
01796                }
01797                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));
01798             }
01799          /* not dynamic, check if the name matches */
01800          } else if (name) {
01801             if (strcasecmp(g->name, at)) {
01802                g = g->next;
01803                continue;
01804             }
01805          /* not dynamic, no name, check if the addr matches */
01806          } else if (!name && sin) {
01807             if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
01808                 (g->addr.sin_port != sin->sin_port)) {
01809                if(!g->next)
01810                   g = find_realtime_gw(name, at, sin);
01811                else
01812                   g = g->next;
01813                continue;
01814             }
01815          } else {
01816             continue;
01817          }
01818          for (p = g->endpoints; p; p = p->next) {
01819             ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name);
01820             if (msgid) {
01821                sub = p->sub;
01822                found = 1;
01823                break;
01824             } else if (name && !strcasecmp(p->name, tmp)) {
01825                ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
01826                   p->name, g->name, p->sub->id);
01827                sub = p->sub;
01828                found = 1;
01829                break;
01830             }
01831          }
01832          if (sub && found) {
01833             ast_mutex_lock(&sub->lock);
01834             break;
01835          }
01836       }
01837    }
01838    ast_mutex_unlock(&gatelock);
01839    if (!sub) {
01840       if (name) {
01841          if (g) {
01842             ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
01843          } else {
01844             ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
01845          }
01846       }
01847    }
01848    return sub;
01849 }

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

get_csv: (SC:) get comma separated value

Definition at line 1636 of file chan_mgcp.c.

Referenced by handle_response().

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

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

Definition at line 1629 of file chan_mgcp.c.

References __get_header().

Referenced by __transmit_response(), _sip_tcp_helper_thread(), build_route(), cc_handle_publish_error(), change_redirecting_information(), check_auth(), check_user_full(), check_via(), check_via_response(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_pai(), get_rdnis(), get_realm(), get_refer_info(), get_rpid(), gettag(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_request(), handle_request_bye(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_register(), handle_request_subscribe(), handle_request_update(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_publish(), handle_response_refer(), handle_response_register(), handle_response_subscribe(), handle_response_update(), parse_allowed_methods(), 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_alloc(), sip_get_cc_information(), sip_pidf_validate(), 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().

01630 {
01631    int start = 0;
01632    return __get_header(req, name, &start, "");
01633 }

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

Definition at line 1580 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

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

Definition at line 1570 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

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

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

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

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

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

Definition at line 3247 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_endpoint::ncs, 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().

03248 {
03249    struct mgcp_endpoint *p = sub->parent;
03250    struct ast_channel *c;
03251    pthread_t t;
03252 
03253    /* Off hook / answer */
03254    if (sub->outgoing) {
03255       /* Answered */
03256       if (sub->owner) {
03257          if (ast_bridged_channel(sub->owner))
03258             ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03259          sub->cxmode = MGCP_CX_SENDRECV;
03260          if (!sub->rtp) {
03261             start_rtp(sub);
03262          } else {
03263             transmit_modify_request(sub);
03264          }
03265          /*transmit_notify_request(sub, "aw");*/
03266          transmit_notify_request(sub, "");
03267          mgcp_queue_control(sub, AST_CONTROL_ANSWER);
03268       }
03269    } else {
03270       /* Start switch */
03271       /*sub->cxmode = MGCP_CX_SENDRECV;*/
03272       if (!sub->owner) {
03273          if (!sub->rtp) {
03274             start_rtp(sub);
03275          } else {
03276             transmit_modify_request(sub);
03277          }
03278          if (p->immediate) {
03279             /* The channel is immediately up. Start right away */
03280 #ifdef DLINK_BUGGY_FIRMWARE
03281             transmit_notify_request(sub, "rt");
03282 #else
03283             transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
03284 #endif
03285             c = mgcp_new(sub, AST_STATE_RING, NULL);
03286             if (!c) {
03287                ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
03288                transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03289                ast_hangup(c);
03290             }
03291          } else {
03292             if (has_voicemail(p)) {
03293                transmit_notify_request(sub, "L/sl");
03294             } else {
03295                transmit_notify_request(sub, "L/dl");
03296             }
03297             c = mgcp_new(sub, AST_STATE_DOWN, NULL);
03298             if (c) {
03299                if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
03300                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03301                   ast_hangup(c);
03302                }
03303             } else {
03304                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03305             }
03306          }
03307       } else {
03308          if (p->hookstate == MGCP_OFFHOOK) {
03309             ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03310          } else {
03311             ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03312             ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03313          }
03314          if (ast_bridged_channel(sub->owner))
03315             ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03316          sub->cxmode = MGCP_CX_SENDRECV;
03317          if (!sub->rtp) {
03318             start_rtp(sub);
03319          } else {
03320             transmit_modify_request(sub);
03321          }
03322          /*transmit_notify_request(sub, "aw");*/
03323          transmit_notify_request(sub, "");
03324          /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
03325       }
03326    }
03327 }

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

Definition at line 1078 of file chan_mgcp.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, ast_strdupa, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, mgcp_gateway::endpoints, gatelock, gateways, mgcpdebug, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, transmit_audit_endpoint(), and ast_cli_entry::usage.

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

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

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

01140 {
01141    switch (cmd) {
01142    case CLI_INIT:
01143       e->command = "mgcp set debug {on|off}";
01144       e->usage =
01145          "Usage: mgcp set debug {on|off}\n"
01146          "       Enables/Disables dumping of MGCP packets for debugging purposes\n";   
01147       return NULL;
01148    case CLI_GENERATE:
01149       return NULL;
01150    }
01151 
01152    if (a->argc != e->args)
01153       return CLI_SHOWUSAGE;
01154 
01155    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
01156       mgcpdebug = 1;
01157       ast_cli(a->fd, "MGCP Debugging Enabled\n");
01158    } else if (!strncasecmp(a->argv[3], "off", 3)) {
01159       mgcpdebug = 0;
01160       ast_cli(a->fd, "MGCP Debugging Disabled\n");
01161    } else {
01162       return CLI_SHOWUSAGE;
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 1036 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock, mgcp_endpoint::chanvars, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, mgcp_endpoint::context, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_subchannel::owner, mgcp_gateway::realtime, mgcp_endpoint::sub, ast_cli_entry::usage, and ast_variable::value.

01037 {
01038    struct mgcp_gateway  *mg;
01039    struct mgcp_endpoint *me;
01040    int hasendpoints = 0;
01041    struct ast_variable * v = NULL;
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    }
01057    ast_mutex_lock(&gatelock);
01058    for (mg = gateways; mg; mg = mg->next) {
01059       ast_cli(a->fd, "Gateway '%s' at %s (%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->realtime ? "Realtime, " : "", mg->dynamic ? "Dynamic" : "Static");
01060       for (me = mg->endpoints; me; me = me->next) {
01061          ast_cli(a->fd, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
01062          if (me->chanvars) {
01063             ast_cli(a->fd, "  Variables:\n");
01064             for (v = me->chanvars ; v ; v = v->next) {
01065                ast_cli(a->fd, "    %s = '%s'\n", v->name, v->value);
01066             }
01067          }
01068          hasendpoints = 1;
01069       }
01070       if (!hasendpoints) {
01071          ast_cli(a->fd, "   << No Endpoints Defined >>     ");
01072       }
01073    }
01074    ast_mutex_unlock(&gatelock);
01075    return CLI_SUCCESS;
01076 }

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

Definition at line 3329 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, 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_endpoint::ncs, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, 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().

03330 {
03331    char *ev, *s;
03332    struct ast_frame f = { 0, };
03333    struct mgcp_endpoint *p = sub->parent;
03334    struct mgcp_gateway *g = NULL;
03335    int res;
03336 
03337    ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
03338    /* Clear out potential response */
03339    if (!strcasecmp(req->verb, "RSIP")) {
03340       /* Test if this RSIP request is just a keepalive */
03341       if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
03342          ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
03343          transmit_response(sub, "200", req, "OK");
03344       } else {
03345          dump_queue(p->parent, p);
03346          dump_cmd_queues(p, NULL);
03347 
03348          if ((strcmp(p->name, p->parent->wcardep) != 0)) {
03349             ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
03350          }
03351          /* For RSIP on wildcard we reset all endpoints */
03352          if (!strcmp(p->name, p->parent->wcardep)) {
03353             /* Reset all endpoints */
03354             struct mgcp_endpoint *tmp_ep;
03355 
03356             g = p->parent;
03357             for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) {
03358                /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
03359                if (strcmp(tmp_ep->name, g->wcardep) != 0) {
03360                   struct mgcp_subchannel *tmp_sub, *first_sub;
03361                   ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
03362 
03363                   first_sub = tmp_ep->sub;
03364                   tmp_sub = tmp_ep->sub;
03365                   while (tmp_sub) {
03366                      mgcp_queue_hangup(tmp_sub);
03367                      tmp_sub = tmp_sub->next;
03368                      if (tmp_sub == first_sub)
03369                         break;
03370                   }
03371                }
03372             }
03373          } else if (sub->owner) {
03374             mgcp_queue_hangup(sub);
03375          }
03376          transmit_response(sub, "200", req, "OK");
03377          /* We don't send NTFY or AUEP to wildcard ep */
03378          if (strcmp(p->name, p->parent->wcardep) != 0) {
03379             transmit_notify_request(sub, "");
03380             /* Audit endpoint.
03381              Idea is to prevent lost lines due to race conditions
03382             */
03383             transmit_audit_endpoint(p);
03384          }
03385       }
03386    } else if (!strcasecmp(req->verb, "NTFY")) {
03387       /* Acknowledge and be sure we keep looking for the same things */
03388       transmit_response(sub, "200", req, "OK");
03389       /* Notified of an event */
03390       ev = get_header(req, "O");
03391       s = strchr(ev, '/');
03392       if (s) ev = s + 1;
03393       ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
03394       /* Keep looking for events unless this was a hangup */
03395       if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
03396          transmit_notify_request(sub, p->curtone);
03397       }
03398       if (!strcasecmp(ev, "hd")) {
03399          p->hookstate = MGCP_OFFHOOK;
03400          sub->cxmode = MGCP_CX_SENDRECV;
03401 
03402          if (p) {
03403            /* When the endpoint have a Off hook transition we allways
03404               starts without any previous dtmfs */
03405            memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03406          }
03407 
03408          handle_hd_hf(sub, ev);
03409       } else if (!strcasecmp(ev, "hf")) {
03410          /* We can assume we are offhook if we received a hookflash */
03411          /* First let's just do call wait and ignore threeway */
03412          /* We're currently in charge */
03413          if (p->hookstate != MGCP_OFFHOOK) {
03414             /* Cisco c7940 sends hf even if the phone is onhook */
03415             /* Thanks to point on IRC for pointing this out */
03416             return -1;
03417          }
03418          /* do not let * conference two down channels */
03419          if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
03420             return -1;
03421 
03422          if (p->callwaiting || p->transfer || p->threewaycalling) {
03423             ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03424             p->sub = p->sub->next;
03425 
03426             /* transfer control to our next subchannel */
03427             if (!sub->next->owner) {
03428                /* plave the first call on hold and start up a new call */
03429                sub->cxmode = MGCP_CX_MUTE;
03430                ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03431                transmit_modify_request(sub);
03432                if (sub->owner && ast_bridged_channel(sub->owner))
03433                   ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03434                sub->next->cxmode = MGCP_CX_RECVONLY;
03435                handle_hd_hf(sub->next, ev);
03436             } else if (sub->owner && sub->next->owner) {
03437                /* We've got two active calls lets decide whether or not to conference or just flip flop */
03438                if ((!sub->outgoing) && (!sub->next->outgoing)) {
03439                   /* We made both calls lets conferenct */
03440                   ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
03441                         sub->id, sub->next->id, p->name, p->parent->name);
03442                   sub->cxmode = MGCP_CX_CONF;
03443                   sub->next->cxmode = MGCP_CX_CONF;
03444                   if (ast_bridged_channel(sub->next->owner))
03445                      ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
03446                   transmit_modify_request(sub);
03447                   transmit_modify_request(sub->next);
03448                } else {
03449                   /* Let's flipflop between calls */
03450                   /* XXX Need to check for state up ??? */
03451                   /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
03452                   ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
03453                         sub->id, sub->next->id, p->name, p->parent->name);
03454                   sub->cxmode = MGCP_CX_MUTE;
03455                   ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
03456                   transmit_modify_request(sub);
03457                   if (ast_bridged_channel(sub->owner))
03458                      ast_queue_control(sub->owner, AST_CONTROL_HOLD);
03459 
03460                   if (ast_bridged_channel(sub->next->owner))
03461                      ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
03462 
03463                   handle_hd_hf(sub->next, ev);
03464                }
03465             } else {
03466                /* We've most likely lost one of our calls find an active call and bring it up */
03467                if (sub->owner) {
03468                   p->sub = sub;
03469                } else if (sub->next->owner) {
03470                   p->sub = sub->next;
03471                } else {
03472                   /* We seem to have lost both our calls */
03473                   /* XXX - What do we do now? */
03474                   return -1;
03475                }
03476                if (ast_bridged_channel(p->sub->owner))
03477                   ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD);
03478                p->sub->cxmode = MGCP_CX_SENDRECV;
03479                transmit_modify_request(p->sub);
03480             }
03481          } else {
03482             ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
03483                p->name, p->parent->name);
03484          }
03485       } else if (!strcasecmp(ev, "hu")) {
03486          p->hookstate = MGCP_ONHOOK;
03487          sub->cxmode = MGCP_CX_RECVONLY;
03488          ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
03489          /* Do we need to send MDCX before a DLCX ?
03490          if (sub->rtp) {
03491             transmit_modify_request(sub);
03492          }
03493          */
03494          if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
03495             /* We're allowed to transfer, we have two avtive calls and */
03496             /* we made at least one of the calls.  Let's try and transfer */
03497             ast_mutex_lock(&p->sub->next->lock);
03498             res = attempt_transfer(p);
03499             if (res < 0) {
03500                if (p->sub->next->owner) {
03501                   sub->next->alreadygone = 1;
03502                   mgcp_queue_hangup(sub->next);
03503                }
03504             } else if (res) {
03505                ast_log(LOG_WARNING, "Transfer attempt failed\n");
03506                ast_mutex_unlock(&p->sub->next->lock);
03507                return -1;
03508             }
03509             ast_mutex_unlock(&p->sub->next->lock);
03510          } else {
03511             /* Hangup the current call */
03512             /* If there is another active call, mgcp_hangup will ring the phone with the other call */
03513             if (sub->owner) {
03514                sub->alreadygone = 1;
03515                mgcp_queue_hangup(sub);
03516             } else {
03517                ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
03518                      p->name, p->parent->name, sub->id);
03519                /* Instruct the other side to remove the connection since it apparently *
03520                 * still thinks the channel is active. *
03521                 * For Cisco IAD2421 /BAK/ */
03522                transmit_connection_del(sub);
03523             }
03524          }
03525          if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
03526             p->hidecallerid = 0;
03527             if (p->hascallwaiting && !p->callwaiting) {
03528                ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
03529                p->callwaiting = -1;
03530             }
03531             if (has_voicemail(p)) {
03532                ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
03533                transmit_notify_request(sub, "L/vmwi(+)");
03534             } else {
03535                ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
03536                transmit_notify_request(sub, "L/vmwi(-)");
03537             }
03538          }
03539       } else if ((strlen(ev) == 1) &&
03540             (((ev[0] >= '0') && (ev[0] <= '9')) ||
03541              ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
03542               (ev[0] == '*') || (ev[0] == '#'))) {
03543          if (sub && sub->owner && (sub->owner->_state >=  AST_STATE_UP)) {
03544             f.frametype = AST_FRAME_DTMF;
03545             f.subclass.integer = ev[0];
03546             f.src = "mgcp";
03547             /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
03548             mgcp_queue_frame(sub, &f);
03549             ast_mutex_lock(&sub->next->lock);
03550             if (sub->next->owner)
03551                mgcp_queue_frame(sub->next, &f);
03552             ast_mutex_unlock(&sub->next->lock);
03553             if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) {
03554                memset(p->curtone, 0, sizeof(p->curtone));
03555             }
03556          } else {
03557             p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
03558             p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
03559          }
03560       } else if (!strcasecmp(ev, "T")) {
03561          /* Digit timeout -- unimportant */
03562       } else if (!strcasecmp(ev, "ping")) {
03563          /* ping -- unimportant */
03564       } else {
03565          ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
03566       }
03567    } else {
03568       ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr));
03569       transmit_response(sub, "510", req, "Unknown verb");
03570    }
03571    return 0;
03572 }

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

References AST_CONTROL_RINGING, ast_copy_string(), ast_free, ast_log(), ast_queue_control(), AST_STATE_RINGING, 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_CMD_MDCX, 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(), transmit_notify_request(), and transmit_response().

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

02740 {
02741    char *c;
02742    struct mgcp_request *req;
02743    struct mgcp_gateway *gw = p->parent;
02744 
02745    if (result < 200) {
02746       /* provisional response */
02747       return;
02748    }
02749 
02750    if (p->slowsequence)
02751       req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02752    else if (sub)
02753       req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
02754    else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
02755       req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
02756 
02757    if (!req) {
02758       ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n",
02759             gw->name, ident);
02760       return;
02761    }
02762 
02763    if (p && (result >= 400) && (result <= 599)) {
02764       switch (result) {
02765       case 401:
02766          p->hookstate = MGCP_OFFHOOK;
02767          break;
02768       case 402:
02769          p->hookstate = MGCP_ONHOOK;
02770          break;
02771       case 406:
02772          ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
02773          break;
02774       case 407:
02775          ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
02776          break;
02777       }
02778       if (sub) {
02779          if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
02780              ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
02781              transmit_connection_del(sub);
02782          }
02783          if (sub->owner) {
02784             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02785                result, p->name, p->parent->name, sub ? sub->id:-1);
02786             mgcp_queue_hangup(sub);
02787          }
02788       } else {
02789          if (p->sub->next->owner) {
02790             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02791                result, p->name, p->parent->name, sub ? sub->id:-1);
02792             mgcp_queue_hangup(p->sub);
02793          }
02794 
02795          if (p->sub->owner) {
02796             ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
02797                result, p->name, p->parent->name, sub ? sub->id:-1);
02798             mgcp_queue_hangup(p->sub);
02799          }
02800 
02801          dump_cmd_queues(p, NULL);
02802       }
02803    }
02804 
02805    if (resp) {
02806       /* responseAck: */
02807       if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
02808             if (sub) {
02809                transmit_response(sub, "000", resp, "OK");
02810                if (sub->owner && sub->owner->_state == AST_STATE_RINGING) {
02811                   ast_queue_control(sub->owner, AST_CONTROL_RINGING);
02812                }
02813             }
02814       }
02815       if (req->cmd == MGCP_CMD_CRCX) {
02816          if ((c = get_header(resp, "I"))) {
02817             if (!ast_strlen_zero(c) && sub) {
02818                /* if we are hanging up do not process this conn. */
02819                if (sub->owner) {
02820                   if (!ast_strlen_zero(sub->cxident)) {
02821                      if (strcasecmp(c, sub->cxident)) {
02822                         ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
02823                      }
02824                   }
02825                   ast_copy_string(sub->cxident, c, sizeof(sub->cxident));
02826                   if (sub->tmpdest.sin_addr.s_addr) {
02827                      transmit_modify_with_sdp(sub, NULL, 0);
02828                   }
02829                } else {
02830                   /* XXX delete this one
02831                      callid and conn id may already be lost.
02832                      so the following del conn may have a side effect of
02833                      cleaning up the next subchannel */
02834                   transmit_connection_del(sub);
02835                }
02836             }
02837          }
02838       }
02839 
02840       if (req->cmd == MGCP_CMD_AUEP) {
02841          /* check stale connection ids */
02842          if ((c = get_header(resp, "I"))) {
02843             char *v, *n;
02844             int len;
02845             while ((v = get_csv(c, &len, &n))) {
02846                if (len) {
02847                   if (strncasecmp(v, p->sub->cxident, len) &&
02848                       strncasecmp(v, p->sub->next->cxident, len)) {
02849                      /* connection id not found. delete it */
02850                      char cxident[80] = "";
02851 
02852                      if (len > (sizeof(cxident) - 1))
02853                         len = sizeof(cxident) - 1;
02854                      ast_copy_string(cxident, v, len);
02855                      ast_verb(3, "Non existing connection id %s on %s@%s \n",
02856                                cxident, p->name, gw->name);
02857                      transmit_connection_del_w_params(p, NULL, cxident);
02858                   }
02859                }
02860                c = n;
02861             }
02862          }
02863 
02864          /* Try to determine the hookstate returned from an audit endpoint command */
02865          if ((c = get_header(resp, "ES"))) {
02866             if (!ast_strlen_zero(c)) {
02867                if (strstr(c, "hu")) {
02868                   if (p->hookstate != MGCP_ONHOOK) {
02869                      /* XXX cleanup if we think we are offhook XXX */
02870                      if ((p->sub->owner || p->sub->next->owner ) &&
02871                          p->hookstate == MGCP_OFFHOOK)
02872                         mgcp_queue_hangup(sub);
02873                      p->hookstate = MGCP_ONHOOK;
02874 
02875                      /* update the requested events according to the new hookstate */
02876                      transmit_notify_request(p->sub, "");
02877 
02878                      ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
02879                      }
02880                } else if (strstr(c, "hd")) {
02881                   if (p->hookstate != MGCP_OFFHOOK) {
02882                      p->hookstate = MGCP_OFFHOOK;
02883 
02884                      /* update the requested events according to the new hookstate */
02885                      transmit_notify_request(p->sub, "");
02886 
02887                      ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
02888                      }
02889                   }
02890                }
02891             }
02892          }
02893 
02894       if (resp && resp->lines) {
02895          /* do not process sdp if we are hanging up. this may be a late response */
02896          if (sub && sub->owner) {
02897             if (!sub->rtp)
02898                start_rtp(sub);
02899             if (sub->rtp)
02900                process_sdp(sub, resp);
02901          }
02902       }
02903    }
02904 
02905    ast_free(req);
02906 }

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

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

00490 {
00491    int new_msgs;
00492    struct ast_event *event;
00493    char *mbox, *cntx;
00494 
00495    cntx = mbox = ast_strdupa(p->mailbox);
00496    strsep(&cntx, "@");
00497    if (ast_strlen_zero(cntx))
00498       cntx = "default";
00499 
00500    event = ast_event_get_cached(AST_EVENT_MWI,
00501       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
00502       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
00503       AST_EVENT_IE_END);
00504 
00505    if (event) {
00506       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
00507       ast_event_destroy(event);
00508    } else
00509       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
00510 
00511    return new_msgs;
00512 }

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

Definition at line 2101 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, mgcp_endpoint::ncs, oseq, and mgcp_endpoint::parent.

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

02102 {
02103    /* Initialize a response */
02104    if (req->headers || req->len) {
02105       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02106       return -1;
02107    }
02108    req->header[req->headers] = req->data + req->len;
02109    /* check if we need brackets around the gw name */
02110    if (p->parent->isnamedottedip) {
02111       snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
02112    } else {
02113 +     snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
02114    }
02115    req->len += strlen(req->header[req->headers]);
02116    if (req->headers < MGCP_MAX_HEADERS) {
02117       req->headers++;
02118    } else {
02119       ast_log(LOG_WARNING, "Out of header space\n");
02120    }
02121    return 0;
02122 }

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

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

02084 {
02085    /* Initialize a response */
02086    if (req->headers || req->len) {
02087       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02088       return -1;
02089    }
02090    req->header[req->headers] = req->data + req->len;
02091    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
02092    req->len += strlen(req->header[req->headers]);
02093    if (req->headers < MGCP_MAX_HEADERS) {
02094       req->headers++;
02095    } else {
02096       ast_log(LOG_WARNING, "Out of header space\n");
02097    }
02098    return 0;
02099 }

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

Definition at line 4777 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_glue_register, cli_mgcp, io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, mgcp_rtp_glue, mgcp_tech, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().

04778 {
04779    if (!(sched = sched_context_create())) {
04780       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04781       return AST_MODULE_LOAD_FAILURE;
04782    }
04783 
04784    if (!(io = io_context_create())) {
04785       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04786       sched_context_destroy(sched);
04787       return AST_MODULE_LOAD_FAILURE;
04788    }
04789 
04790    if (reload_config(0))
04791       return AST_MODULE_LOAD_DECLINE;
04792 
04793    /* Make sure we can register our mgcp channel type */
04794    if (ast_channel_register(&mgcp_tech)) {
04795       ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04796       io_context_destroy(io);
04797       sched_context_destroy(sched);
04798       return AST_MODULE_LOAD_FAILURE;
04799    }
04800 
04801    ast_rtp_glue_register(&mgcp_rtp_glue);
04802    ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04803 
04804    /* And start the monitor for the first time */
04805    restart_monitor();
04806 
04807    return AST_MODULE_LOAD_SUCCESS;
04808 }

static int mgcp_alloc_pktcgate ( struct mgcp_subchannel sub  )  [static]

Definition at line 2403 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_pktccops_gate_alloc(), mgcp_subchannel::gate, cops_gate::gate_open, GATE_SET, mgcp_pktcgate_open(), mgcp_pktcgate_remove(), mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::sub, and cops_gate::tech_pvt.

Referenced by start_rtp().

02404 {
02405    struct mgcp_endpoint *p = sub->parent;
02406    sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
02407                8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
02408 
02409    if (!sub->gate) {
02410       return 0;
02411    }
02412    sub->gate->tech_pvt = sub;
02413    sub->gate->gate_open = &mgcp_pktcgate_open;
02414    return 1;
02415 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

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

01175 {
01176    int res = 0;
01177    struct mgcp_subchannel *sub = ast->tech_pvt;
01178    struct mgcp_endpoint *p = sub->parent;
01179 
01180    ast_mutex_lock(&sub->lock);
01181    sub->cxmode = MGCP_CX_SENDRECV;
01182    if (!sub->rtp) {
01183       start_rtp(sub);
01184    } else {
01185       transmit_modify_request(sub);
01186    }
01187    ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
01188          ast->name, p->name, p->parent->name, sub->id);
01189    if (ast->_state != AST_STATE_UP) {
01190       ast_setstate(ast, AST_STATE_UP);
01191       ast_debug(1, "mgcp_answer(%s)\n", ast->name);
01192       transmit_notify_request(sub, "");
01193       transmit_modify_request(sub);
01194    }
01195    ast_mutex_unlock(&sub->lock);
01196    return res;
01197 }

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

Definition at line 834 of file chan_mgcp.c.

References ast_channel::_state, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), mgcp_subchannel::callid, ast_channel::connected, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, ast_party_connected_line::id, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, ast_party_id::name, ast_channel::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, S_COR, start_rtp(), ast_party_name::str, ast_party_number::str, ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, ast_party_name::valid, ast_party_number::valid, and ast_channel::varshead.

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

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

References AST_DEVICE_INVALID, ast_mutex_lock, ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_gateway::name, and mgcp_gateway::next.

01360 {
01361    struct mgcp_gateway  *g;
01362    struct mgcp_endpoint *e = NULL;
01363    char *tmp, *endpt, *gw;
01364    int ret = AST_DEVICE_INVALID;
01365 
01366    endpt = ast_strdupa(data);
01367    if ((tmp = strchr(endpt, '@'))) {
01368       *tmp++ = '\0';
01369       gw = tmp;
01370    } else
01371       goto error;
01372 
01373    ast_mutex_lock(&gatelock);
01374    for (g = gateways; g; g = g->next) {
01375       if (strcasecmp(g->name, gw) == 0) {
01376          e = g->endpoints;
01377          break;
01378       }
01379    }
01380 
01381    if (!e)
01382       goto error;
01383 
01384    for (; e; e = e->next) {
01385       if (strcasecmp(e->name, endpt) == 0) {
01386          break;
01387       }
01388    }
01389 
01390    if (!e)
01391       goto error;
01392 
01393    /*
01394     * As long as the gateway/endpoint is valid, we'll
01395     * assume that the device is available and its state
01396     * can be tracked.
01397     */
01398    ret = AST_DEVICE_UNKNOWN;
01399 
01400 error:
01401    ast_mutex_unlock(&gatelock);
01402    return ret;
01403 }

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

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

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

static format_t mgcp_get_codec ( struct ast_channel chan  )  [static]

Definition at line 4425 of file chan_mgcp.c.

References mgcp_endpoint::capability, mgcp_subchannel::parent, mgcp_endpoint::sub, and ast_channel::tech_pvt.

04426 {
04427    struct mgcp_subchannel *sub = chan->tech_pvt;
04428    struct mgcp_endpoint *p = sub->parent;
04429    return p->capability;
04430 }

static enum ast_rtp_glue_result mgcp_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance **  instance 
) [static]

Definition at line 4398 of file chan_mgcp.c.

References ao2_ref, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, mgcp_endpoint::directmedia, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.

04399 {
04400    struct mgcp_subchannel *sub = NULL;
04401 
04402    if (!(sub = chan->tech_pvt) || !(sub->rtp))
04403       return AST_RTP_GLUE_RESULT_FORBID;
04404 
04405    *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
04406 
04407    if (sub->parent->directmedia)
04408       return AST_RTP_GLUE_RESULT_REMOTE;
04409    else
04410       return AST_RTP_GLUE_RESULT_LOCAL;
04411 }

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 919 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_pktccops_gate_alloc(), ast_rtp_instance_destroy(), ast_strlen_zero(), ast_verb, ast_channel::caller, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, cops_gate::deltimer, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, mgcp_subchannel::gate, GATE_ALLOC_PROGRESS, GATE_ALLOCATED, GATE_DEL, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, ast_party_caller::id, 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, ast_party_id::name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, mgcp_subchannel::rtp, S_COR, cops_gate::state, ast_party_name::str, ast_party_number::str, mgcp_endpoint::sub, cops_gate::tech_pvt, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), ast_party_name::valid, and ast_party_number::valid.

00920 {
00921    struct mgcp_subchannel *sub = ast->tech_pvt;
00922    struct mgcp_endpoint *p = sub->parent;
00923    struct ast_channel *bridged;
00924 
00925    ast_debug(1, "mgcp_hangup(%s)\n", ast->name);
00926    if (!ast->tech_pvt) {
00927       ast_debug(1, "Asked to hangup channel not connected\n");
00928       return 0;
00929    }
00930    if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
00931       ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
00932       return 0;
00933    }
00934    ast_mutex_lock(&sub->lock);
00935    ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
00936 
00937    if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
00938       /* check whether other channel is active. */
00939       if (!sub->next->owner) {
00940          if (p->dtmfmode & MGCP_DTMF_HYBRID) {
00941             p->dtmfmode &= ~MGCP_DTMF_INBAND;
00942          }
00943          ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
00944          ast_dsp_free(p->dsp);
00945          p->dsp = NULL;
00946       }
00947    }
00948 
00949    sub->owner = NULL;
00950 
00951    /* for deleting gate */
00952    if (p->pktcgatealloc && sub->gate) {
00953       sub->gate->gate_open = NULL;
00954       sub->gate->gate_remove = NULL;
00955       sub->gate->got_dq_gi = NULL;
00956       sub->gate->tech_pvt = NULL;
00957       if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) {
00958          ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL);
00959       } else {
00960          sub->gate->deltimer = time(NULL) + 5;
00961       }
00962       sub->gate = NULL;
00963    }
00964 
00965    if (!ast_strlen_zero(sub->cxident)) {
00966       transmit_connection_del(sub);
00967    }
00968    sub->cxident[0] = '\0';
00969    if ((sub == p->sub) && sub->next->owner) {
00970       if (p->hookstate == MGCP_OFFHOOK) {
00971          if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
00972             /* ncs fix! */
00973             bridged = ast_bridged_channel(sub->next->owner);
00974             transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"),
00975                S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
00976                S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
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             bridged = ast_bridged_channel(sub->next->owner);
00985             transmit_notify_request_with_callerid(p->sub, "L/rg",
00986                S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
00987                S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
00988          }
00989       }
00990 
00991    } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
00992       transmit_notify_request(sub, p->ncs ? "" : "L/v");
00993    } else if (p->hookstate == MGCP_OFFHOOK) {
00994       transmit_notify_request(sub, "L/ro");
00995    } else {
00996       transmit_notify_request(sub, "");
00997    }
00998 
00999    ast->tech_pvt = NULL;
01000    sub->alreadygone = 0;
01001    sub->outgoing = 0;
01002    sub->cxmode = MGCP_CX_INACTIVE;
01003    sub->callid[0] = '\0';
01004    if (p) {
01005       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
01006    }
01007    /* Reset temporary destination */
01008    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
01009    if (sub->rtp) {
01010       ast_rtp_instance_destroy(sub->rtp);
01011       sub->rtp = NULL;
01012    }
01013 
01014    ast_module_unref(ast_module_info->self);
01015 
01016    if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
01017       p->hidecallerid = 0;
01018       if (p->hascallwaiting && !p->callwaiting) {
01019          ast_verb(3, "Enabling call waiting on %s\n", ast->name);
01020          p->callwaiting = -1;
01021       }
01022       if (has_voicemail(p)) {
01023          ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
01024             ast->name, p->name, p->parent->name);
01025          transmit_notify_request(sub, "L/vmwi(+)");
01026       } else {
01027          ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
01028             ast->name, p->name, p->parent->name);
01029          transmit_notify_request(sub, "L/vmwi(-)");
01030       }
01031    }
01032    ast_mutex_unlock(&sub->lock);
01033    return 0;
01034 }

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

Definition at line 1437 of file chan_mgcp.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), control2str(), mgcp_subchannel::lock, LOG_WARNING, ast_channel::name, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().

01438 {
01439    struct mgcp_subchannel *sub = ast->tech_pvt;
01440    int res = 0;
01441 
01442    ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
01443       ind, control2str(ind), ast->name);
01444    ast_mutex_lock(&sub->lock);
01445    switch(ind) {
01446    case AST_CONTROL_RINGING:
01447 #ifdef DLINK_BUGGY_FIRMWARE   
01448       transmit_notify_request(sub, "rt");
01449 #else
01450       if (!sub->sdpsent) { /* will hide the inband progress!!! */
01451          transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt");
01452       }
01453 #endif
01454       break;
01455    case AST_CONTROL_BUSY:
01456       transmit_notify_request(sub, "L/bz");
01457       break;
01458    case AST_CONTROL_CONGESTION:
01459       transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
01460       break;
01461    case AST_CONTROL_HOLD:
01462       ast_moh_start(ast, data, NULL);
01463       break;
01464    case AST_CONTROL_UNHOLD:
01465       ast_moh_stop(ast);
01466       break;
01467    case AST_CONTROL_SRCUPDATE:
01468       ast_rtp_instance_update_source(sub->rtp);
01469       break;
01470    case AST_CONTROL_SRCCHANGE:
01471       ast_rtp_instance_change_source(sub->rtp);
01472       break;
01473    case AST_CONTROL_PROGRESS:
01474    case AST_CONTROL_PROCEEDING:
01475       transmit_modify_request(sub);
01476    case -1:
01477       transmit_notify_request(sub, "");
01478       break;
01479    default:
01480       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
01481       res = -1;
01482    }
01483    ast_mutex_unlock(&sub->lock);
01484    return res;
01485 }

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

Definition at line 1487 of file chan_mgcp.c.

References accountcode, mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, ast_party_caller::ani, 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_get_encoded_str(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_instance_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, ast_channel::caller, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, mgcp_endpoint::chanvars, 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, ast_variable::name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, ast_variable::next, ast_party_id::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, ast_party_number::str, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, and ast_channel::writeformat.

Referenced by handle_hd_hf(), and mgcp_request().

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

static int mgcp_pktcgate_open ( struct cops_gate gate  )  [static]

Definition at line 2390 of file chan_mgcp.c.

References ast_debug, ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::gate, cops_gate::gateid, mgcp_subchannel::lock, mgcp_subchannel::sdpsent, cops_gate::tech_pvt, and transmit_modify_with_sdp().

Referenced by mgcp_alloc_pktcgate().

02391 {
02392    struct mgcp_subchannel *sub = gate->tech_pvt;
02393    if (!sub) {
02394       return 1;
02395    }
02396    ast_mutex_lock(&sub->lock);
02397    ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
02398    if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
02399    ast_mutex_unlock(&sub->lock);
02400    return 1;
02401 }

static int mgcp_pktcgate_remove ( struct cops_gate gate  )  [static]

Definition at line 2367 of file chan_mgcp.c.

References AST_CAUSE_REQUESTED_CHAN_UNAVAIL, ast_channel_unlock, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), mgcp_subchannel::gate, GATE_CLOSED, cops_gate::gateid, mgcp_endpoint::hangupongateremove, mgcp_subchannel::lock, mgcp_subchannel::owner, mgcp_subchannel::parent, cops_gate::state, and cops_gate::tech_pvt.

Referenced by mgcp_alloc_pktcgate().

02368 {
02369    struct mgcp_subchannel *sub = gate->tech_pvt;
02370 
02371    if (!sub) {
02372       return 1;
02373    }
02374 
02375    ast_mutex_lock(&sub->lock);
02376    ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid);
02377    if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) {
02378       sub->gate = NULL;
02379       if (sub->owner) {
02380          ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
02381          ast_channel_unlock(sub->owner);
02382       }
02383    } else {
02384       sub->gate = NULL;
02385    }
02386    ast_mutex_unlock(&sub->lock);
02387    return 1;
02388 }

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

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

00709 {
00710    struct mgcp_message *msg;
00711    struct mgcp_message *cur;
00712    struct mgcp_gateway *gw;
00713    struct timeval now;
00714 
00715    if (!(msg = ast_malloc(sizeof(*msg) + len))) {
00716       return -1;
00717    }
00718    if (!(gw = ((p && p->parent) ? p->parent : NULL))) {
00719       ast_free(msg);
00720       return -1;
00721    }
00722 
00723    msg->owner_sub = sub;
00724    msg->owner_ep = p;
00725    msg->seqno = seqno;
00726    msg->next = NULL;
00727    msg->len = len;
00728    msg->retrans = 0;
00729    memcpy(msg->buf, data, msg->len);
00730 
00731    ast_mutex_lock(&gw->msgs_lock);
00732    for (cur = gw->msgs; cur && cur->next; cur = cur->next);
00733    if (cur) {
00734       cur->next = msg;
00735    } else {
00736       gw->msgs = msg;
00737    }
00738 
00739    now = ast_tvnow();
00740    msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS;
00741 
00742    if (gw->retransid == -1)
00743       gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
00744    ast_mutex_unlock(&gw->msgs_lock);
00745    __mgcp_xmit(gw, msg->buf, msg->len);
00746    /* XXX Should schedule retransmission XXX */
00747    return 0;
00748 }

static int mgcp_prune_realtime_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 3695 of file chan_mgcp.c.

References ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_strlen_zero(), mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, mgcp_gateway::endpoints, mgcp_subchannel::gate, mgcp_gateway::ha, mgcp_subchannel::lock, mgcp_endpoint::lock, MAX_SUBS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::realtime, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, and mgcp_endpoint::sub.

Referenced by do_monitor().

03696 {
03697    struct mgcp_endpoint *enext, *e;
03698    struct mgcp_subchannel *s, *sub;
03699    int i, prune = 1;
03700 
03701    if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) {
03702       ast_mutex_unlock(&g->msgs_lock);
03703       return 0;
03704    }
03705 
03706    for (e = g->endpoints; e; e = e->next) {
03707       ast_mutex_lock(&e->lock);
03708       if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) {
03709          prune = 0;
03710       } else if (e->rqnt_queue || e->cmd_queue) {
03711          prune = 0;
03712       }
03713       s = e->sub;
03714       for (i = 0; (i < MAX_SUBS) && s; i++) {
03715          ast_mutex_lock(&s->lock);
03716          if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) {
03717             prune = 0;
03718          } else if (s->cx_queue) {
03719             prune = 0;
03720          }
03721          s = s->next;
03722       }
03723    }
03724 
03725    for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) {
03726       for (i = 0; (i < MAX_SUBS) && sub; i++) {
03727          s = sub;
03728          sub = sub->next;
03729          ast_mutex_unlock(&s->lock);
03730          ast_mutex_unlock(&s->cx_queue_lock);
03731          if (prune) {
03732             ast_mutex_destroy(&s->lock);
03733             ast_mutex_destroy(&s->cx_queue_lock);
03734             free(s);
03735          }
03736       }
03737       ast_mutex_unlock(&e->lock);
03738       ast_mutex_unlock(&e->rqnt_queue_lock);
03739       ast_mutex_unlock(&e->cmd_queue_lock);
03740       if (prune) {
03741          ast_mutex_destroy(&e->lock);
03742          ast_mutex_destroy(&e->rqnt_queue_lock);
03743          ast_mutex_destroy(&e->cmd_queue_lock);
03744          free(e);
03745       }
03746    }
03747    if (prune) {
03748       ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name);
03749    }
03750    return prune;
03751 }

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

Definition at line 646 of file chan_mgcp.c.

References AST_FRAME_CONTROL, f, and mgcp_queue_frame().

Referenced by handle_hd_hf().

00647 {
00648    struct ast_frame f = { AST_FRAME_CONTROL, { control } };
00649    return mgcp_queue_frame(sub, &f);
00650 }

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

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

00613 {
00614    for (;;) {
00615       if (sub->owner) {
00616          if (!ast_channel_trylock(sub->owner)) {
00617             ast_queue_frame(sub->owner, f);
00618             ast_channel_unlock(sub->owner);
00619             break;
00620          } else {
00621             DEADLOCK_AVOIDANCE(&sub->lock);
00622          }
00623       } else {
00624          break;
00625       }
00626    }
00627 }

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

Definition at line 629 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(), handle_response(), and start_rtp().

00630 {
00631    for (;;) {
00632       if (sub->owner) {
00633          if (!ast_channel_trylock(sub->owner)) {
00634             ast_queue_hangup(sub->owner);
00635             ast_channel_unlock(sub->owner);
00636             break;
00637          } else {
00638             DEADLOCK_AVOIDANCE(&sub->lock);
00639          }
00640       } else {
00641          break;
00642       }
00643    }
00644 }

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

Definition at line 1230 of file chan_mgcp.c.

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

01231 {
01232    struct ast_frame *f;
01233    struct mgcp_subchannel *sub = ast->tech_pvt;
01234    ast_mutex_lock(&sub->lock);
01235    f = mgcp_rtp_read(sub);
01236    ast_mutex_unlock(&sub->lock);
01237    return f;
01238 }

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

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

04811 {
04812    static int deprecated = 0;
04813 
04814    if (e) {
04815       switch (cmd) {
04816       case CLI_INIT:
04817          e->command = "mgcp reload";
04818          e->usage =
04819             "Usage: mgcp reload\n"
04820             "       'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n";
04821          return NULL;
04822       case CLI_GENERATE:
04823          return NULL;
04824       }
04825    }
04826 
04827    if (!deprecated && a && a->argc > 0) {
04828       ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
04829       deprecated = 1;
04830    }
04831 
04832    ast_mutex_lock(&mgcp_reload_lock);
04833    if (mgcp_reloading) {
04834       ast_verbose("Previous mgcp reload not yet done\n");
04835    } else {
04836       mgcp_reloading = 1;
04837    }
04838    ast_mutex_unlock(&mgcp_reload_lock);
04839    restart_monitor();
04840    return CLI_SUCCESS;
04841 }

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

Definition at line 3902 of file chan_mgcp.c.

References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_getformatname_multiple(), 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, ast_channel::linkedid, 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().

03903 {
03904    format_t oldformat;
03905    struct mgcp_subchannel *sub;
03906    struct ast_channel *tmpc = NULL;
03907    char tmp[256];
03908    char *dest = data;
03909 
03910    oldformat = format;
03911    format &= capability;
03912    if (!format) {
03913       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
03914       /*return NULL;*/
03915    }
03916    ast_copy_string(tmp, dest, sizeof(tmp));
03917    if (ast_strlen_zero(tmp)) {
03918       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03919       return NULL;
03920    }
03921    if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) {
03922       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03923       *cause = AST_CAUSE_UNREGISTERED;
03924       return NULL;
03925    }
03926 
03927    ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
03928    ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03929          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03930    /* Must be busy */
03931    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03932       ((!sub->parent->callwaiting) && (sub->owner)) ||
03933        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03934       if (sub->parent->hookstate == MGCP_ONHOOK) {
03935          if (has_voicemail(sub->parent)) {
03936             transmit_notify_request(sub,"L/vmwi(+)");
03937          } else {
03938             transmit_notify_request(sub,"L/vmwi(-)");
03939          }
03940       }
03941       *cause = AST_CAUSE_BUSY;
03942       ast_mutex_unlock(&sub->lock);
03943       return NULL;
03944    }
03945    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
03946    ast_mutex_unlock(&sub->lock);
03947    if (!tmpc)
03948       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03949    restart_monitor();
03950    return tmpc;
03951 }

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

Definition at line 1199 of file chan_mgcp.c.

References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_instance_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().

01200 {
01201    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
01202    struct ast_frame *f;
01203 
01204    f = ast_rtp_instance_read(sub->rtp, 0);
01205    /* Don't send RFC2833 if we're not supposed to */
01206    if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
01207       return &ast_null_frame;
01208    if (sub->owner) {
01209       /* We already hold the channel lock */
01210       if (f->frametype == AST_FRAME_VOICE) {
01211          if (f->subclass.codec != sub->owner->nativeformats) {
01212             ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
01213             sub->owner->nativeformats = f->subclass.codec;
01214             ast_set_read_format(sub->owner, sub->owner->readformat);
01215             ast_set_write_format(sub->owner, sub->owner->writeformat);
01216          }
01217          /* Courtesy fearnor aka alex@pilosoft.com */
01218          if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
01219 #if 0
01220             ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
01221 #endif
01222             f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
01223          }
01224       }
01225    }
01226    return f;
01227 }

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

Definition at line 1297 of file chan_mgcp.c.

References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, 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.

01298 {
01299    struct mgcp_subchannel *sub = ast->tech_pvt;
01300    struct mgcp_endpoint *p = sub->parent;
01301    int res = 0;
01302 
01303    ast_mutex_lock(&sub->lock);
01304    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01305       ast_debug(1, "Sending DTMF using inband/hybrid\n");
01306       res = -1; /* Let asterisk play inband indications */
01307    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01308       ast_debug(1, "Sending DTMF using RFC2833");
01309       ast_rtp_instance_dtmf_begin(sub->rtp, digit);
01310    } else {
01311       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01312    }
01313    ast_mutex_unlock(&sub->lock);
01314 
01315    return res;
01316 }

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

Definition at line 1318 of file chan_mgcp.c.

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

01319 {
01320    struct mgcp_subchannel *sub = ast->tech_pvt;
01321    struct mgcp_endpoint *p = sub->parent;
01322    int res = 0;
01323    char tmp[4];
01324 
01325    ast_mutex_lock(&sub->lock);
01326    if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
01327       ast_debug(1, "Stopping DTMF using inband/hybrid\n");
01328       res = -1; /* Tell Asterisk to stop inband indications */
01329    } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
01330       ast_debug(1, "Stopping DTMF using RFC2833\n");
01331       if (sub->parent->ncs) {
01332          tmp[0] = digit;
01333          tmp[1] = '\0';
01334       } else {
01335          tmp[0] = 'D';
01336          tmp[1] = '/';
01337          tmp[2] = digit;
01338          tmp[3] = '\0';
01339       }
01340       transmit_notify_request(sub, tmp);
01341       ast_rtp_instance_dtmf_end(sub->rtp, digit);
01342    } else {
01343       ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
01344    }
01345    ast_mutex_unlock(&sub->lock);
01346 
01347    return res;
01348 }

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

Definition at line 4413 of file chan_mgcp.c.

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

04414 {
04415    /* XXX Is there such thing as video support with MGCP? XXX */
04416    struct mgcp_subchannel *sub;
04417    sub = chan->tech_pvt;
04418    if (sub && !sub->alreadygone) {
04419       transmit_modify_with_sdp(sub, rtp, codecs);
04420       return 0;
04421    }
04422    return -1;
04423 }

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

Definition at line 2941 of file chan_mgcp.c.

References ast_party_caller::ani, 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_valid(), 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_strdup, ast_strlen_zero(), ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, ast_channel::caller, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, ast_channel::dialed, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_party_caller::id, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, ast_party_dialed::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, ast_channel::rings, S_COR, start_rtp(), ast_party_number::str, ast_party_dialed::str, mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_notify_request(), and ast_party_number::valid.

Referenced by handle_hd_hf().

02942 {
02943    struct ast_channel *chan = data;
02944    struct mgcp_subchannel *sub = chan->tech_pvt;
02945    struct mgcp_endpoint *p = sub->parent;
02946    /* char exten[AST_MAX_EXTENSION] = ""; */
02947    int len = 0;
02948    int timeout = firstdigittimeout;
02949    int res= 0;
02950    int getforward = 0;
02951    int loop_pause = 100;
02952 
02953    len = strlen(p->dtmf_buf);
02954 
02955    while (len < AST_MAX_EXTENSION - 1) {
02956       ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name);
02957       res = 1;  /* Assume that we will get a digit */
02958       while (strlen(p->dtmf_buf) == len) {
02959          ast_safe_sleep(chan, loop_pause);
02960          timeout -= loop_pause;
02961          if (timeout <= 0){
02962             res = 0;
02963             break;
02964          }
02965          res = 1;
02966       }
02967 
02968       timeout = 0;
02969       len = strlen(p->dtmf_buf);
02970 
02971       if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) {
02972          /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02973          ast_indicate(chan, -1);
02974       } else {
02975          /* XXX Redundant?  We should already be playing dialtone */
02976          /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
02977          transmit_notify_request(sub, "L/dl");
02978       }
02979       if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02980          if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) {
02981             if (getforward) {
02982                /* Record this as the forwarding extension */
02983                ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
02984                ast_verb(3, "Setting call forward to '%s' on channel %s\n",
02985                      p->call_forward, chan->name);
02986                /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
02987                transmit_notify_request(sub, "L/sl");
02988                if (res)
02989                   break;
02990                usleep(500000);
02991                /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
02992                ast_indicate(chan, -1);
02993                sleep(1);
02994                memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
02995                /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
02996                transmit_notify_request(sub, "L/dl");
02997                len = 0;
02998                getforward = 0;
02999             } else {
03000                /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
03001                ast_indicate(chan, -1);
03002                ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
03003                chan->dialed.number.str = ast_strdup(p->dtmf_buf);
03004                memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03005                ast_set_callerid(chan,
03006                   p->hidecallerid ? "" : p->cid_num,
03007                   p->hidecallerid ? "" : p->cid_name,
03008                   chan->caller.ani.number.valid ? NULL : p->cid_num);
03009                ast_setstate(chan, AST_STATE_RING);
03010                /*dahdi_enable_ec(p);*/
03011                if (p->dtmfmode & MGCP_DTMF_HYBRID) {
03012                   p->dtmfmode |= MGCP_DTMF_INBAND;
03013                   ast_indicate(chan, -1);
03014                }
03015                res = ast_pbx_run(chan);
03016                if (res) {
03017                   ast_log(LOG_WARNING, "PBX exited non-zero\n");
03018                   /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
03019                   /*transmit_notify_request(p, "nbz", 1);*/
03020                   transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03021                }
03022                return NULL;
03023             }
03024          } else {
03025             /* It's a match, but they just typed a digit, and there is an ambiguous match,
03026                so just set the timeout to matchdigittimeout and wait some more */
03027             timeout = matchdigittimeout;
03028          }
03029       } else if (res == 0) {
03030          ast_debug(1, "not enough digits (and no ambiguous match)...\n");
03031          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
03032          transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03033          /*dahdi_wait_event(p->subs[index].zfd);*/
03034          ast_hangup(chan);
03035          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03036          return NULL;
03037       } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
03038          ast_verb(3, "Disabling call waiting on %s\n", chan->name);
03039          /* Disable call waiting if enabled */
03040          p->callwaiting = 0;
03041          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03042          transmit_notify_request(sub, "L/sl");
03043          len = 0;
03044          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03045          timeout = firstdigittimeout;
03046       } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
03047          /* Scan all channels and see if any there
03048           * ringing channqels with that have call groups
03049           * that equal this channels pickup group
03050           */
03051          if (ast_pickup_call(chan)) {
03052             ast_log(LOG_WARNING, "No call pickup possible...\n");
03053             /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
03054             transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03055          }
03056          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03057          ast_hangup(chan);
03058          return NULL;
03059       } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
03060          ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
03061          /* Disable Caller*ID if enabled */
03062          p->hidecallerid = 1;
03063          ast_set_callerid(chan, "", "", NULL);
03064          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03065          transmit_notify_request(sub, "L/sl");
03066          len = 0;
03067          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03068          timeout = firstdigittimeout;
03069       } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
03070          res = 0;
03071          if (!ast_strlen_zero(p->lastcallerid)) {
03072             res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
03073          }
03074          if (!res)
03075             /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03076             transmit_notify_request(sub, "L/sl");
03077          break;
03078       } else if (!strcmp(p->dtmf_buf, "*78")) {
03079          /* Do not disturb */
03080          ast_verb(3, "Enabled DND on channel %s\n", chan->name);
03081          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03082          transmit_notify_request(sub, "L/sl");
03083          p->dnd = 1;
03084          getforward = 0;
03085          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03086          len = 0;
03087       } else if (!strcmp(p->dtmf_buf, "*79")) {
03088          /* Do not disturb */
03089          ast_verb(3, "Disabled DND on channel %s\n", chan->name);
03090          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03091          transmit_notify_request(sub, "L/sl");
03092          p->dnd = 0;
03093          getforward = 0;
03094          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03095          len = 0;
03096       } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
03097          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03098          transmit_notify_request(sub, "L/sl");
03099          getforward = 1;
03100          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03101          len = 0;
03102       } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
03103          ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name);
03104          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03105          transmit_notify_request(sub, "L/sl");
03106          memset(p->call_forward, 0, sizeof(p->call_forward));
03107          getforward = 0;
03108          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03109          len = 0;
03110       } else if (ast_parking_ext_valid(p->dtmf_buf, chan, chan->context) &&
03111          sub->next->owner && ast_bridged_channel(sub->next->owner)) {
03112          /* This is a three way call, the main call being a real channel,
03113             and we're parking the first call. */
03114          ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
03115          ast_verb(3, "Parking call to '%s'\n", chan->name);
03116          break;
03117       } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
03118          ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
03119          res = ast_db_put("blacklist", p->lastcallerid, "1");
03120          if (!res) {
03121             /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03122             transmit_notify_request(sub, "L/sl");
03123             memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03124             len = 0;
03125          }
03126       } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
03127          ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
03128          /* Enable Caller*ID if enabled */
03129          p->hidecallerid = 0;
03130          ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
03131          /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
03132          transmit_notify_request(sub, "L/sl");
03133          len = 0;
03134          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03135          timeout = firstdigittimeout;
03136       } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1,
03137          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
03138          && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
03139          ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf,
03140             S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
03141             chan->context);
03142          break;
03143       }
03144       if (!timeout)
03145          timeout = gendigittimeout;
03146       if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf))
03147          /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
03148          ast_indicate(chan, -1);
03149    }
03150 #if 0
03151    for (;;) {
03152       res = ast_waitfordigit(chan, to);
03153       if (!res) {
03154          ast_debug(1, "Timeout...\n");
03155          break;
03156       }
03157       if (res < 0) {
03158          ast_debug(1, "Got hangup...\n");
03159          ast_hangup(chan);
03160          break;
03161       }
03162       exten[pos++] = res;
03163       if (!ast_ignore_pattern(chan->context, exten))
03164          ast_indicate(chan, -1);
03165       if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
03166          if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
03167             to = 3000;
03168          else
03169             to = 8000;
03170       } else
03171          break;
03172    }
03173    if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
03174       ast_copy_string(chan->exten, exten, sizeof(chan->exten)1);
03175       if (!p->rtp) {
03176          start_rtp(p);
03177       }
03178       ast_setstate(chan, AST_STATE_RING);
03179       chan->rings = 1;
03180       if (ast_pbx_run(chan)) {
03181          ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
03182       } else {
03183          memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03184          return NULL;
03185       }
03186    }
03187 #endif
03188    ast_hangup(chan);
03189    memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
03190    return NULL;
03191 }

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

Definition at line 1240 of file chan_mgcp.c.

References ast_debug, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::codec, ast_frame::frametype, mgcp_subchannel::gate, GATE_ALLOCATED, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, cops_gate::state, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, transmit_modify_with_sdp(), and ast_channel::writeformat.

01241 {
01242    struct mgcp_subchannel *sub = ast->tech_pvt;
01243    int res = 0;
01244    char buf[256];
01245 
01246    if (frame->frametype != AST_FRAME_VOICE) {
01247       if (frame->frametype == AST_FRAME_IMAGE)
01248          return 0;
01249       else {
01250          ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
01251          return 0;
01252       }
01253    } else {
01254       if (!(frame->subclass.codec & ast->nativeformats)) {
01255          ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
01256             ast_getformatname(frame->subclass.codec),
01257             ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
01258             ast_getformatname(ast->readformat),
01259             ast_getformatname(ast->writeformat));
01260          /* return -1; */
01261       }
01262    }
01263    if (sub) {
01264       ast_mutex_lock(&sub->lock);
01265       if (!sub->sdpsent && sub->gate) {
01266          if (sub->gate->state == GATE_ALLOCATED) {
01267             ast_debug(1, "GATE ALLOCATED, sending sdp\n");
01268             transmit_modify_with_sdp(sub, NULL, 0);
01269          }
01270       }
01271       if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
01272          if (sub->rtp) {
01273             res =  ast_rtp_instance_write(sub->rtp, frame);
01274          }
01275       }
01276       ast_mutex_unlock(&sub->lock);
01277    }
01278    return res;
01279 }

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

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

03605 {
03606    struct mgcp_request req;
03607    struct sockaddr_in sin;
03608    struct mgcp_subchannel *sub;
03609    int res;
03610    socklen_t len;
03611    int result;
03612    int ident;
03613    len = sizeof(sin);
03614    memset(&req, 0, sizeof(req));
03615    res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
03616    if (res < 0) {
03617       if (errno != ECONNREFUSED)
03618          ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
03619       return 1;
03620    }
03621    req.data[res] = '\0';
03622    req.len = res;
03623    ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03624    parse(&req);
03625    if (req.headers < 1) {
03626       /* Must have at least one header */
03627       return 1;
03628    }
03629    if (ast_strlen_zero(req.identifier)) {
03630       ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr));
03631       return 1;
03632    }
03633 
03634    if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
03635       if (result < 200) {
03636          ast_debug(1, "Ignoring provisional response on transaction %d\n", ident);
03637          return 1;
03638       }
03639       /* Try to find who this message is for, if it's important */
03640       sub = find_subchannel_and_lock(NULL, ident, &sin);
03641       if (sub) {
03642          struct mgcp_gateway *gw = sub->parent->parent;
03643          struct mgcp_message *cur, *prev;
03644 
03645          ast_mutex_unlock(&sub->lock);
03646          ast_mutex_lock(&gw->msgs_lock);
03647          for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
03648             if (cur->seqno == ident) {
03649                ast_debug(1, "Got response back on transaction %d\n", ident);
03650                if (prev)
03651                   prev->next = cur->next;
03652                else
03653                   gw->msgs = cur->next;
03654                break;
03655             }
03656          }
03657 
03658          /* stop retrans timer if the queue is empty */
03659          if (!gw->msgs) {
03660             AST_SCHED_DEL(sched, gw->retransid);
03661          }
03662 
03663          ast_mutex_unlock(&gw->msgs_lock);
03664          if (cur) {
03665             handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
03666             ast_free(cur);
03667             return 1;
03668          }
03669 
03670          ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
03671             gw->name, ident);
03672       }
03673    } else {
03674       if (ast_strlen_zero(req.endpoint) ||
03675          ast_strlen_zero(req.version) ||
03676          ast_strlen_zero(req.verb)) {
03677          ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
03678          return 1;
03679       }
03680       /* Process request, with iflock held */
03681       sub = find_subchannel_and_lock(req.endpoint, 0, &sin);
03682       if (sub) {
03683          /* look first to find a matching response in the queue */
03684          if (!find_and_retrans(sub, &req))
03685             /* pass the request off to the currently mastering subchannel */
03686             handle_request(sub, &req, &sin);
03687          ast_mutex_unlock(&sub->lock);
03688       }
03689    }
03690    return 1;
03691 }

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

Definition at line 481 of file chan_mgcp.c.

00482 {
00483    /* This module does not handle MWI in an event-based manner.  However, it
00484     * subscribes to MWI for each mailbox that is configured so that the core
00485     * knows that we care about it.  Then, chan_mgcp will get the MWI from the
00486     * event cache instead of checking the mailbox directly. */
00487 }

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1851 of file chan_mgcp.c.

References ast_debug, ast_log(), ast_strlen_zero(), 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, mgcp_request::verb, and mgcp_request::version.

Referenced by acf_jabberreceive_read(), acf_meetme_info(), add_agent(), app_exec(), aqm_exec(), ast_parse_allow_disallow(), astman_get_variables(), celgenuserevent_exec(), chanspy_exec(), conf_exec(), conf_run(), confbridge_exec(), config_function_read(), cut_internal(), dahdi_accept_r2_call_exec(), dahdi_send_callrerouting_facility_exec(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), extenspy_exec(), find_conf(), function_agent(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), mgcpsock_read(), mixmonitor_exec(), originate_exec(), oss_call(), oss_request(), page_exec(), park_call_exec(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_waitexten(), pickupchan_exec(), play_moh_exec(), pqm_exec(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), rcvfax_exec(), receivefax_exec(), record_exec(), reload_single_member(), retrydial_exec(), rqm_exec(), saycountedadj_exec(), saycountednoun_exec(), sayunixtime_exec(), sendfax_exec(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), srv_result_read(), start_moh_exec(), start_monitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), and zapateller_exec().

01852 {
01853    /* Divide fields by NULL's */
01854    char *c;
01855    int f = 0;
01856    c = req->data;
01857 
01858    /* First header starts immediately */
01859    req->header[f] = c;
01860    for (; *c; c++) {
01861       if (*c == '\n') {
01862          /* We've got a new header */
01863          *c = 0;
01864          ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f]));
01865          if (ast_strlen_zero(req->header[f])) {
01866             /* Line by itself means we're now in content */
01867             c++;
01868             break;
01869          }
01870          if (f >= MGCP_MAX_HEADERS - 1) {
01871             ast_log(LOG_WARNING, "Too many MGCP headers...\n");
01872          } else {
01873             f++;
01874          }
01875          req->header[f] = c + 1;
01876       } else if (*c == '\r') {
01877          /* Ignore but eliminate \r's */
01878          *c = 0;
01879       }
01880    }
01881    /* Check for last header */
01882    if (!ast_strlen_zero(req->header[f])) {
01883       f++;
01884    }
01885    req->headers = f;
01886    /* Now we process any mime content */
01887    f = 0;
01888    req->line[f] = c;
01889    for (; *c; c++) {
01890       if (*c == '\n') {
01891          /* We've got a new line */
01892          *c = 0;
01893          ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f]));
01894          if (f >= MGCP_MAX_LINES - 1) {
01895             ast_log(LOG_WARNING, "Too many SDP lines...\n");
01896          } else {
01897             f++;
01898          }
01899          req->line[f] = c + 1;
01900       } else if (*c == '\r') {
01901          /* Ignore and eliminate \r's */
01902          *c = 0;
01903       }
01904    }
01905    /* Check for last line */
01906    if (!ast_strlen_zero(req->line[f])) {
01907       f++;
01908    }
01909    req->lines = f;
01910    /* Parse up the initial header */
01911    c = req->header[0];
01912    while (*c && *c < 33) c++;
01913    /* First the verb */
01914    req->verb = c;
01915    while (*c && (*c > 32)) c++;
01916    if (*c) {
01917       *c = '\0';
01918       c++;
01919       while (*c && (*c < 33)) c++;
01920       req->identifier = c;
01921       while (*c && (*c > 32)) c++;
01922       if (*c) {
01923          *c = '\0';
01924          c++;
01925          while (*c && (*c < 33)) c++;
01926          req->endpoint = c;
01927          while (*c && (*c > 32)) c++;
01928          if (*c) {
01929             *c = '\0';
01930             c++;
01931             while (*c && (*c < 33)) c++;
01932             req->version = c;
01933             while (*c && (*c > 32)) c++;
01934             while (*c && (*c < 33)) c++;
01935             while (*c && (*c > 32)) c++;
01936             *c = '\0';
01937          }
01938       }
01939    }
01940 
01941    ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
01942          req->verb, req->identifier, req->endpoint, req->version);
01943    ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines);
01944    if (*c) {
01945       ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
01946    }
01947 }

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

Definition at line 1949 of file chan_mgcp.c.

References ahp, ast_debug, ast_getformatname_multiple(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_formats(), ast_rtp_codecs_payloads_clear(), ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_sockaddr_from_sin, ast_strdupa, ast_strlen_zero(), capability, mgcp_endpoint::capability, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, 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().

01950 {
01951    char *m;
01952    char *c;
01953    char *a;
01954    char host[258];
01955    int len;
01956    int portno;
01957    format_t peercapability;
01958    int peerNonCodecCapability;
01959    struct sockaddr_in sin;
01960    struct ast_sockaddr sin_tmp;
01961    char *codecs;
01962    struct ast_hostent ahp; struct hostent *hp;
01963    int codec, codec_count=0;
01964    int iterator;
01965    struct mgcp_endpoint *p = sub->parent;
01966    char tmp1[256], tmp2[256], tmp3[256];
01967 
01968    /* Get codec and RTP info from SDP */
01969    m = get_sdp(req, "m");
01970    c = get_sdp(req, "c");
01971    if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
01972       ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
01973       return -1;
01974    }
01975    if (sscanf(c, "IN IP4 %256s", host) != 1) {
01976       ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
01977       return -1;
01978    }
01979    /* XXX This could block for a long time, and block the main thread! XXX */
01980    hp = ast_gethostbyname(host, &ahp);
01981    if (!hp) {
01982       ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
01983       return -1;
01984    }
01985    if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) {
01986       ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
01987       return -1;
01988    }
01989    sin.sin_family = AF_INET;
01990    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
01991    sin.sin_port = htons(portno);
01992    ast_sockaddr_from_sin(&sin_tmp, &sin);
01993    ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
01994    ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01995    /* Scan through the RTP payload types specified in a "m=" line: */
01996    ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
01997    codecs = ast_strdupa(m + len);
01998    while (!ast_strlen_zero(codecs)) {
01999       if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
02000          if (codec_count) {
02001             break;
02002          }
02003          ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
02004          return -1;
02005       }
02006       ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec);
02007       codec_count++;
02008       codecs += len;
02009    }
02010 
02011    /* Next, scan through each "a=rtpmap:" line, noting each */
02012    /* specified RTP payload type (with corresponding MIME subtype): */
02013    sdpLineNum_iterator_init(&iterator);
02014    while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
02015       char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
02016       if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2)
02017          continue;
02018       /* Note: should really look at the 'freq' and '#chans' params too */
02019       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
02020    }
02021 
02022    /* Now gather all of the codecs that were asked for: */
02023    ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability);
02024    p->capability = capability & peercapability;
02025    ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
02026       ast_getformatname_multiple(tmp1, sizeof(tmp1), capability),
02027       ast_getformatname_multiple(tmp2, sizeof(tmp2), peercapability),
02028       ast_getformatname_multiple(tmp3, sizeof(tmp3), p->capability));
02029    ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
02030       nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
02031    if (!p->capability) {
02032       ast_log(LOG_WARNING, "No compatible codecs!\n");
02033       return -1;
02034    }
02035    return 0;
02036 }

static void prune_gateways ( void   )  [static]

Definition at line 4527 of file chan_mgcp.c.

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

Referenced by unload_module().

04528 {
04529    struct mgcp_gateway *g, *z, *r;
04530    struct mgcp_endpoint *e, *p, *t;
04531 
04532    ast_mutex_lock(&gatelock);
04533 
04534    /* prune gateways */
04535    for (z = NULL, g = gateways; g;) {
04536       /* prune endpoints */
04537       for (p = NULL, e = g->endpoints; e; ) {
04538          if (!g->realtime && (e->delme || g->delme)) {
04539             t = e;
04540             e = e->next;
04541             if (!p)
04542                g->endpoints = e;
04543             else
04544                p->next = e;
04545             destroy_endpoint(t);
04546          } else {
04547             p = e;
04548             e = e->next;
04549          }
04550       }
04551 
04552       if (g->delme) {
04553          r = g;
04554          g = g->next;
04555          if (!z)
04556             gateways = g;
04557          else
04558             z->next = g;
04559 
04560          destroy_gateway(r);
04561       } else {
04562          z = g;
04563          g = g->next;
04564       }
04565    }
04566 
04567    ast_mutex_unlock(&gatelock);
04568 }

static int reload ( void   )  [static]

Definition at line 4843 of file chan_mgcp.c.

References mgcp_reload().

04844 {
04845    mgcp_reload(NULL, 0, NULL);
04846    return 0;
04847 }

static int reload_config ( int  reload  )  [static]

Definition at line 4602 of file chan_mgcp.c.

References ahp, ast_config_load, ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_variable_browse(), bindaddr, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, default_jbconf, dtmfmode, format, global_jbconf, hp, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, ourhost, and ast_variable::value.

04603 {
04604    struct ast_config *cfg;
04605    struct ast_variable *v;
04606    struct mgcp_gateway *g;
04607    struct mgcp_endpoint *e;
04608    char *cat;
04609    struct ast_hostent ahp;
04610    struct hostent *hp;
04611    int format;
04612    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04613    
04614    if (gethostname(ourhost, sizeof(ourhost)-1)) {
04615       ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
04616       return 0;
04617    }
04618    cfg = ast_config_load(config, config_flags);
04619 
04620    /* We *must* have a config file otherwise stop immediately */
04621    if (!cfg) {
04622       ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
04623       return 0;
04624    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
04625       return 0;
04626    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
04627       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
04628       return 0;
04629    }
04630 
04631    memset(&bindaddr, 0, sizeof(bindaddr));
04632    dtmfmode = 0;
04633 
04634    /* Copy the default jb config over global_jbconf */
04635    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04636 
04637    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
04638       /* handle jb conf */
04639       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04640          continue;
04641       }
04642 
04643       /* Create the interface list */
04644       if (!strcasecmp(v->name, "bindaddr")) {
04645          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04646             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04647          } else {
04648             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04649          }
04650       } else if (!strcasecmp(v->name, "allow")) {
04651          format = ast_getformatbyname(v->value);
04652          if (format < 1) {
04653             ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
04654          } else {
04655             capability |= format;
04656          }
04657       } else if (!strcasecmp(v->name, "disallow")) {
04658          format = ast_getformatbyname(v->value);
04659          if (format < 1) {
04660             ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
04661          } else {
04662             capability &= ~format;
04663          }
04664       } else if (!strcasecmp(v->name, "tos")) {
04665          if (ast_str2tos(v->value, &qos.tos)) {
04666              ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
04667          }
04668       } else if (!strcasecmp(v->name, "tos_audio")) {
04669          if (ast_str2tos(v->value, &qos.tos_audio))
04670              ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04671       } else if (!strcasecmp(v->name, "cos")) {
04672          if (ast_str2cos(v->value, &qos.cos))
04673              ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
04674       } else if (!strcasecmp(v->name, "cos_audio")) {
04675          if (ast_str2cos(v->value, &qos.cos_audio))
04676              ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
04677       } else if (!strcasecmp(v->name, "port")) {
04678          if (sscanf(v->value, "%5d", &ourport) == 1) {
04679             bindaddr.sin_port = htons(ourport);
04680          } else {
04681             ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
04682          }
04683       } else if (!strcasecmp(v->name, "firstdigittimeout")) {
04684          firstdigittimeout = atoi(v->value);
04685       } else if (!strcasecmp(v->name, "gendigittimeout")) {
04686          gendigittimeout = atoi(v->value);
04687       } else if (!strcasecmp(v->name, "matchdigittimeout")) {
04688          matchdigittimeout = atoi(v->value);
04689       }
04690    }
04691 
04692    /* mark existing entries for deletion */
04693    ast_mutex_lock(&gatelock);
04694    for (g = gateways; g; g = g->next) {
04695       g->delme = 1;
04696       for (e = g->endpoints; e; e = e->next) {
04697          e->delme = 1;
04698       }
04699    }
04700    ast_mutex_unlock(&gatelock);
04701 
04702    for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
04703       if (strcasecmp(cat, "general")) {
04704          ast_mutex_lock(&gatelock);
04705          if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) {
04706             ast_verb(3, "Added gateway '%s'\n", g->name);
04707             g->next = gateways;
04708             gateways = g;
04709          }
04710          ast_mutex_unlock(&gatelock);
04711 
04712          /* FS: process queue and IO */
04713          if (monitor_thread == pthread_self()) {
04714             if (sched) ast_sched_runq(sched);
04715             if (io) ast_io_wait(io, 10);
04716          }
04717       }
04718    }
04719 
04720    /* prune deleted entries etc. */
04721    prune_gateways();
04722 
04723    if (ntohl(bindaddr.sin_addr.s_addr)) {
04724       memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
04725    } else {
04726       hp = ast_gethostbyname(ourhost, &ahp);
04727       if (!hp) {
04728          ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
04729          ast_config_destroy(cfg);
04730          return 0;
04731       }
04732       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04733    }
04734    if (!ntohs(bindaddr.sin_port))
04735       bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
04736    bindaddr.sin_family = AF_INET;
04737    ast_mutex_lock(&netlock);
04738    if (mgcpsock > -1)
04739       close(mgcpsock);
04740 
04741    if (mgcpsock_read_id != NULL)
04742       ast_io_remove(io, mgcpsock_read_id);
04743    mgcpsock_read_id = NULL;
04744 
04745    mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
04746    if (mgcpsock < 0) {
04747       ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
04748    } else {
04749       if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04750          ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04751             ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04752                strerror(errno));
04753          close(mgcpsock);
04754          mgcpsock = -1;
04755       } else {
04756          ast_verb(2, "MGCP Listening on %s:%d\n",
04757                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04758          ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP");
04759       }
04760    }
04761    ast_mutex_unlock(&netlock);
04762    ast_config_destroy(cfg);
04763 
04764    /* send audit only to the new endpoints */
04765    for (g = gateways; g; g = g->next) {
04766       for (e = g->endpoints; e && e->needaudit; e = e->next) {
04767          e->needaudit = 0;
04768          transmit_audit_endpoint(e);
04769          ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
04770       }
04771    }
04772 
04773    return 0;
04774 }

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

Definition at line 2132 of file chan_mgcp.c.

References init_req(), and oseq.

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

02133 {
02134    memset(req, 0, sizeof(struct mgcp_request));
02135    oseq++;
02136    if (oseq > 999999999) {
02137       oseq = 1;
02138    }
02139    init_req(p, req, verb);
02140    return 0;
02141 }

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

Definition at line 555 of file chan_mgcp.c.

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

Referenced by find_and_retrans().

00556 {
00557    struct mgcp_endpoint *p = sub->parent;
00558    int res;
00559    ast_debug(1, "Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00560    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00561    if (res > 0)
00562       res = 0;
00563    return res;
00564 }

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

Definition at line 2125 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_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sdp(), transmit_response_with_sip_etag(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), update_connectedline(), and update_redirecting().

02126 {
02127    memset(resp, 0, sizeof(*resp));
02128    init_resp(resp, msg, req, msgrest);
02129    return 0;
02130 }

static int restart_monitor ( void   )  [static]

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

03874 {
03875    /* If we're supposed to be stopped -- stay stopped */
03876    if (monitor_thread == AST_PTHREADT_STOP)
03877       return 0;
03878    if (ast_mutex_lock(&monlock)) {
03879       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03880       return -1;
03881    }
03882    if (monitor_thread == pthread_self()) {
03883       ast_mutex_unlock(&monlock);
03884       ast_log(LOG_WARNING, "Cannot kill myself\n");
03885       return -1;
03886    }
03887    if (monitor_thread != AST_PTHREADT_NULL) {
03888       /* Wake up the thread */
03889       pthread_kill(monitor_thread, SIGURG);
03890    } else {
03891       /* Start a new monitor */
03892       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03893          ast_mutex_unlock(&monlock);
03894          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03895          return -1;
03896       }
03897    }
03898    ast_mutex_unlock(&monlock);
03899    return 0;
03900 }

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

Definition at line 652 of file chan_mgcp.c.

References __mgcp_xmit(), ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_message::buf, handle_response(), mgcp_message::len, LOG_WARNING, MAX_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_message::retrans, mgcp_gateway::retransid, and mgcp_message::seqno.

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

00653 {
00654    struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
00655    struct mgcp_message *cur, *exq = NULL, *w, *prev;
00656    int res = 0;
00657 
00658    /* find out expired msgs */
00659    ast_mutex_lock(&gw->msgs_lock);
00660 
00661    for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
00662       if (cur->retrans < MAX_RETRANS) {
00663          cur->retrans++;
00664          ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n",
00665             cur->retrans, cur->seqno, gw->name);
00666          __mgcp_xmit(gw, cur->buf, cur->len);
00667       } else {
00668          if (prev)
00669             prev->next = cur->next;
00670          else
00671             gw->msgs = cur->next;
00672 
00673          ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
00674             cur->seqno, gw->name);
00675 
00676          w = cur;
00677 
00678          if (exq) {
00679             w->next = exq;
00680          } else {
00681             w->next = NULL;
00682          }
00683          exq = w;
00684       }
00685    }
00686 
00687    if (!gw->msgs) {
00688       gw->retransid = -1;
00689       res = 0;
00690    } else {
00691       res = 1;
00692    }
00693    ast_mutex_unlock(&gw->msgs_lock);
00694 
00695    while (exq) {
00696       cur = exq;
00697       /* time-out transaction */
00698       handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
00699       exq = exq->next;
00700       ast_free(cur);
00701    }
00702 
00703    return res;
00704 }

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1593 of file chan_mgcp.c.

Referenced by process_sdp().

01594 {
01595    *iterator = 0;
01596 }

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

Definition at line 751 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, 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(), mgcp_endpoint::ncs, mgcp_request::next, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.

Referenced by transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), 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_state_notify(), and update_connectedline().

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

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

Definition at line 566 of file chan_mgcp.c.

References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), 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_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sdp(), transmit_response_with_sip_etag(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), update_connectedline(), and update_redirecting().

00567 {
00568    struct mgcp_endpoint *p = sub->parent;
00569    int res;
00570    ast_debug(1, "Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00571    res = __mgcp_xmit(p->parent, req->data, req->len);
00572    if (res > 0)
00573       res = 0;
00574    return res;
00575 }

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2908 of file chan_mgcp.c.

References ast_channel_set_fd(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_destroy(), ast_rtp_instance_fd(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, ast_sockaddr_from_sin, bindaddr, mgcp_subchannel::callid, mgcp_subchannel::gate, mgcp_subchannel::lock, mgcp_alloc_pktcgate(), mgcp_queue_hangup(), mgcp_subchannel::nat, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, qos, mgcp_subchannel::rtp, transmit_connect(), 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().

02909 {
02910    struct ast_sockaddr bindaddr_tmp;
02911 
02912    ast_mutex_lock(&sub->lock);
02913    /* check again to be on the safe side */
02914    if (sub->rtp) {
02915       ast_rtp_instance_destroy(sub->rtp);
02916       sub->rtp = NULL;
02917    }
02918    /* Allocate the RTP now */
02919    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
02920    sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
02921    if (sub->rtp && sub->owner)
02922       ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
02923    if (sub->rtp) {
02924       ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
02925       ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
02926    }
02927    /* Make a call*ID */
02928    snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02929    /* Transmit the connection create */
02930    if(!sub->parent->pktcgatealloc) {
02931       transmit_connect_with_sdp(sub, NULL);
02932    } else {
02933       transmit_connect(sub);
02934       sub->gate = NULL;
02935       if(!mgcp_alloc_pktcgate(sub))
02936          mgcp_queue_hangup(sub);
02937    }
02938    ast_mutex_unlock(&sub->lock);
02939 }

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

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

02621 {
02622    struct mgcp_request resp;
02623    reqprep(&resp, p, "AUEP");
02624    /* removed unknown param VS */
02625    /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
02626    add_header(&resp, "F", "A");
02627    /* fill in new fields */
02628    resp.cmd = MGCP_CMD_AUEP;
02629    resp.trid = oseq;
02630    return send_request(p, NULL, &resp, oseq);
02631 }

static int transmit_connect ( struct mgcp_subchannel sub  )  [static]

Definition at line 2417 of file chan_mgcp.c.

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

Referenced by skinny_unhold(), and start_rtp().

02418 {
02419    struct mgcp_request resp;
02420    char local[256];
02421    char tmp[80];
02422    format_t x;
02423    struct mgcp_endpoint *p = sub->parent;
02424 
02425    ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
02426 
02427    for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02428       if (p->capability & x) {
02429          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
02430          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02431       }
02432    }
02433 
02434    ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02435           p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02436    sub->sdpsent = 0;
02437    reqprep(&resp, p, "CRCX");
02438    add_header(&resp, "C", sub->callid);
02439    add_header(&resp, "L", local);
02440    add_header(&resp, "M", "inactive");
02441    /* X header should not be sent. kept for compatibility */
02442    add_header(&resp, "X", sub->txident);
02443    /*add_header(&resp, "S", "");*/
02444    /* fill in new fields */
02445    resp.cmd = MGCP_CMD_CRCX;
02446    resp.trid = oseq;
02447    return send_request(p, sub, &resp, oseq);
02448 }

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

Definition at line 2322 of file chan_mgcp.c.

References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.

Referenced by start_rtp().

02323 {
02324    struct mgcp_request resp;
02325    char local[256];
02326    char tmp[80];
02327    int x;
02328    struct mgcp_endpoint *p = sub->parent;
02329 
02330    ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02331        p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02332 
02333    ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
02334 
02335    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02336       if (!(x & AST_FORMAT_AUDIO_MASK)) {
02337          /* No longer contiguous */
02338          continue;
02339       }
02340       if (p->capability & x) {
02341          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
02342          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02343       }
02344    }
02345 
02346    if (sub->gate) {
02347       if(sub->gate->state == GATE_ALLOCATED) {
02348          snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02349          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02350       }
02351    }
02352    sub->sdpsent = 1;
02353    reqprep(&resp, p, "CRCX");
02354    add_header(&resp, "C", sub->callid);
02355    add_header(&resp, "L", local);
02356    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02357    /* X header should not be sent. kept for compatibility */
02358    add_header(&resp, "X", sub->txident);
02359    /*add_header(&resp, "S", "");*/
02360    add_sdp(&resp, sub, rtp);
02361    /* fill in new fields */
02362    resp.cmd = MGCP_CMD_CRCX;
02363    resp.trid = oseq;
02364    return send_request(p, sub, &resp, oseq);
02365 }

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

Definition at line 2633 of file chan_mgcp.c.

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

02634 {
02635    struct mgcp_endpoint *p = sub->parent;
02636    struct mgcp_request resp;
02637 
02638    ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02639       sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02640    reqprep(&resp, p, "DLCX");
02641    /* check if call id is avail */
02642    if (sub->callid[0])
02643       add_header(&resp, "C", sub->callid);
02644    /* X header should not be sent. kept for compatibility */
02645    add_header(&resp, "X", sub->txident);
02646    /* check if cxident is avail */
02647    if (sub->cxident[0])
02648       add_header(&resp, "I", sub->cxident);
02649    /* fill in new fields */
02650    resp.cmd = MGCP_CMD_DLCX;
02651    resp.trid = oseq;
02652    return send_request(p, sub, &resp, oseq);
02653 }

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

Definition at line 2655 of file chan_mgcp.c.

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

Referenced by handle_response().

02656 {
02657    struct mgcp_request resp;
02658 
02659    ast_debug(3, "Delete connection %s %s@%s on callid: %s\n",
02660       cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02661    reqprep(&resp, p, "DLCX");
02662    /* check if call id is avail */
02663    if (callid && *callid)
02664       add_header(&resp, "C", callid);
02665    /* check if cxident is avail */
02666    if (cxident && *cxident)
02667       add_header(&resp, "I", cxident);
02668    /* fill in new fields */
02669    resp.cmd = MGCP_CMD_DLCX;
02670    resp.trid = oseq;
02671    return send_request(p, p->sub, &resp, oseq);
02672 }

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2521 of file chan_mgcp.c.

References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.

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

02522 {
02523    struct mgcp_request resp;
02524    struct mgcp_endpoint *p = sub->parent;
02525    format_t x;
02526    int fc = 1;
02527    char local[256];
02528    char tmp[80];
02529 
02530    if (ast_strlen_zero(sub->cxident)) {
02531       /* We don't have a CXident yet, store the destination and
02532          wait a bit */
02533       return 0;
02534    }
02535    ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02536       p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02537 
02538    ast_copy_string(local, "", sizeof(local));
02539    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02540       if (p->capability & x) {
02541          if (p->ncs && !fc) {
02542             p->capability = x; /* sb5120e bug */
02543             break;
02544          } else {
02545             fc = 0;
02546             snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
02547          }
02548          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02549       }
02550    }
02551 
02552    if (!sub->sdpsent) {
02553       if (sub->gate) {
02554          if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
02555             snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02556             strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02557          } else {
02558                /* we still don't have gateid wait */
02559             return 0;
02560          }
02561       }
02562    }
02563 
02564    reqprep(&resp, p, "MDCX");
02565    add_header(&resp, "C", sub->callid);
02566    if (!sub->sdpsent) {
02567       add_header(&resp, "L", local);
02568    }
02569    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02570    /* X header should not be sent. kept for compatibility */
02571    add_header(&resp, "X", sub->txident);
02572    add_header(&resp, "I", sub->cxident);
02573    switch (sub->parent->hookstate) {
02574    case MGCP_ONHOOK:
02575       add_header(&resp, "R", "L/hd(N)");
02576       break;
02577    case MGCP_OFFHOOK:
02578       add_header_offhook(sub, &resp, "");
02579       break;
02580    }
02581    if (!sub->sdpsent) {
02582       add_sdp(&resp, sub, NULL);
02583       sub->sdpsent = 1;
02584    }
02585    /* fill in new fields */
02586    resp.cmd = MGCP_CMD_MDCX;
02587    resp.trid = oseq;
02588    return send_request(p, sub, &resp, oseq);
02589 }

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

Definition at line 2265 of file chan_mgcp.c.

References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, ast_strlen_zero(), mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::parent, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.

Referenced by handle_response(), mgcp_pktcgate_open(), mgcp_set_rtp_peer(), and mgcp_write().

02266 {
02267    struct mgcp_request resp;
02268    char local[256];
02269    char tmp[80];
02270    struct mgcp_endpoint *p = sub->parent;
02271    format_t x;
02272    struct ast_sockaddr sub_tmpdest_tmp;
02273 
02274    if (ast_strlen_zero(sub->cxident) && rtp) {
02275       /* We don't have a CXident yet, store the destination and
02276          wait a bit */
02277       ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp);
02278       ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest);
02279       return 0;
02280    }
02281    ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
02282    for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) {
02283       if (!(x & AST_FORMAT_AUDIO_MASK)) {
02284          /* No longer contiguous */
02285          continue;
02286       }
02287       if (p->capability & x) {
02288          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0));
02289          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02290       }
02291    }
02292 
02293    if (sub->gate) {
02294       if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
02295          snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02296          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02297          sub->sdpsent = 1;
02298       } else {
02299          /* oops wait */
02300          ast_debug(1, "Waiting for opened gate...\n");
02301          sub->sdpsent = 0;
02302          return 0;
02303       }
02304    }
02305 
02306 
02307    reqprep(&resp, p, "MDCX");
02308    add_header(&resp, "C", sub->callid);
02309    add_header(&resp, "L", local);
02310    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02311    /* X header should not be sent. kept for compatibility */
02312    add_header(&resp, "X", sub->txident);
02313    add_header(&resp, "I", sub->cxident);
02314    /*add_header(&resp, "S", "");*/
02315    add_sdp(&resp, sub, rtp);
02316    /* fill in new fields */
02317    resp.cmd = MGCP_CMD_MDCX;
02318    resp.trid = oseq;
02319    return send_request(p, sub, &resp, oseq);
02320 }

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

Definition at line 2450 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_strlen_zero(), 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().

02451 {
02452    struct mgcp_request resp;
02453    struct mgcp_endpoint *p = sub->parent;
02454 
02455    ast_debug(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
02456       tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02457    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02458    reqprep(&resp, p, "RQNT");
02459    add_header(&resp, "X", p->rqnt_ident);
02460    switch (p->hookstate) {
02461    case MGCP_ONHOOK:
02462       add_header(&resp, "R", "L/hd(N)");
02463       break;
02464    case MGCP_OFFHOOK:
02465       add_header_offhook(sub, &resp, tone);
02466       break;
02467    }
02468    if (!ast_strlen_zero(tone)) {
02469       add_header(&resp, "S", tone);
02470    }
02471    /* fill in new fields */
02472    resp.cmd = MGCP_CMD_RQNT;
02473    resp.trid = oseq;
02474    return send_request(p, NULL, &resp, oseq);
02475 }

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

Definition at line 2477 of file chan_mgcp.c.

References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_localtime(), ast_strlen_zero(), ast_tvnow(), 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().

02478 {
02479    struct mgcp_request resp;
02480    char tone2[256];
02481    char *l, *n;
02482    struct timeval t = ast_tvnow();
02483    struct ast_tm tm;
02484    struct mgcp_endpoint *p = sub->parent;
02485 
02486    ast_localtime(&t, &tm, NULL);
02487    n = callername;
02488    l = callernum;
02489    if (!n)
02490       n = "";
02491    if (!l)
02492       l = "";
02493 
02494    /* Keep track of last callerid for blacklist and callreturn */
02495    ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
02496 
02497    snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
02498       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
02499    ast_copy_string(p->curtone, tone, sizeof(p->curtone));
02500    reqprep(&resp, p, "RQNT");
02501    add_header(&resp, "X", p->rqnt_ident);
02502    switch (p->hookstate) {
02503    case MGCP_ONHOOK:
02504       add_header(&resp, "R", "L/hd(N)");
02505       break;
02506    case MGCP_OFFHOOK:
02507       add_header_offhook(sub, &resp, tone);
02508       break;
02509    }
02510    if (!ast_strlen_zero(tone2)) {
02511       add_header(&resp, "S", tone2);
02512    }
02513    ast_debug(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
02514       tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
02515    /* fill in new fields */
02516    resp.cmd = MGCP_CMD_RQNT;
02517    resp.trid = oseq;
02518    return send_request(p, NULL, &resp, oseq);
02519 }

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

Definition at line 2143 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 cc_esc_publish_handler(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_invite_replaces(), handle_keep_alive_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_options(), handle_request_publish(), handle_request_refer(), handle_request_subscribe(), handle_request_update(), handle_response(), handle_sip_publish_initial(), handle_sip_publish_modify(), handle_sip_publish_refresh(), handle_sip_publish_remove(), handle_skinny_reset(), receive_message(), register_verify(), send_provisional_keepalive_full(), sip_cc_agent_ack(), sip_cc_agent_destructor(), sip_indicate(), sip_park_thread(), sip_sendhtml(), skinny_reload(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_linestatres(), transmit_provisional_response(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speaker_mode(), transmit_speeddialstatres(), transmit_start_tone(), transmit_startmediatransmission(), transmit_stop_tone(), transmit_stopmediatransmission(), and transmit_versionres().

02144 {
02145    struct mgcp_request resp;
02146    struct mgcp_endpoint *p = sub->parent;
02147    struct mgcp_response *mgr;
02148 
02149    if (!sub) {
02150       return -1;
02151    }
02152 
02153    respprep(&resp, p, msg, req, msgrest);
02154    if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) {
02155       return send_response(sub, &resp);
02156    }
02157    /* Store MGCP response in case we have to retransmit */
02158    sscanf(req->identifier, "%30d", &mgr->seqno);
02159    time(&mgr->whensent);
02160    mgr->len = resp.len;
02161    memcpy(mgr->buf, resp.data, resp.len);
02162    mgr->buf[resp.len] = '\0';
02163    mgr->next = p->parent->responses;
02164    p->parent->responses = mgr;
02165 
02166    return send_response(sub, &resp);
02167 }

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

Definition at line 514 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_instance_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().

00515 {
00516    struct mgcp_endpoint *p = sub->parent;
00517    if (p->sub == sub) {
00518       ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
00519       return -1;
00520    }
00521    ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
00522 
00523    sub->owner = NULL;
00524    if (!ast_strlen_zero(sub->cxident)) {
00525       transmit_connection_del(sub);
00526    }
00527    sub->cxident[0] = '\0';
00528    sub->callid[0] = '\0';
00529    sub->cxmode = MGCP_CX_INACTIVE;
00530    sub->outgoing = 0;
00531    sub->alreadygone = 0;
00532    memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
00533    if (sub->rtp) {
00534       ast_rtp_instance_destroy(sub->rtp);
00535       sub->rtp = NULL;
00536    }
00537    dump_cmd_queues(NULL, sub);
00538    return 0;
00539 }

static int unload_module ( void   )  [static]

Definition at line 4849 of file chan_mgcp.c.

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

04850 {
04851    struct mgcp_endpoint *e;
04852    struct mgcp_gateway *g;
04853 
04854    /* Check to see if we're reloading */
04855    if (ast_mutex_trylock(&mgcp_reload_lock)) {
04856       ast_log(LOG_WARNING, "MGCP is currently reloading.  Unable to remove module.\n");
04857       return -1;
04858    } else {
04859       mgcp_reloading = 1;
04860       ast_mutex_unlock(&mgcp_reload_lock);
04861    }
04862 
04863    /* First, take us out of the channel loop */
04864    ast_channel_unregister(&mgcp_tech);
04865 
04866    /* Shut down the monitoring thread */
04867    if (!ast_mutex_lock(&monlock)) {
04868       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04869          pthread_cancel(monitor_thread);
04870          pthread_kill(monitor_thread, SIGURG);
04871          pthread_join(monitor_thread, NULL);
04872       }
04873       monitor_thread = AST_PTHREADT_STOP;
04874       ast_mutex_unlock(&monlock);
04875    } else {
04876       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04877       /* We always want to leave this in a consistent state */
04878       ast_channel_register(&mgcp_tech);
04879       mgcp_reloading = 0;
04880       mgcp_reload(NULL, 0, NULL);
04881       return -1;
04882    }
04883 
04884    if (!ast_mutex_lock(&gatelock)) {
04885       for (g = gateways; g; g = g->next) {
04886          g->delme = 1;
04887          for (e = g->endpoints; e; e = e->next) {
04888             e->delme = 1;
04889          }
04890       }
04891 
04892       prune_gateways();
04893       ast_mutex_unlock(&gatelock);
04894    } else {
04895       ast_log(LOG_WARNING, "Unable to lock the gateways list.\n");
04896       /* We always want to leave this in a consistent state */
04897       ast_channel_register(&mgcp_tech);
04898       /* Allow the monitor to restart */
04899       monitor_thread = AST_PTHREADT_NULL;
04900       mgcp_reloading = 0;
04901       mgcp_reload(NULL, 0, NULL);
04902       return -1;
04903    }
04904 
04905    close(mgcpsock);
04906    ast_rtp_glue_unregister(&mgcp_rtp_glue);
04907    ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04908    sched_context_destroy(sched);
04909 
04910    return 0;
04911 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } [static]

Definition at line 4919 of file chan_mgcp.c.

struct in_addr __ourip [static]

Definition at line 229 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 193 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 199 of file chan_mgcp.c.

int amaflags = 0 [static]

Definition at line 197 of file chan_mgcp.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4919 of file chan_mgcp.c.

struct sockaddr_in bindaddr [static]

Definition at line 424 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 178 of file chan_mgcp.c.

int callwaiting = 0 [static]

Definition at line 176 of file chan_mgcp.c.

int cancallforward = 0 [static]

Definition at line 187 of file chan_mgcp.c.

format_t capability = AST_FORMAT_ULAW [static]

Definition at line 225 of file chan_mgcp.c.

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

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 156 of file chan_mgcp.c.

Referenced by __analog_handle_event(), __oh323_new(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), dial_exec_full(), get_pai(), get_rpid(), misdn_new(), read_config(), set_peer_defaults(), set_pvt_defaults(), sip_call(), socket_process(), and store_callerid().

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 155 of file chan_mgcp.c.

Referenced by __analog_handle_event(), __oh323_new(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), dial_exec_full(), get_pai(), get_rpid(), misdn_new(), read_config(), set_peer_defaults(), set_pvt_defaults(), socket_process(), state_notify_build_xml(), and store_callerid().

struct ast_cli_entry cli_mgcp[] [static]

Definition at line 1167 of file chan_mgcp.c.

Referenced by load_module().

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

Definition at line 108 of file chan_mgcp.c.

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

Definition at line 150 of file chan_mgcp.c.

unsigned int cos

Definition at line 170 of file chan_mgcp.c.

unsigned int cos_audio

Definition at line 171 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 164 of file chan_mgcp.c.

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 165 of file chan_mgcp.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 97 of file chan_mgcp.c.

int directmedia = DIRECTMEDIA [static]

Definition at line 191 of file chan_mgcp.c.

Referenced by build_gateway().

int dtmfmode = 0 [static]

Definition at line 158 of file chan_mgcp.c.

Referenced by reload_config(), and set_local_capabilities().

int firstdigittimeout = 16000 [static]

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

Definition at line 204 of file chan_mgcp.c.

ast_mutex_t gatelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

gatelock: mutex for gateway/endpoint lists

Definition at line 420 of file chan_mgcp.c.

Referenced by do_monitor(), find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), 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(), and unload_module().

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic)

Definition at line 207 of file chan_mgcp.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 105 of file chan_mgcp.c.

int hangupongateremove = 0 [static]

Definition at line 162 of file chan_mgcp.c.

int immediate = 0 [static]

Definition at line 174 of file chan_mgcp.c.

struct io_context* io [static]

Definition at line 235 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 152 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 195 of file chan_mgcp.c.

Referenced by action_mailboxcount(), action_mailboxstatus(), add_peer_mailboxes(), add_peer_mwi_subs(), aji_mwi_cb(), append_mailbox_mapping(), ast_event_hash_mwi(), build_peer(), chanspy_exec(), clear_peer_mailboxes(), disa_exec(), extenspy_exec(), get_cached_mwi(), handle_request_notify(), has_voicemail(), minivm_mwi_exec(), notify_message(), peer_mailboxes_to_str(), peers_data_provider_get(), queue_mwi_event(), realtime_directory(), sip_subscribe_mwi(), 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 210 of file chan_mgcp.c.

const char* const mgcp_cxmodes[] [static]

}

Definition at line 130 of file chan_mgcp.c.

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

ast_mutex_t mgcp_reload_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 416 of file chan_mgcp.c.

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

int mgcp_reloading = 0 [static]

Definition at line 417 of file chan_mgcp.c.

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

struct ast_rtp_glue mgcp_rtp_glue [static]

Definition at line 4432 of file chan_mgcp.c.

Referenced by load_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 461 of file chan_mgcp.c.

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

int mgcpdebug = 0 [static]

Definition at line 232 of file chan_mgcp.c.

Referenced by handle_mgcp_audit_endpoint(), and handle_mgcp_set_debug().

int mgcpsock = -1 [static]

Definition at line 422 of file chan_mgcp.c.

Referenced by do_monitor(), and mgcpsock_read().

int* mgcpsock_read_id = NULL [static]

Definition at line 3693 of file chan_mgcp.c.

Referenced by do_monitor().

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

ast_mutex_t monlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 216 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

Definition at line 153 of file chan_mgcp.c.

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

int nat = 0 [static]

Definition at line 159 of file chan_mgcp.c.

int ncs = 0 [static]

Definition at line 160 of file chan_mgcp.c.

ast_mutex_t netlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, 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 214 of file chan_mgcp.c.

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

int nonCodecCapability = AST_RTP_DTMF [static]

Definition at line 226 of file chan_mgcp.c.

Referenced by process_sdp().

unsigned int oseq [static]

Definition at line 201 of file chan_mgcp.c.

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

char ourhost[MAXHOSTNAMELEN] [static]

Definition at line 228 of file chan_mgcp.c.

Referenced by ast_find_ourip(), and reload_config().

int ourport [static]

Definition at line 230 of file chan_mgcp.c.

Referenced by initreqprep(), and transmit_notify_with_mwi().

char parkinglot[AST_MAX_CONTEXT] [static]

Definition at line 154 of file chan_mgcp.c.

int pktcgatealloc = 0 [static]

Definition at line 161 of file chan_mgcp.c.

struct { ... } qos [static]

struct sched_context* sched [static]

Definition at line 234 of file chan_mgcp.c.

int singlepath = 0 [static]

Definition at line 189 of file chan_mgcp.c.

int slowsequence = 0 [static]

Definition at line 180 of file chan_mgcp.c.

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

Definition at line 107 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 182 of file chan_mgcp.c.

unsigned int tos

Definition at line 168 of file chan_mgcp.c.

unsigned int tos_audio

Definition at line 169 of file chan_mgcp.c.

int transfer = 0 [static]

This is for flashhook transfers

Definition at line 185 of file chan_mgcp.c.


Generated on Wed Apr 6 11:29:57 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7