Thu Oct 11 06:35:09 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/netsock2.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"

Include dependency graph for chan_mgcp.c:

Go to the source code of this file.

Data Structures

struct  mgcp_endpoint
struct  mgcp_gateway
struct  mgcp_message
 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 the module.
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, const char *dest, int timeout)
static int mgcp_devicestate (const char *data)
 mgcp_devicestate: channel callback for device status monitoring
static int mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static void mgcp_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, 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, const struct ast_format_cap *cap, 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, const struct ast_format_cap *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 = AST_BUILDOPT_SUM, .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 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_MUTEX_INITIALIZER , NULL, 1 }
 gatelock: mutex for gateway/endpoint lists
static struct mgcp_gatewaygateways
static int gendigittimeout = 8000
static struct ast_format_capglobal_capability
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_MUTEX_INITIALIZER , 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_MUTEX_INITIALIZER , NULL, 1 }
static char musicclass [MAX_MUSICCLASS] = ""
static int nat = 0
static int ncs = 0
static ast_mutex_t netlock = { PTHREAD_MUTEX_INITIALIZER , 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 ast_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>

Definition in file chan_mgcp.c.


Define Documentation

#define DEFAULT_EXPIRY   120

Definition at line 94 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 122 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 121 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 124 of file chan_mgcp.c.

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

#define DIRECTMEDIA   1

Definition at line 96 of file chan_mgcp.c.

Referenced by build_gateway().

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 99 of file chan_mgcp.c.

Referenced by build_gateway().

#define MAX_EXPIRY   3600

Definition at line 95 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 125 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 288 of file chan_mgcp.c.

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

#define MGCP_CX_CONF   3

Definition at line 131 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 132 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 134 of file chan_mgcp.c.

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

#define MGCP_CX_MUTE   4

Definition at line 133 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

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

#define MGCP_CX_SENDRECV   2

Definition at line 130 of file chan_mgcp.c.

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

#define MGCP_DTMF_HYBRID   (1 << 2)

#define MGCP_DTMF_INBAND   (1 << 1)

#define MGCP_DTMF_RFC2833   (1 << 0)

#define MGCP_MAX_HEADERS   64

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

Definition at line 247 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

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

#define MGCP_OFFHOOK   2

#define MGCP_ONHOOK   1

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

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 93 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 278 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 291 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 290 of file chan_mgcp.c.

#define TYPE_LINE   2

#define TYPE_TRUNK   1

Definition at line 326 of file chan_mgcp.c.

Referenced by build_gateway().


Enumeration Type Documentation

anonymous enum

Enumerator:
MGCP_CMD_EPCF 
MGCP_CMD_CRCX 
MGCP_CMD_MDCX 
MGCP_CMD_DLCX 
MGCP_CMD_RQNT 
MGCP_CMD_NTFY 
MGCP_CMD_AUEP 
MGCP_CMD_AUCX 
MGCP_CMD_RSIP 

Definition at line 145 of file chan_mgcp.c.

00145      {
00146    MGCP_CMD_EPCF,
00147    MGCP_CMD_CRCX,
00148    MGCP_CMD_MDCX,
00149    MGCP_CMD_DLCX,
00150    MGCP_CMD_RQNT,
00151    MGCP_CMD_NTFY,
00152    MGCP_CMD_AUEP,
00153    MGCP_CMD_AUCX,
00154    MGCP_CMD_RSIP
00155 };


Function Documentation

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

Definition at line 1622 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(), parse_register_contact(), and sip_get_header().

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

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 4969 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

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

References ast_channel_tech(), ast_channel_tech_pvt(), ast_log(), LOG_ERROR, mgcp_endpoint::ncs, mgcp_subchannel::parent, and sub.

04467 {
04468    struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
04469    int res = 0;
04470 
04471    /* Sanity check */
04472    if (!chan || ast_channel_tech(chan) != &mgcp_tech) {
04473       ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
04474       return -1;
04475    }
04476 
04477    if (!strcasecmp(args, "ncs")) {
04478       snprintf(buf, buflen, "%s", sub->parent->ncs ?  "yes":"no");
04479    } else {
04480       res = -1;
04481    }
04482    return res;
04483 }

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

Definition at line 2056 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_date(), add_digit(), add_diversion(), add_expires(), add_header_offhook(), add_max_forwards(), add_route(), add_rpid(), add_sdp(), add_supported(), add_text(), add_vidupdate(), ast_sipinfo_send(), copy_all_header(), copy_header(), copy_via_headers(), finalize_content(), initreqprep(), reqprep(), respprep(), transmit_audit_endpoint(), transmit_cc_notify(), transmit_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_invite(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_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().

02057 {
02058    if (req->len >= sizeof(req->data) - 4) {
02059       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
02060       return -1;
02061    }
02062    if (req->lines) {
02063       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
02064       return -1;
02065    }
02066    req->header[req->headers] = req->data + req->len;
02067    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
02068    req->len += strlen(req->header[req->headers]);
02069    if (req->headers < MGCP_MAX_HEADERS) {
02070       req->headers++;
02071    } else {
02072       ast_log(LOG_WARNING, "Out of header space\n");
02073       return -1;
02074    }
02075    return 0;
02076 }

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

Definition at line 2621 of file chan_mgcp.c.

References 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_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

02622 {
02623    struct mgcp_endpoint *p = sub->parent;
02624    char tone_indicate_end = 0;
02625 
02626    /* We also should check the tone to indicate, because it have no sense
02627       to request notify D/[0-9#*] (dtmf keys) if we are sending congestion
02628       tone for example G/cg */
02629    if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
02630       tone_indicate_end = 1;
02631    }
02632 
02633    if (p && p->sub && p->sub->owner &&
02634          ast_channel_state(p->sub->owner) >= AST_STATE_RINGING &&
02635          (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) {
02636        add_header(resp, "R", "L/hu(N),L/hf(N)");
02637 
02638    } else if (!tone_indicate_end){
02639        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)"));
02640    } else {
02641       ast_debug(1, "We don't want more digits if we will end the call\n");
02642       add_header(resp, "R", "L/hu(N),L/hf(N)");
02643    }
02644 }

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

Definition at line 2078 of file chan_mgcp.c.

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

Referenced by add_sdp().

02079 {
02080    if (req->len >= sizeof(req->data) - 4) {
02081       ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
02082       return -1;
02083    }
02084    if (!req->lines) {
02085       /* Add extra empty return */
02086       ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
02087       req->len += strlen(req->data + req->len);
02088    }
02089    req->line[req->lines] = req->data + req->len;
02090    snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
02091    req->len += strlen(req->line[req->lines]);
02092    if (req->lines < MGCP_MAX_LINES) {
02093       req->lines++;
02094    } else {
02095       ast_log(LOG_WARNING, "Out of line space\n");
02096       return -1;
02097    }
02098    return 0;
02099 }

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

Definition at line 2188 of file chan_mgcp.c.

References add_line(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_AUDIO, ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_code(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), AST_RTP_MAX, ast_sockaddr_to_sin, mgcp_endpoint::cap, ast_format::id, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, and mgcp_subchannel::tmpdest.

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

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

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

Definition at line 4597 of file chan_mgcp.c.

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

Referenced by build_gateway(), build_peer(), and config_parse_variables().

04598 {
04599    struct ast_variable *tmpvar = NULL;
04600    char *varname = ast_strdupa(buf), *varval = NULL;
04601 
04602    if ((varval = strchr(varname, '='))) {
04603       *varval++ = '\0';
04604       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
04605          tmpvar->next = list;
04606          list = tmpvar;
04607       }
04608    }
04609    return list;
04610 }

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

Definition at line 3223 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_name(), ast_channel_softhangup_internal_flag_add(), 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, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().

03224 {
03225    /* *************************
03226     * I hope this works.
03227     * Copied out of chan_zap
03228     * Cross your fingers
03229     * *************************/
03230 
03231    /* In order to transfer, we need at least one of the channels to
03232       actually be in a call bridge.  We can't conference two applications
03233       together (but then, why would we want to?) */
03234    if (ast_bridged_channel(p->sub->owner)) {
03235       /* The three-way person we're about to transfer to could still be in MOH, so
03236          stop if now if appropriate */
03237       if (ast_bridged_channel(p->sub->next->owner))
03238          ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
03239       if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
03240          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
03241       }
03242       if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
03243          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03244             ast_channel_name(ast_bridged_channel(p->sub->owner)), ast_channel_name(p->sub->next->owner));
03245          return -1;
03246       }
03247       /* Orphan the channel */
03248       unalloc_sub(p->sub->next);
03249    } else if (ast_bridged_channel(p->sub->next->owner)) {
03250       if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
03251          ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
03252       }
03253       ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
03254       if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
03255          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03256             ast_channel_name(ast_bridged_channel(p->sub->next->owner)), ast_channel_name(p->sub->owner));
03257          return -1;
03258       }
03259       /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
03260       ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
03261       p->sub = p->sub->next;
03262       unalloc_sub(p->sub->next);
03263       /* Tell the caller not to hangup */
03264       return 1;
03265    } else {
03266       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03267          ast_channel_name(p->sub->owner), ast_channel_name(p->sub->next->owner));
03268       ast_channel_softhangup_internal_flag_add(p->sub->next->owner, AST_SOFTHANGUP_DEV);
03269       if (p->sub->next->owner) {
03270          p->sub->next->alreadygone = 1;
03271          mgcp_queue_hangup(p->sub->next);
03272       }
03273    }
03274    return 0;
03275 }

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

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

