Mon Mar 19 11:30:40 2012

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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static int ncs = 0
static ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 89 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 117 of file chan_mgcp.c.

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 116 of file chan_mgcp.c.

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 119 of file chan_mgcp.c.

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

#define DIRECTMEDIA   1

Definition at line 91 of file chan_mgcp.c.

Referenced by build_gateway().

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 94 of file chan_mgcp.c.

#define MAX_EXPIRY   3600

Definition at line 90 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 120 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 283 of file chan_mgcp.c.

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

#define MGCP_CX_CONF   3

Definition at line 126 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 127 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 129 of file chan_mgcp.c.

Referenced by mgcp_hangup(), and unalloc_sub().

#define MGCP_CX_MUTE   4

Definition at line 128 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

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

#define MGCP_CX_SENDRECV   2

Definition at line 125 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 114 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 113 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 112 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 242 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

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

#define MGCP_OFFHOOK   2

Definition at line 319 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 318 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 294 of file chan_mgcp.c.

Referenced by mgcp_hangup().

#define MGCPDUMPER

Definition at line 88 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 273 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 286 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 285 of file chan_mgcp.c.

#define TYPE_LINE   2

Definition at line 322 of file chan_mgcp.c.

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

#define TYPE_TRUNK   1

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

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


Function Documentation

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

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

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

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 4922 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4573 of file chan_mgcp.c.

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

Referenced by build_peer(), and config_parse_variables().

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

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

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

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

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

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

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

static char* control2str ( int  ind  )  [static]

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

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

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

duplicate a list of channel variables,

Returns:
the copy.

Definition at line 4591 of file chan_mgcp.c.

References ast_variable_new(), and ast_variable::next.

Referenced by check_peer_ok(), and create_addr_from_peer().

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

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

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

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

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4520 of file chan_mgcp.c.

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

04521 {
04522    if (g->ha)
04523       ast_free_ha(g->ha);
04524 
04525    dump_queue(g, NULL);
04526 
04527    ast_free(g);
04528 }

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

Definition at line 3760 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, netlock, mgcp_gateway::next, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.

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

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

dump_cmd_queues: (SC:) cleanup pending commands

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

get_csv: (SC:) get comma separated value

Definition at line 1642 of file chan_mgcp.c.

Referenced by handle_response().

01643 {
01644    char *s;
01645 
01646    *next = NULL, *len = 0;
01647    if (!c) return NULL;
01648 
01649    while (*c && (*c < 33 || *c == ',')) {
01650       c++;
01651    }
01652 
01653    s = c;
01654    while (*c && (*c >= 33 && *c != ',')) {
01655       c++, (*len)++;
01656    }
01657    *next = c;
01658 
01659    if (*len == 0) {
01660       s = NULL, *next = NULL;
01661    }
01662 
01663    return s;
01664 }

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

Definition at line 1635 of file chan_mgcp.c.

References __get_header().

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

01636 {
01637    int start = 0;
01638    return __get_header(req, name, &start, "");
01639 }

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

Definition at line 1586 of file chan_mgcp.c.

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

Referenced by process_sdp().

01587 {
01588    int x;
01589    int len = strlen(name);
01590    char *r;
01591 
01592    for (x = 0; x < req->lines; x++) {
01593       r = get_sdp_by_line(req->line[x], name, len);
01594       if (r[0] != '\0') return r;
01595    }
01596    return "";
01597 }

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

Definition at line 1576 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01577 {
01578    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01579       char *r = line + nameLen + 1;
01580       while (*r && (*r < 33)) ++r;
01581       return r;
01582    }
01583    return "";
01584 }

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

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

01605 {
01606    int len = strlen(name);
01607    char *r;
01608    while (*iterator < req->lines) {
01609       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01610       if (r[0] != '\0') return r;
01611    }
01612    return "";
01613 }

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

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

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

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

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

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

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

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

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

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

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