Definition at line 3979 of file chan_mgcp.c.

References __ourip, mgcp_endpoint::accountcode, add_var(), mgcp_gateway::addr, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_format_cap_alloc_nolock(), ast_format_cap_copy(), ast_free, ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy, ast_mutex_init, ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variables_destroy(), ast_verb, mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, copy_vars(), mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::directmedia, DIRECTMEDIA, mgcp_endpoint::dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, mgcp_subchannel::gate, gateways, mgcp_gateway::ha, mgcp_endpoint::hangupongateremove, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, INADDR_NONE, mgcp_gateway::isnamedottedip, mgcp_endpoint::language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, MAX_SUBS, mbox(), MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::msgs_lock, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, mwi_event_cb(), mgcp_endpoint::mwi_event_sub, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, mgcp_endpoint::ncs, mgcp_endpoint::needaudit, mgcp_subchannel::next, mgcp_endpoint::next, ast_variable::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_gateway::ourip, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::parkinglot, mgcp_endpoint::pickupgroup, mgcp_endpoint::pktcgatealloc, mgcp_gateway::realtime, mgcp_gateway::retransid, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, mgcp_endpoint::slowsequence, strsep(), mgcp_endpoint::sub, sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and mgcp_gateway::wcardep.

Referenced by find_realtime_gw(), and reload_config().

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

static char* control2str ( int  ind  )  [static]

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

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

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

duplicate a list of channel variables,

Returns:
the copy.

Definition at line 4615 of file chan_mgcp.c.

References ast_variable_new(), and ast_variable::next.

Referenced by build_gateway(), check_peer_ok(), and create_addr_from_peer().

04616 {
04617    struct ast_variable *res = NULL, *tmp, *v = NULL;
04618 
04619    for (v = src ; v ; v = v->next) {
04620       if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
04621          tmp->next = res;
04622          res = tmp;
04623       }
04624    }
04625    return res;
04626 }

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

Definition at line 4486 of file chan_mgcp.c.

References ast_dsp_free(), ast_event_unsubscribe(), ast_format_cap_destroy(), ast_free, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_destroy(), ast_strlen_zero(), ast_variables_destroy(), mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, dump_cmd_queues(), dump_queue(), mgcp_subchannel::gate, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, mgcp_endpoint::lock, mgcp_subchannel::lock, mgcp_subchannel::magic, MAX_SUBS, mgcp_queue_hangup(), mgcp_endpoint::mwi_event_sub, mgcp_subchannel::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::sub, sub, cops_gate::tech_pvt, and transmit_connection_del().

Referenced by prune_gateways().