01039 {
01040    struct mgcp_gateway  *mg;
01041    struct mgcp_endpoint *me;
01042    int hasendpoints = 0;
01043    struct ast_variable * v = NULL;
01044 
01045    switch (cmd) {
01046    case CLI_INIT:
01047       e->command = "mgcp show endpoints";
01048       e->usage =
01049          "Usage: mgcp show endpoints\n"
01050          "       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
01051       return NULL;
01052    case CLI_GENERATE:
01053       return NULL;
01054    }
01055 
01056    if (a->argc != 3) {
01057       return CLI_SHOWUSAGE;
01058    }
01059    ast_mutex_lock(&gatelock);
01060    for (mg = gateways; mg; mg = mg->next) {
01061       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");
01062       for (me = mg->endpoints; me; me = me->next) {
01063          ast_cli(a->fd, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
01064          if (me->chanvars) {
01065             ast_cli(a->fd, "  Variables:\n");
01066             for (v = me->chanvars ; v ; v = v->next) {
01067                ast_cli(a->fd, "    %s = '%s'\n", v->name, v->value);
01068             }
01069          }
01070          hasendpoints = 1;
01071       }
01072       if (!hasendpoints) {
01073          ast_cli(a->fd, "   << No Endpoints Defined >>     ");
01074       }
01075    }
01076    ast_mutex_unlock(&gatelock);
01077    return CLI_SUCCESS;
01078 }

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

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

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

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

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

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

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

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

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

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

02108 {
02109    /* Initialize a response */
02110    if (req->headers || req->len) {
02111       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02112       return -1;
02113    }
02114    req->header[req->headers] = req->data + req->len;
02115    /* check if we need brackets around the gw name */
02116    if (p->parent->isnamedottedip) {
02117       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" : "");
02118    } else {
02119 +     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" : "");
02120    }
02121    req->len += strlen(req->header[req->headers]);
02122    if (req->headers < MGCP_MAX_HEADERS) {
02123       req->headers++;
02124    } else {
02125       ast_log(LOG_WARNING, "Out of header space\n");
02126    }
02127    return 0;
02128 }

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

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

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

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

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

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

static int mgcp_alloc_pktcgate ( struct mgcp_subchannel sub  )  [static]

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

02410 {
02411    struct mgcp_endpoint *p = sub->parent;
02412    sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
02413                8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
02414 
02415    if (!sub->gate) {
02416       return 0;
02417    }
02418    sub->gate->tech_pvt = sub;
02419    sub->gate->gate_open = &mgcp_pktcgate_open;
02420    return 1;
02421 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

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

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

static format_t mgcp_get_codec ( struct ast_channel chan  )  [static]

Definition at line 4428 of file chan_mgcp.c.

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

04429 {
04430    struct mgcp_subchannel *sub = chan->tech_pvt;
04431    struct mgcp_endpoint *p = sub->parent;
04432    return p->capability;
04433 }

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

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

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

static int mgcp_hangup ( struct ast_channel ast  )  [static]

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

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

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

Definition at line 1439 of file chan_mgcp.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, 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().

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

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

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

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

static int mgcp_pktcgate_open ( struct cops_gate gate  )  [static]

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

02397 {
02398    struct mgcp_subchannel *sub = gate->tech_pvt;
02399    if (!sub) {
02400       return 1;
02401    }
02402    ast_mutex_lock(&sub->lock);
02403    ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
02404    if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
02405    ast_mutex_unlock(&sub->lock);
02406    return 1;
02407 }

static int mgcp_pktcgate_remove ( struct cops_gate gate  )  [static]

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

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

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

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

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

static int mgcp_prune_realtime_gateway ( struct mgcp_gateway g  )  [static]

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

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

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

Definition at line 648 of file chan_mgcp.c.

References AST_FRAME_CONTROL, f, and mgcp_queue_frame().

Referenced by handle_hd_hf().

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

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

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

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

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

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

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

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

Definition at line 1232 of file chan_mgcp.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 483 of file chan_mgcp.c.

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

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1857 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_masq_park_call_exten(), ast_park_call_exten(), ast_parse_allow_disallow(), 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(), get_comma(), get_in_brackets_full(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), man_do_variable_value(), mgcpsock_read(), mixmonitor_exec(), originate_exec(), oss_call(), oss_request(), page_exec(), park_call_exec(), parked_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(), sip_acf_channel_read(), 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(), xfer_park_call_helper(), and zapateller_exec().

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

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

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

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

static void prune_gateways ( void   )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 4846 of file chan_mgcp.c.

References mgcp_reload().

04847 {
04848    mgcp_reload(NULL, 0, NULL);
04849    return 0;
04850 }

static int reload_config ( int  reload  )  [static]

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

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

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

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

02139 {
02140    memset(req, 0, sizeof(struct mgcp_request));
02141    oseq++;
02142    if (oseq > 999999999) {
02143       oseq = 1;
02144    }
02145    init_req(p, req, verb);
02146    return 0;
02147 }

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

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

00558 {
00559    struct mgcp_endpoint *p = sub->parent;
00560    int res;
00561    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));
00562    res = __mgcp_xmit(p->parent, resp->buf, resp->len);
00563    if (res > 0)
00564       res = 0;
00565    return res;
00566 }

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

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

02132 {
02133    memset(resp, 0, sizeof(*resp));
02134    init_resp(resp, msg, req, msgrest);
02135    return 0;
02136 }

static int restart_monitor ( void   )  [static]

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

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

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

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

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

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1599 of file chan_mgcp.c.

Referenced by process_sdp().

01600 {
01601    *iterator = 0;
01602 }

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

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

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

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

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