04487 {
04488    struct mgcp_subchannel *sub = e->sub->next, *s;
04489    int i;
04490 
04491    for (i = 0; i < MAX_SUBS; i++) {
04492       ast_mutex_lock(&sub->lock);
04493       if (!ast_strlen_zero(sub->cxident)) {
04494          transmit_connection_del(sub);
04495       }
04496       if (sub->rtp) {
04497          ast_rtp_instance_destroy(sub->rtp);
04498          sub->rtp = NULL;
04499       }
04500       memset(sub->magic, 0, sizeof(sub->magic));
04501       mgcp_queue_hangup(sub);
04502       dump_cmd_queues(NULL, sub);
04503       if(sub->gate) {
04504          sub->gate->tech_pvt = NULL;
04505          sub->gate->got_dq_gi = NULL;
04506          sub->gate->gate_remove = NULL;
04507          sub->gate->gate_open = NULL;
04508       }
04509       ast_mutex_unlock(&sub->lock);
04510       sub = sub->next;
04511    }
04512 
04513    if (e->dsp) {
04514       ast_dsp_free(e->dsp);
04515    }
04516 
04517    dump_queue(e->parent, e);
04518    dump_cmd_queues(e, NULL);
04519 
04520    sub = e->sub;
04521    for (i = 0; (i < MAX_SUBS) && sub; i++) {
04522       s = sub;
04523       sub = sub->next;
04524       ast_mutex_destroy(&s->lock);
04525       ast_mutex_destroy(&s->cx_queue_lock);
04526       ast_free(s);
04527    }
04528 
04529    if (e->mwi_event_sub)
04530       ast_event_unsubscribe(e->mwi_event_sub);
04531 
04532    if (e->chanvars) {
04533       ast_variables_destroy(e->chanvars);
04534       e->chanvars = NULL;
04535    }
04536 
04537    ast_mutex_destroy(&e->lock);
04538    ast_mutex_destroy(&e->rqnt_queue_lock);
04539    ast_mutex_destroy(&e->cmd_queue_lock);
04540    e->cap = ast_format_cap_destroy(e->cap);
04541    ast_free(e);
04542 }

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4544 of file chan_mgcp.c.

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

Referenced by fax_gateway_new(), and prune_gateways().

04545 {
04546    if (g->ha)
04547       ast_free_ha(g->ha);
04548 
04549    dump_queue(g, NULL);
04550 
04551    ast_free(g);
04552 }

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

Definition at line 3783 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(), MGCP_ONHOOK, mgcp_prune_realtime_gateway(), mgcp_reload_lock, mgcpsock_read(), monlock, mgcp_gateway::msgs_lock, netlock, mgcp_gateway::next, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.

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

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

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2704 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 destroy_endpoint(), handle_request(), handle_response(), and unalloc_sub().

02705 {
02706    struct mgcp_request *t, *q;
02707 
02708    if (p) {
02709       ast_mutex_lock(&p->rqnt_queue_lock);
02710       for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
02711       p->rqnt_queue = NULL;
02712       ast_mutex_unlock(&p->rqnt_queue_lock);
02713 
02714       ast_mutex_lock(&p->cmd_queue_lock);
02715       for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
02716       p->cmd_queue = NULL;
02717       ast_mutex_unlock(&p->cmd_queue_lock);
02718 
02719       ast_mutex_lock(&p->sub->cx_queue_lock);
02720       for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02721       p->sub->cx_queue = NULL;
02722       ast_mutex_unlock(&p->sub->cx_queue_lock);
02723 
02724       ast_mutex_lock(&p->sub->next->cx_queue_lock);
02725       for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
02726       p->sub->next->cx_queue = NULL;
02727       ast_mutex_unlock(&p->sub->next->cx_queue_lock);
02728    } else if (sub) {
02729       ast_mutex_lock(&sub->cx_queue_lock);
02730       for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
02731       sub->cx_queue = NULL;
02732       ast_mutex_unlock(&sub->cx_queue_lock);
02733    }
02734 }

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

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

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

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

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

03605 {
03606    int seqno=0;
03607    time_t now;
03608    struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
03609    time(&now);
03610    if (sscanf(req->identifier, "%30d", &seqno) != 1) {
03611       seqno = 0;
03612    }
03613    for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
03614       if (now - cur->whensent > RESPONSE_TIMEOUT) {
03615          /* Delete this entry */
03616          if (prev)
03617             prev->next = next;
03618          else
03619             sub->parent->parent->responses = next;
03620          ast_free(cur);
03621       } else {
03622          if (seqno == cur->seqno)
03623             answer = cur;
03624          prev = cur;
03625       }
03626    }
03627    if (answer) {
03628       resend_response(sub, answer);
03629       return 1;
03630    }
03631    return 0;
03632 }

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

find_command: (SC:) remove command transaction from queue

Definition at line 2738 of file chan_mgcp.c.

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

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

02740 {
02741    struct mgcp_request *prev, *req;
02742 
02743    ast_mutex_lock(l);
02744    for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
02745       if (req->trid == ident) {
02746          /* remove from queue */
02747          if (!prev)
02748             *queue = req->next;
02749          else
02750             prev->next = req->next;
02751 
02752          /* send next pending command */
02753          if (*queue) {
02754             ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
02755                ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
02756 
02757             mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
02758          }
02759          break;
02760       }
02761    }
02762    ast_mutex_unlock(l);
02763    return req;
02764 }

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

Note:
This is a fairly odd way of instantiating lines. Instead of each line created by virtue of being in the database (and loaded via ast_load_realtime_multientry), this code forces a specific order with a "lines" entry in the "mgcpgw" record. This has benefits, because as with chan_dahdi, values are inherited across definitions. The downside is that it's not as clear what the values will be simply by looking at a single row in the database, and it's probable that the sanest configuration should have the first column in the "mgcpep" table be "clearvars", with a static value of "all", if any variables are set at all. It may be worth making this assumption explicit in the code in the future, and then just using ast_load_realtime_multientry for the "mgcpep" records.

Definition at line 1673 of file chan_mgcp.c.