00569 {
00570    struct mgcp_endpoint *p = sub->parent;
00571    int res;
00572    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));
00573    res = __mgcp_xmit(p->parent, req->data, req->len);
00574    if (res > 0)
00575       res = 0;
00576    return res;
00577 }

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

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

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

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

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

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

static int transmit_connect ( struct mgcp_subchannel sub  )  [static]

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

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

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

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

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

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

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

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

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

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

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

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2149 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_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_destructor(), sip_cc_agent_respond(), sip_indicate(), 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().

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

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

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

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

static int unload_module ( void   )  [static]

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

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


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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } [static]

Definition at line 4922 of file chan_mgcp.c.

struct in_addr __ourip [static]

Definition at line 231 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 195 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 201 of file chan_mgcp.c.

int amaflags = 0 [static]

Definition at line 199 of file chan_mgcp.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4922 of file chan_mgcp.c.

struct sockaddr_in bindaddr [static]

Definition at line 426 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 180 of file chan_mgcp.c.

int callwaiting = 0 [static]

Definition at line 178 of file chan_mgcp.c.

int cancallforward = 0 [static]

Definition at line 189 of file chan_mgcp.c.

format_t capability = AST_FORMAT_ULAW [static]

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

Referenced by __analog_handle_event(), __oh323_new(), action_originate(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), 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 157 of file chan_mgcp.c.

Referenced by __analog_handle_event(), __oh323_new(), action_originate(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), 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 1169 of file chan_mgcp.c.

Referenced by load_module().

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

Definition at line 110 of file chan_mgcp.c.

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

Definition at line 152 of file chan_mgcp.c.

unsigned int cos

Definition at line 172 of file chan_mgcp.c.

unsigned int cos_audio

Definition at line 173 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 166 of file chan_mgcp.c.

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 167 of file chan_mgcp.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Note:
Values shown here match the defaults shown in mgcp.conf.sample

Definition at line 99 of file chan_mgcp.c.

int directmedia = DIRECTMEDIA [static]

Definition at line 193 of file chan_mgcp.c.

Referenced by build_gateway().

int dtmfmode = 0 [static]

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

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

gatelock: mutex for gateway/endpoint lists

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

struct ast_jb_conf global_jbconf [static]

Definition at line 107 of file chan_mgcp.c.

int hangupongateremove = 0 [static]

Definition at line 164 of file chan_mgcp.c.

int immediate = 0 [static]

Definition at line 176 of file chan_mgcp.c.

struct io_context* io [static]

Definition at line 237 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 154 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

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

const char* const mgcp_cxmodes[] [static]

}

Definition at line 132 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 418 of file chan_mgcp.c.

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

int mgcp_reloading = 0 [static]

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

Referenced by load_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 463 of file chan_mgcp.c.

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

int mgcpdebug = 0 [static]

Definition at line 234 of file chan_mgcp.c.

Referenced by handle_mgcp_audit_endpoint(), and handle_mgcp_set_debug().

int mgcpsock = -1 [static]

Definition at line 424 of file chan_mgcp.c.

Referenced by do_monitor(), and mgcpsock_read().

int* mgcpsock_read_id = NULL [static]

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

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

Definition at line 218 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

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

int ncs = 0 [static]

Definition at line 162 of file chan_mgcp.c.

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

Referenced by process_sdp().

unsigned int oseq [static]

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

Referenced by ast_find_ourip(), and reload_config().

int ourport [static]

Definition at line 232 of file chan_mgcp.c.

Referenced by initreqprep(), and transmit_notify_with_mwi().

char parkinglot[AST_MAX_CONTEXT] [static]

Definition at line 156 of file chan_mgcp.c.

Referenced by __find_callno(), ast_iax2_new(), build_parkinglot(), build_peer(), build_user(), check_access(), check_peer_ok(), copy_parkinglot(), create_addr_from_peer(), create_dynamic_parkinglot(), dahdi_new(), find_parkinglot(), func_channel_write_real(), gtalk_load_config(), gtalk_new(), iax_park(), park_space_abort(), park_space_reserve(), parked_call_exec(), parkinglot_activate(), parkinglot_activate_cb(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_is_marked_cb(), parkinglot_markall_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().

int pktcgatealloc = 0 [static]

Definition at line 163 of file chan_mgcp.c.

struct { ... } qos [static]

struct sched_context* sched [static]

Definition at line 236 of file chan_mgcp.c.

int singlepath = 0 [static]

Definition at line 191 of file chan_mgcp.c.

int slowsequence = 0 [static]

Definition at line 182 of file chan_mgcp.c.

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

Definition at line 109 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 184 of file chan_mgcp.c.

unsigned int tos

Definition at line 170 of file chan_mgcp.c.

unsigned int tos_audio

Definition at line 171 of file chan_mgcp.c.

int transfer = 0 [static]

This is for flashhook transfers

Definition at line 187 of file chan_mgcp.c.


Generated on Mon Mar 19 11:30:40 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7