References args, AST_APP_ARG, ast_check_realtime(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_load_realtime(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_variables_destroy(), build_gateway(), mgcp_gateway::endpoints, gateways, ast_variable::name, mgcp_endpoint::needaudit, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, mgcp_gateway::realtime, transmit_audit_endpoint(), and ast_variable::value.

Referenced by find_subchannel_and_lock().

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

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

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

Referenced by mgcp_request(), and mgcpsock_read().

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

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

get_csv: (SC:) get comma separated value

Definition at line 1649 of file chan_mgcp.c.

Referenced by handle_response().

01650 {
01651    char *s;
01652 
01653    *next = NULL, *len = 0;
01654    if (!c) return NULL;
01655 
01656    while (*c && (*c < 33 || *c == ',')) {
01657       c++;
01658    }
01659 
01660    s = c;
01661    while (*c && (*c >= 33 && *c != ',')) {
01662       c++, (*len)++;
01663    }
01664    *next = c;
01665 
01666    if (*len == 0) {
01667       s = NULL, *next = NULL;
01668    }
01669 
01670    return s;
01671 }

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

Definition at line 1642 of file chan_mgcp.c.

References __get_header().

Referenced by handle_request(), and handle_response().

01643 {
01644    int start = 0;
01645    return __get_header(req, name, &start, "");
01646 }

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

Definition at line 1593 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

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

Definition at line 1583 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01584 {
01585    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01586       char *r = line + nameLen + 1;
01587       while (*r && (*r < 33)) ++r;
01588       return r;
01589    }
01590    return "";
01591 }

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

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

01612 {
01613    int len = strlen(name);
01614    char *r;
01615    while (*iterator < req->lines) {
01616       r = get_sdp_by_line(req->line[(*iterator)++], name, len);
01617       if (r[0] != '\0') return r;
01618    }
01619    return "";
01620 }

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

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

Referenced by handle_request().

03278 {
03279    struct mgcp_endpoint *p = sub->parent;
03280    struct ast_channel *c;
03281    pthread_t t;
03282 
03283    /* Off hook / answer */
03284    if (sub->outgoing) {
03285       /* Answered */
03286       if (sub->owner) {
03287          if (ast_bridged_channel(sub->owner))
03288             ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03289          sub->cxmode = MGCP_CX_SENDRECV;
03290          if (!sub->rtp) {
03291             start_rtp(sub);
03292          } else {
03293             transmit_modify_request(sub);
03294          }
03295          /*transmit_notify_request(sub, "aw");*/
03296          transmit_notify_request(sub, "");
03297          mgcp_queue_control(sub, AST_CONTROL_ANSWER);
03298       }
03299    } else {
03300       /* Start switch */
03301       /*sub->cxmode = MGCP_CX_SENDRECV;*/
03302       if (!sub->owner) {
03303          if (!sub->rtp) {
03304             start_rtp(sub);
03305          } else {
03306             transmit_modify_request(sub);
03307          }
03308          if (p->immediate) {
03309             /* The channel is immediately up. Start right away */
03310 #ifdef DLINK_BUGGY_FIRMWARE
03311             transmit_notify_request(sub, "rt");
03312 #else
03313             transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
03314 #endif
03315             c = mgcp_new(sub, AST_STATE_RING, NULL);
03316             if (!c) {
03317                ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
03318                transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
03319                ast_hangup(c);
03320             }
03321          } else {
03322             if (has_voicemail(p)) {
03323                transmit_notify_request(sub, "L/sl");
03324             } else {
03325                transmit_notify_request(sub, "L/dl");
03326             }
03327             c = mgcp_new(sub, AST_STATE_DOWN, NULL);
03328             if (c) {
03329                if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
03330                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03331                   ast_hangup(c);
03332                }
03333             } else {
03334                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
03335             }
03336          }
03337       } else {
03338          if (p->hookstate == MGCP_OFFHOOK) {
03339             ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03340          } else {
03341             ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
03342             ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n");
03343          }
03344          if (ast_bridged_channel(sub->owner))
03345             ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03346          sub->cxmode = MGCP_CX_SENDRECV;
03347          if (!sub->rtp) {
03348             start_rtp(sub);
03349          } else {
03350             transmit_modify_request(sub);
03351          }
03352          /*transmit_notify_request(sub, "aw");*/
03353          transmit_notify_request(sub, "");
03354          /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
03355       }
03356    }
03357 }

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

Definition at line 1084 of file chan_mgcp.c.

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

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

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

Definition at line 1145 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, and ast_cli_entry::usage.

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

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

Definition at line 1042 of file chan_mgcp.c.

References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock, ast_mutex_unlock, mgcp_endpoint::chanvars, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, 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.

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

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

Definition at line 3359 of file chan_mgcp.c.

References 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, ast_frame::frametype, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, ast_frame_subclass::integer, 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, ast_frame::src, mgcp_endpoint::sub, ast_frame::subclass, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, transmit_audit_endpoint(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_response(), mgcp_request::verb, and mgcp_gateway::wcardep.

Referenced by mgcpsock_read().

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

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

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

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

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

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

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

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

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

02120 {
02121    /* Initialize a response */
02122    if (req->headers || req->len) {
02123       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02124       return -1;
02125    }
02126    req->header[req->headers] = req->data + req->len;
02127    /* check if we need brackets around the gw name */
02128    if (p->parent->isnamedottedip) {
02129       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" : "");
02130    } else {
02131 +     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" : "");
02132    }
02133    req->len += strlen(req->header[req->headers]);
02134    if (req->headers < MGCP_MAX_HEADERS) {
02135       req->headers++;
02136    } else {
02137       ast_log(LOG_WARNING, "Out of header space\n");
02138    }
02139    return 0;
02140 }

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

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

02102 {
02103    /* Initialize a response */
02104    if (req->headers || req->len) {
02105       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02106       return -1;
02107    }
02108    req->header[req->headers] = req->data + req->len;
02109    snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
02110    req->len += strlen(req->header[req->headers]);
02111    if (req->headers < MGCP_MAX_HEADERS) {
02112       req->headers++;
02113    } else {
02114       ast_log(LOG_WARNING, "Out of header space\n");
02115    }
02116    return 0;
02117 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 4813 of file chan_mgcp.c.

References ast_channel_register(), ast_cli_register_multiple(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_alloc(), ast_format_set(), AST_FORMAT_ULAW, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_sched_context_create(), ast_sched_context_destroy(), ast_channel_tech::capabilities, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, reload_config(), and restart_monitor().

04814 {
04815    struct ast_format tmpfmt;
04816 
04817    if (!(global_capability = ast_format_cap_alloc())) {
04818       return AST_MODULE_LOAD_FAILURE;
04819    }
04820    if (!(mgcp_tech.capabilities = ast_format_cap_alloc())) {
04821       return AST_MODULE_LOAD_FAILURE;
04822    }
04823    ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
04824    ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
04825    ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
04826    if (!(sched = ast_sched_context_create())) {
04827       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04828       return AST_MODULE_LOAD_FAILURE;
04829    }
04830 
04831    if (!(io = io_context_create())) {
04832       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04833       ast_sched_context_destroy(sched);
04834       return AST_MODULE_LOAD_FAILURE;
04835    }
04836 
04837    if (reload_config(0))
04838       return AST_MODULE_LOAD_DECLINE;
04839 
04840    /* Make sure we can register our mgcp channel type */
04841    if (ast_channel_register(&mgcp_tech)) {
04842       ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
04843       io_context_destroy(io);
04844       ast_sched_context_destroy(sched);
04845       return AST_MODULE_LOAD_FAILURE;
04846    }
04847 
04848    ast_rtp_glue_register(&mgcp_rtp_glue);
04849    ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
04850 
04851    /* And start the monitor for the first time */
04852    restart_monitor();
04853 
04854    return AST_MODULE_LOAD_SUCCESS;
04855 }

static int mgcp_alloc_pktcgate ( struct mgcp_subchannel sub  )  [static]

Definition at line 2430 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, and cops_gate::tech_pvt.

Referenced by start_rtp().

02431 {
02432    struct mgcp_endpoint *p = sub->parent;
02433    sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
02434                8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
02435 
02436    if (!sub->gate) {
02437       return 0;
02438    }
02439    sub->gate->tech_pvt = sub;
02440    sub->gate->gate_open = &mgcp_pktcgate_open;
02441    return 1;
02442 }

static int mgcp_answer ( struct ast_channel ast  )  [static]

Definition at line 1180 of file chan_mgcp.c.

References ast_channel_name(), ast_channel_tech_pvt(), 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, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), sub, transmit_modify_request(), and transmit_notify_request().

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

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

Definition at line 840 of file chan_mgcp.c.

References ast_channel_connected(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_varshead(), 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, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, S_COR, start_rtp(), sub, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, and TYPE_LINE.

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

static int mgcp_devicestate ( const char *  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 1365 of file chan_mgcp.c.

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

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

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

Definition at line 1287 of file chan_mgcp.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_subchannel::owner, and sub.

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

static void mgcp_get_codec ( struct ast_channel chan,
struct ast_format_cap result 
) [static]

Definition at line 4451 of file chan_mgcp.c.

References ast_channel_tech_pvt(), ast_format_cap_copy(), mgcp_endpoint::cap, mgcp_subchannel::parent, and sub.

04452 {
04453    struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
04454    struct mgcp_endpoint *p = sub->parent;
04455    ast_format_cap_copy(result, p->cap);
04456 }

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

Definition at line 4424 of file chan_mgcp.c.

References ao2_ref, ast_channel_tech_pvt(), 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 sub.

04425 {
04426    struct mgcp_subchannel *sub = NULL;
04427 
04428    if (!(sub = ast_channel_tech_pvt(chan)) || !(sub->rtp))
04429       return AST_RTP_GLUE_RESULT_FORBID;
04430 
04431    *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
04432 
04433    if (sub->parent->directmedia)
04434       return AST_RTP_GLUE_RESULT_REMOTE;
04435    else
04436       return AST_RTP_GLUE_RESULT_LOCAL;
04437 }

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 925 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_caller(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), 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, 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, 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, name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, mgcp_subchannel::rtp, S_COR, cops_gate::state, mgcp_endpoint::sub, sub, cops_gate::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

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

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

Definition at line 1443 of file chan_mgcp.c.

References ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, 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, mgcp_endpoint::ncs, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, sub, transmit_modify_request(), and transmit_notify_request().

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

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

Definition at line 1499 of file chan_mgcp.c.

References mgcp_endpoint::accountcode, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_adsicpe_set(), ast_channel_alloc, ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_writeformat(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_format_cap_copy(), ast_format_cap_is_empty(), ast_format_copy(), 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_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_variable::name, mgcp_gateway::name, mgcp_endpoint::name, ast_variable::next, ast_party_id::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, mgcp_subchannel::rtp, ast_party_number::str, ast_party_number::valid, and ast_variable::value.

Referenced by handle_hd_hf(), and mgcp_request().

01500 {
01501    struct ast_channel *tmp;
01502    struct ast_variable *v = NULL;
01503    struct mgcp_endpoint *i = sub->parent;
01504    struct ast_format tmpfmt;
01505 
01506    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);
01507    if (tmp) {
01508       ast_channel_tech_set(tmp, &mgcp_tech);
01509       ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
01510       if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
01511          ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability);
01512       }
01513       if (sub->rtp) {
01514          ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
01515       }
01516       if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
01517          i->dsp = ast_dsp_new();
01518          ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
01519          /* this is to prevent clipping of dtmf tones during dsp processing */
01520          ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
01521       } else {
01522          i->dsp = NULL;
01523       }
01524       if (state == AST_STATE_RING)
01525          ast_channel_rings_set(tmp, 1);
01526 
01527       ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
01528       ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
01529       ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
01530       ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
01531       ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
01532       ast_channel_tech_pvt_set(tmp, sub);
01533       if (!ast_strlen_zero(i->language))
01534          ast_channel_language_set(tmp, i->language);
01535       if (!ast_strlen_zero(i->accountcode))
01536          ast_channel_accountcode_set(tmp, i->accountcode);
01537       if (i->amaflags)
01538          ast_channel_amaflags_set(tmp, i->amaflags);
01539       sub->owner = tmp;
01540       ast_module_ref(ast_module_info->self);
01541       ast_channel_callgroup_set(tmp, i->callgroup);
01542       ast_channel_pickupgroup_set(tmp, i->pickupgroup);
01543       ast_channel_call_forward_set(tmp, i->call_forward);
01544       ast_channel_context_set(tmp, i->context);
01545       ast_channel_exten_set(tmp, i->exten);
01546 
01547       /* Don't use ast_set_callerid() here because it will
01548        * generate a needless NewCallerID event */
01549       if (!ast_strlen_zero(i->cid_num)) {
01550          ast_channel_caller(tmp)->ani.number.valid = 1;
01551          ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
01552       }
01553 
01554       if (!i->adsi) {
01555          ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
01556       }
01557       ast_channel_priority_set(tmp, 1);
01558 
01559       /* Set channel variables for this call from configuration */
01560       for (v = i->chanvars ; v ; v = v->next) {
01561          char valuebuf[1024];
01562          pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
01563       }
01564 
01565       if (sub->rtp) {
01566          ast_jb_configure(tmp, &global_jbconf);
01567       }
01568       if (state != AST_STATE_DOWN) {
01569          if (ast_pbx_start(tmp)) {
01570             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
01571             ast_hangup(tmp);
01572             tmp = NULL;
01573          }
01574       }
01575       ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
01576             ast_channel_name(tmp), ast_state2str(state));
01577    } else {
01578       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01579    }
01580    return tmp;
01581 }

static int mgcp_pktcgate_open ( struct cops_gate gate  )  [static]

Definition at line 2417 of file chan_mgcp.c.

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

Referenced by mgcp_alloc_pktcgate().

02418 {
02419    struct mgcp_subchannel *sub = gate->tech_pvt;
02420    if (!sub) {
02421       return 1;
02422    }
02423    ast_mutex_lock(&sub->lock);
02424    ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
02425    if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
02426    ast_mutex_unlock(&sub->lock);
02427    return 1;
02428 }

static int mgcp_pktcgate_remove ( struct cops_gate gate  )  [static]

Definition at line 2394 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, sub, and cops_gate::tech_pvt.

Referenced by mgcp_alloc_pktcgate().

02395 {
02396    struct mgcp_subchannel *sub = gate->tech_pvt;
02397 
02398    if (!sub) {
02399       return 1;
02400    }
02401 
02402    ast_mutex_lock(&sub->lock);
02403    ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid);
02404    if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) {
02405       sub->gate = NULL;
02406       if (sub->owner) {
02407          ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
02408          ast_channel_unlock(sub->owner);
02409       }
02410    } else {
02411       sub->gate = NULL;
02412    }
02413    ast_mutex_unlock(&sub->lock);
02414    return 1;
02415 }

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

Definition at line 713 of file chan_mgcp.c.

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

Referenced by find_command(), and send_request().

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

static int mgcp_prune_realtime_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 3725 of file chan_mgcp.c.

References ast_debug, ast_mutex_destroy, 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, free, mgcp_subchannel::gate, mgcp_gateway::ha, mgcp_subchannel::lock, mgcp_endpoint::lock, MAX_SUBS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::realtime, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::sub, and sub.

Referenced by do_monitor().

03726 {
03727    struct mgcp_endpoint *enext, *e;
03728    struct mgcp_subchannel *s, *sub;
03729    int i, prune = 1;
03730 
03731    if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) {
03732       ast_mutex_unlock(&g->msgs_lock);
03733       return 0;
03734    }
03735 
03736    for (e = g->endpoints; e; e = e->next) {
03737       ast_mutex_lock(&e->lock);
03738       if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) {
03739          prune = 0;
03740       } else if (e->rqnt_queue || e->cmd_queue) {
03741          prune = 0;
03742       }
03743       s = e->sub;
03744       for (i = 0; (i < MAX_SUBS) && s; i++) {
03745          ast_mutex_lock(&s->lock);
03746          if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) {
03747             prune = 0;
03748          } else if (s->cx_queue) {
03749             prune = 0;
03750          }
03751          s = s->next;
03752       }
03753    }
03754 
03755    for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) {
03756       for (i = 0; (i < MAX_SUBS) && sub; i++) {
03757          s = sub;
03758          sub = sub->next;
03759          ast_mutex_unlock(&s->lock);
03760          ast_mutex_unlock(&s->cx_queue_lock);
03761          if (prune) {
03762             ast_mutex_destroy(&s->lock);
03763             ast_mutex_destroy(&s->cx_queue_lock);
03764             free(s);
03765          }
03766       }
03767       ast_mutex_unlock(&e->lock);
03768       ast_mutex_unlock(&e->rqnt_queue_lock);
03769       ast_mutex_unlock(&e->cmd_queue_lock);
03770       if (prune) {
03771          ast_mutex_destroy(&e->lock);
03772          ast_mutex_destroy(&e->rqnt_queue_lock);
03773          ast_mutex_destroy(&e->cmd_queue_lock);
03774          free(e);
03775       }
03776    }
03777    if (prune) {
03778       ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name);
03779    }
03780    return prune;
03781 }

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

Definition at line 652 of file chan_mgcp.c.

References AST_FRAME_CONTROL, and mgcp_queue_frame().

Referenced by handle_hd_hf().

00653 {
00654    struct ast_frame f = { AST_FRAME_CONTROL, { control } };
00655    return mgcp_queue_frame(sub, &f);
00656 }

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

Definition at line 618 of file chan_mgcp.c.

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

Referenced by handle_request(), and mgcp_queue_control().

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

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

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

00636 {
00637    for (;;) {
00638       if (sub->owner) {
00639          if (!ast_channel_trylock(sub->owner)) {
00640             ast_queue_hangup(sub->owner);
00641             ast_channel_unlock(sub->owner);
00642             break;
00643          } else {
00644             DEADLOCK_AVOIDANCE(&sub->lock);
00645          }
00646       } else {
00647          break;
00648       }
00649    }
00650 }

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

Definition at line 1236 of file chan_mgcp.c.

References ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, f, mgcp_subchannel::lock, mgcp_rtp_read(), and sub.

01237 {
01238    struct ast_frame *f;
01239    struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
01240    ast_mutex_lock(&sub->lock);
01241    f = mgcp_rtp_read(sub);
01242    ast_mutex_unlock(&sub->lock);
01243    return f;
01244 }

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

Definition at line 4857 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, restart_monitor(), and ast_cli_entry::usage.

Referenced by reload(), and unload_module().

04858 {
04859    static int deprecated = 0;
04860 
04861    if (e) {
04862       switch (cmd) {
04863       case CLI_INIT:
04864          e->command = "mgcp reload";
04865          e->usage =
04866             "Usage: mgcp reload\n"
04867             "       'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n";
04868          return NULL;
04869       case CLI_GENERATE:
04870          return NULL;
04871       }
04872    }
04873 
04874    if (!deprecated && a && a->argc > 0) {
04875       ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
04876       deprecated = 1;
04877    }
04878 
04879    ast_mutex_lock(&mgcp_reload_lock);
04880    if (mgcp_reloading) {
04881       ast_verbose("Previous mgcp reload not yet done\n");
04882    } else {
04883       mgcp_reloading = 1;
04884    }
04885    ast_mutex_unlock(&mgcp_reload_lock);
04886    restart_monitor();
04887    return CLI_SUCCESS;
04888 }

static struct ast_channel * mgcp_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_channel requestor,
const char *  dest,
int *  cause 
) [static, read]

Definition at line 3930 of file chan_mgcp.c.

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

03931 {
03932    struct mgcp_subchannel *sub;
03933    struct ast_channel *tmpc = NULL;
03934    char tmp[256];
03935 
03936    if (!(ast_format_cap_has_joint(cap, global_capability))) {
03937       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
03938       /*return NULL;*/
03939    }
03940    ast_copy_string(tmp, dest, sizeof(tmp));
03941    if (ast_strlen_zero(tmp)) {
03942       ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
03943       return NULL;
03944    }
03945    if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) {
03946       ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
03947       *cause = AST_CAUSE_UNREGISTERED;
03948       return NULL;
03949    }
03950 
03951    ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
03952    ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
03953          sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03954    /* Must be busy */
03955    if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
03956       ((!sub->parent->callwaiting) && (sub->owner)) ||
03957        (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) {
03958       if (sub->parent->hookstate == MGCP_ONHOOK) {
03959          if (has_voicemail(sub->parent)) {
03960             transmit_notify_request(sub,"L/vmwi(+)");
03961          } else {
03962             transmit_notify_request(sub,"L/vmwi(-)");
03963          }
03964       }
03965       *cause = AST_CAUSE_BUSY;
03966       ast_mutex_unlock(&sub->lock);
03967       return NULL;
03968    }
03969    tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
03970    ast_mutex_unlock(&sub->lock);
03971    if (!tmpc)
03972       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03973    restart_monitor();
03974    return tmpc;
03975 }

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

Definition at line 1205 of file chan_mgcp.c.

References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_writeformat(), ast_debug, ast_dsp_process(), ast_format_cap_iscompatible(), ast_format_cap_set(), 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, ast_frame_subclass::format, ast_frame::frametype, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_frame::subclass.

Referenced by mgcp_read().

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

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

Definition at line 1303 of file chan_mgcp.c.

References ast_channel_tech_pvt(), 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, and sub.

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

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

Definition at line 1324 of file chan_mgcp.c.

References ast_channel_tech_pvt(), 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, sub, and transmit_notify_request().

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

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,
const struct ast_format_cap cap,
int  nat_active 
) [static]

Definition at line 4439 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_channel_tech_pvt(), sub, and transmit_modify_with_sdp().

04440 {
04441    /* XXX Is there such thing as video support with MGCP? XXX */
04442    struct mgcp_subchannel *sub;
04443    sub = ast_channel_tech_pvt(chan);
04444    if (sub && !sub->alreadygone) {
04445       transmit_modify_with_sdp(sub, rtp, cap);
04446       return 0;
04447    }
04448    return -1;
04449 }

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

Definition at line 2970 of file chan_mgcp.c.

References ast_bridged_channel(), ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_language(), ast_channel_name(), ast_channel_tech_pvt(), 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, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, ast_channel::exten, exten, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_dialed::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, ast_channel::rings, S_COR, start_rtp(), ast_party_dialed::str, sub, and transmit_notify_request().

Referenced by handle_hd_hf().

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

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

Definition at line 1246 of file chan_mgcp.c.

References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_debug, ast_format_cap_iscompatible(), 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::format, ast_frame::frametype, mgcp_subchannel::gate, GATE_ALLOCATED, mgcp_subchannel::lock, LOG_WARNING, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, cops_gate::state, mgcp_endpoint::sub, sub, ast_frame::subclass, and transmit_modify_with_sdp().

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

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

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

Referenced by do_monitor().

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

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

Definition at line 487 of file chan_mgcp.c.

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

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1864 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(), acf_vm_info(), add_agent(), add_hintdevice(), 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(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), expand_gosub_args(), extenspy_exec(), find_conf(), func_confbridge_info(), function_agent(), get_comma(), get_in_brackets_full(), gosub_exec(), handle_presencechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), jb_framedata_init(), log_exec(), login_exec(), man_do_variable_value(), mgcpsock_read(), mixmonitor_exec(), msg_send_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(), presence_read(), privacy_exec(), 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(), sip_parse_nat_option(), 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(), stop_mixmonitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), vm_playmsgexec(), xfer_park_call_helper(), and zapateller_exec().

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

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

Definition at line 1962 of file chan_mgcp.c.

References ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_is_empty(), ast_format_cap_joint_copy(), 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(), mgcp_endpoint::cap, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sdpLineNum_iterator_init().

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

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

static void prune_gateways ( void   )  [static]

Definition at line 4554 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

04555 {
04556    struct mgcp_gateway *g, *z, *r;
04557    struct mgcp_endpoint *e, *p, *t;
04558 
04559    ast_mutex_lock(&gatelock);
04560 
04561    /* prune gateways */
04562    for (z = NULL, g = gateways; g;) {
04563       /* prune endpoints */
04564       for (p = NULL, e = g->endpoints; e; ) {
04565          if (!g->realtime && (e->delme || g->delme)) {
04566             t = e;
04567             e = e->next;
04568             if (!p)
04569                g->endpoints = e;
04570             else
04571                p->next = e;
04572             destroy_endpoint(t);
04573          } else {
04574             p = e;
04575             e = e->next;
04576          }
04577       }
04578 
04579       if (g->delme) {
04580          r = g;
04581          g = g->next;
04582          if (!z)
04583             gateways = g;
04584          else
04585             z->next = g;
04586 
04587          destroy_gateway(r);
04588       } else {
04589          z = g;
04590          g = g->next;
04591       }
04592    }
04593 
04594    ast_mutex_unlock(&gatelock);
04595 }

static int reload ( void   )  [static]

Definition at line 4890 of file chan_mgcp.c.

References mgcp_reload().

04891 {
04892    mgcp_reload(NULL, 0, NULL);
04893    return 0;
04894 }

static int reload_config ( int  reload  )  [static]

Definition at line 4629 of file chan_mgcp.c.

References __ourip, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_format_cap_add(), ast_format_cap_remove(), ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_jb_read_conf(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_set_qos(), ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_gateway(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, errno, gatelock, gateways, global_jbconf, hp, ast_format::id, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, netlock, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, prune_gateways(), qos, transmit_audit_endpoint(), and ast_variable::value.

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

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

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

Definition at line 561 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, and mgcp_subchannel::parent.

Referenced by find_and_retrans().

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

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

static int restart_monitor ( void   )  [static]

Definition at line 3901 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, and monlock.

03902 {
03903    /* If we're supposed to be stopped -- stay stopped */
03904    if (monitor_thread == AST_PTHREADT_STOP)
03905       return 0;
03906    if (ast_mutex_lock(&monlock)) {
03907       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03908       return -1;
03909    }
03910    if (monitor_thread == pthread_self()) {
03911       ast_mutex_unlock(&monlock);
03912       ast_log(LOG_WARNING, "Cannot kill myself\n");
03913       return -1;
03914    }
03915    if (monitor_thread != AST_PTHREADT_NULL) {
03916       /* Wake up the thread */
03917       pthread_kill(monitor_thread, SIGURG);
03918    } else {
03919       /* Start a new monitor */
03920       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03921          ast_mutex_unlock(&monlock);
03922          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03923          return -1;
03924       }
03925    }
03926    ast_mutex_unlock(&monlock);
03927    return 0;
03928 }

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

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

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

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1606 of file chan_mgcp.c.

Referenced by process_sdp().

01607 {
01608    *iterator = 0;
01609 }

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

Definition at line 757 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 ast_sipinfo_send(), transmit_audit_endpoint(), transmit_cc_notify(), transmit_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_state_notify(), and update_connectedline().

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

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

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2937 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_call_outgoing(), handle_hd_hf(), handle_response(), mgcp_answer(), mgcp_call(), mgcp_ss(), setsubstate(), skinny_newcall(), unistim_answer(), and unistim_request().

02938 {
02939    struct ast_sockaddr bindaddr_tmp;
02940 
02941    ast_mutex_lock(&sub->lock);
02942    /* check again to be on the safe side */
02943    if (sub->rtp) {
02944       ast_rtp_instance_destroy(sub->rtp);
02945       sub->rtp = NULL;
02946    }
02947    /* Allocate the RTP now */
02948    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
02949    sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
02950    if (sub->rtp && sub->owner)
02951       ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
02952    if (sub->rtp) {
02953       ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
02954       ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
02955    }
02956    /* Make a call*ID */
02957    snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
02958    /* Transmit the connection create */
02959    if(!sub->parent->pktcgatealloc) {
02960       transmit_connect_with_sdp(sub, NULL);
02961    } else {
02962       transmit_connect(sub);
02963       sub->gate = NULL;
02964       if(!mgcp_alloc_pktcgate(sub))
02965          mgcp_queue_hangup(sub);
02966    }
02967    ast_mutex_unlock(&sub->lock);
02968 }

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

Definition at line 2649 of file chan_mgcp.c.

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

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

02650 {
02651    struct mgcp_request resp;
02652    reqprep(&resp, p, "AUEP");
02653    /* removed unknown param VS */
02654    /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
02655    add_header(&resp, "F", "A");
02656    /* fill in new fields */
02657    resp.cmd = MGCP_CMD_AUEP;
02658    resp.trid = oseq;
02659    return send_request(p, NULL, &resp, oseq);
02660 }

static int transmit_connect ( struct mgcp_subchannel sub  )  [static]

Definition at line 2444 of file chan_mgcp.c.

References add_header(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by setsubstate(), and start_rtp().

02445 {
02446    struct mgcp_request resp;
02447    char local[256];
02448    char tmp[80];
02449    struct ast_format tmpfmt;
02450    struct mgcp_endpoint *p = sub->parent;
02451 
02452    ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
02453 
02454    ast_format_cap_iter_start(p->cap);
02455    while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02456       if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
02457          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02458          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02459       }
02460    }
02461    ast_format_cap_iter_end(p->cap);
02462 
02463    ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02464           p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02465    sub->sdpsent = 0;
02466    reqprep(&resp, p, "CRCX");
02467    add_header(&resp, "C", sub->callid);
02468    add_header(&resp, "L", local);
02469    add_header(&resp, "M", "inactive");
02470    /* X header should not be sent. kept for compatibility */
02471    add_header(&resp, "X", sub->txident);
02472    /*add_header(&resp, "S", "");*/
02473    /* fill in new fields */
02474    resp.cmd = MGCP_CMD_CRCX;
02475    resp.trid = oseq;
02476    return send_request(p, sub, &resp, oseq);
02477 }

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

Definition at line 2347 of file chan_mgcp.c.

References add_header(), add_sdp(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_AUDIO, ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::gate, GATE_ALLOCATED, cops_gate::gateid, ast_format::id, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, mgcp_request::trid, and mgcp_subchannel::txident.

Referenced by start_rtp().

02348 {
02349    struct mgcp_request resp;
02350    char local[256];
02351    char tmp[80];
02352    struct ast_format tmpfmt;
02353    struct mgcp_endpoint *p = sub->parent;
02354 
02355    ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
02356        p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02357 
02358    ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
02359 
02360    ast_format_cap_iter_start(p->cap);
02361    while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02362       if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
02363          /* Audio is now discontiguous */
02364          continue;
02365       }
02366       if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
02367          snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
02368          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02369       }
02370    }
02371    ast_format_cap_iter_end(p->cap);
02372 
02373    if (sub->gate) {
02374       if(sub->gate->state == GATE_ALLOCATED) {
02375          snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
02376          strncat(local, tmp, sizeof(local) - strlen(local) - 1);
02377       }
02378    }
02379    sub->sdpsent = 1;
02380    reqprep(&resp, p, "CRCX");
02381    add_header(&resp, "C", sub->callid);
02382    add_header(&resp, "L", local);
02383    add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
02384    /* X header should not be sent. kept for compatibility */
02385    add_header(&resp, "X", sub->txident);
02386    /*add_header(&resp, "S", "");*/
02387    add_sdp(&resp, sub, rtp);
02388    /* fill in new fields */
02389    resp.cmd = MGCP_CMD_CRCX;
02390    resp.trid = oseq;
02391    return send_request(p, sub, &resp, oseq);
02392 }

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

Definition at line 2662 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_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.

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

02663 {
02664    struct mgcp_endpoint *p = sub->parent;
02665    struct mgcp_request resp;
02666 
02667    ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
02668       sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02669    reqprep(&resp, p, "DLCX");
02670    /* check if call id is avail */
02671    if (sub->callid[0])
02672       add_header(&resp, "C", sub->callid);
02673    /* X header should not be sent. kept for compatibility */
02674    add_header(&resp, "X", sub->txident);
02675    /* check if cxident is avail */
02676    if (sub->cxident[0])
02677       add_header(&resp, "I", sub->cxident);
02678    /* fill in new fields */
02679    resp.cmd = MGCP_CMD_DLCX;
02680    resp.trid = oseq;
02681    return send_request(p, sub, &resp, oseq);
02682 }

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

Definition at line 2684 of file chan_mgcp.c.

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

Referenced by handle_response().

02685 {
02686    struct mgcp_request resp;
02687 
02688    ast_debug(3, "Delete connection %s %s@%s on callid: %s\n",
02689       cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
02690    reqprep(&resp, p, "DLCX");
02691    /* check if call id is avail */
02692    if (callid && *callid)
02693       add_header(&resp, "C", callid);
02694    /* check if cxident is avail */
02695    if (cxident && *cxident)
02696       add_header(&resp, "I", cxident);
02697    /* fill in new fields */
02698    resp.cmd = MGCP_CMD_DLCX;
02699    resp.trid = oseq;
02700    return send_request(p, p->sub, &resp, oseq);
02701 }

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2550 of file chan_mgcp.c.

References add_header(), add_header_offhook(), add_sdp(), ast_copy_string(), ast_debug, ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_cap_set(), ast_rtp_lookup_mime_subtype2(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::gate, GATE_ALLOCATED, GATE_OPEN, cops_gate::gateid, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, mgcp_request::trid, and mgcp_subchannel::txident.

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

02551 {
02552    struct mgcp_request resp;
02553    struct mgcp_endpoint *p = sub->parent;
02554    struct ast_format tmpfmt;
02555    int fc = 1;
02556    char local[256];
02557    char tmp[80];
02558 
02559    if (ast_strlen_zero(sub->cxident)) {
02560       /* We don't have a CXident yet, store the destination and
02561          wait a bit */
02562       return 0;
02563    }
02564    ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
02565       p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
02566 
02567    ast_copy_string(local, "", sizeof(local));
02568    ast_format_cap_iter_start(p->cap);
02569    while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
02570       if (p->ncs && !fc) {
02571          ast_format_cap_set(p->