Fri Jun 19 12:10:16 2009

Asterisk developer's documentation


chan_mgcp.c File Reference

Implementation of Media Gateway Control Protocol. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/signal.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/event.h"

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

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

Functions

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

Variables

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


Detailed Description

Implementation of Media Gateway Control Protocol.

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

Definition in file chan_mgcp.c.


Define Documentation

#define CANREINVITE   1

Definition at line 83 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_EXPIRY   120

Definition at line 81 of file chan_mgcp.c.

#define DEFAULT_MGCP_CA_PORT   2727

From RFC 2705

Definition at line 107 of file chan_mgcp.c.

Referenced by reload_config().

#define DEFAULT_MGCP_GW_PORT   2427

From RFC 2705

Definition at line 106 of file chan_mgcp.c.

Referenced by build_gateway().

#define DEFAULT_RETRANS   1000

How frequently to retransmit

Definition at line 109 of file chan_mgcp.c.

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

#define INADDR_NONE   (in_addr_t)(-1)

Definition at line 86 of file chan_mgcp.c.

Referenced by build_gateway().

#define MAX_EXPIRY   3600

Definition at line 82 of file chan_mgcp.c.

#define MAX_RETRANS   5

Try only 5 times for retransmissions

Definition at line 110 of file chan_mgcp.c.

Referenced by retrans_pkt().

#define MAX_SUBS   2

Definition at line 268 of file chan_mgcp.c.

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

#define MGCP_CX_CONF   3

Definition at line 116 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_CONFERENCE   3

Definition at line 117 of file chan_mgcp.c.

#define MGCP_CX_INACTIVE   4

Definition at line 119 of file chan_mgcp.c.

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

#define MGCP_CX_MUTE   4

Definition at line 118 of file chan_mgcp.c.

Referenced by handle_request().

#define MGCP_CX_RECVONLY   1

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

#define MGCP_CX_SENDRECV   2

Definition at line 115 of file chan_mgcp.c.

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

#define MGCP_DTMF_HYBRID   (1 << 2)

Definition at line 104 of file chan_mgcp.c.

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

#define MGCP_DTMF_INBAND   (1 << 1)

Definition at line 103 of file chan_mgcp.c.

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

#define MGCP_DTMF_RFC2833   (1 << 0)

Definition at line 102 of file chan_mgcp.c.

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

#define MGCP_MAX_HEADERS   64

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

Definition at line 227 of file chan_mgcp.c.

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

#define MGCP_MAX_LINES   64

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

#define MGCP_OFFHOOK   2

Definition at line 302 of file chan_mgcp.c.

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

#define MGCP_ONHOOK   1

Definition at line 301 of file chan_mgcp.c.

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

#define MGCP_SUBCHANNEL_MAGIC   "!978!"

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

Definition at line 279 of file chan_mgcp.c.

Referenced by build_gateway(), and mgcp_hangup().

#define MGCPDUMPER

Definition at line 80 of file chan_mgcp.c.

#define RESPONSE_TIMEOUT   30

in seconds

Definition at line 258 of file chan_mgcp.c.

Referenced by find_and_retrans().

#define SUB_ALT   1

Definition at line 271 of file chan_mgcp.c.

#define SUB_REAL   0

Definition at line 270 of file chan_mgcp.c.

#define TYPE_LINE   2

Definition at line 305 of file chan_mgcp.c.

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

#define TYPE_TRUNK   1

Definition at line 304 of file chan_mgcp.c.

Referenced by build_device(), and build_gateway().


Enumeration Type Documentation

anonymous enum

Enumerator:
MGCP_CMD_EPCF 
MGCP_CMD_CRCX 
MGCP_CMD_MDCX 
MGCP_CMD_DLCX 
MGCP_CMD_RQNT 
MGCP_CMD_NTFY 
MGCP_CMD_AUEP 
MGCP_CMD_AUCX 
MGCP_CMD_RSIP 

Definition at line 130 of file chan_mgcp.c.

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


Function Documentation

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

Definition at line 1603 of file chan_mgcp.c.

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

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

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

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 4415 of file chan_mgcp.c.

static void __unreg_module ( void   )  [static]

Definition at line 4415 of file chan_mgcp.c.

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

Definition at line 1949 of file chan_mgcp.c.

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

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

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

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

Definition at line 2344 of file chan_mgcp.c.

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

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

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

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

Definition at line 1971 of file chan_mgcp.c.

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

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

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

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

Definition at line 2072 of file chan_mgcp.c.

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

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

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

static int attempt_transfer ( struct mgcp_endpoint p  )  [static]

Definition at line 2909 of file chan_mgcp.c.

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

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

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

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

Definition at line 3577 of file chan_mgcp.c.

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

Referenced by reload_config().

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

static char* control2str ( int  ind  )  [static]

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

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

static void destroy_endpoint ( struct mgcp_endpoint e  )  [static]

Definition at line 4002 of file chan_mgcp.c.

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

Referenced by prune_gateways().

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

static void destroy_gateway ( struct mgcp_gateway g  )  [static]

Definition at line 4048 of file chan_mgcp.c.

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

04049 {
04050    if (g->ha)
04051       ast_free_ha(g->ha);
04052 
04053    dump_queue(g, NULL);
04054 
04055    ast_free(g);
04056 }

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

Definition at line 3408 of file chan_mgcp.c.

References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, gateways, has_voicemail(), io, MGCP_ONHOOK, mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), monlock, netlock, reload_config(), transmit_notify_request(), and TYPE_LINE.

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

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

dump_cmd_queues: (SC:) cleanup pending commands

Definition at line 2413 of file chan_mgcp.c.

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

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

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

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

Definition at line 554 of file chan_mgcp.c.

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

Referenced by destroy_gateway(), and handle_request().

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

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

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

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

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

find_command: (SC:) remove command transaction from queue

Definition at line 2447 of file chan_mgcp.c.

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

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

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

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

Definition at line 1650 of file chan_mgcp.c.

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

Referenced by mgcp_request(), and mgcpsock_read().

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

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

get_csv: (SC:) get comma separated value

Definition at line 1629 of file chan_mgcp.c.

References s.

Referenced by handle_response().

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

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

Definition at line 1622 of file chan_mgcp.c.

References __get_header().

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

01623 {
01624    int start = 0;
01625    return __get_header(req, name, &start);
01626 }

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

Definition at line 1574 of file chan_mgcp.c.

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

Referenced by process_sdp().

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

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

Definition at line 1564 of file chan_mgcp.c.

Referenced by get_sdp(), and get_sdp_iterate().

01565 {
01566    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
01567       char* r = line + nameLen + 1;
01568       while (*r && (*r < 33)) ++r;
01569       return r;
01570    }
01571    return "";
01572 }

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

Definition at line 1592 of file chan_mgcp.c.

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

Referenced by get_sdp(), and process_sdp().

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

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

Definition at line 2963 of file chan_mgcp.c.

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

Referenced by handle_request().

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

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

Definition at line 1076 of file chan_mgcp.c.

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

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

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

Definition at line 1166 of file chan_mgcp.c.

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

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

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

Definition at line 1141 of file chan_mgcp.c.

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

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

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

Definition at line 1036 of file chan_mgcp.c.

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

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

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

Definition at line 3045 of file chan_mgcp.c.

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

Referenced by mgcpsock_read().

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

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

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

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

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

static int has_voicemail ( struct mgcp_endpoint p  )  [static]

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

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

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

Definition at line 2011 of file chan_mgcp.c.

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

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

02012 {
02013    /* Initialize a response */
02014    if (req->headers || req->len) {
02015       ast_log(LOG_WARNING, "Request already initialized?!?\n");
02016       return -1;
02017    }
02018    req->header[req->headers] = req->data + req->len;
02019    /* check if we need brackets around the gw name */
02020    if (p->parent->isnamedottedip)
02021       snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
02022    else
02023       snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
02024    req->len += strlen(req->header[req->headers]);
02025    if (req->headers < MGCP_MAX_HEADERS)
02026       req->headers++;
02027    else
02028       ast_log(LOG_WARNING, "Out of header space\n");
02029    return 0;
02030 }

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

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

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

static int load_module ( void   )  [static]

load_module: PBX load module - initialization ---

Definition at line 4277 of file chan_mgcp.c.

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

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

static int mgcp_answer ( struct ast_channel ast  )  [static]

Definition at line 1202 of file chan_mgcp.c.

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

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

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

Definition at line 842 of file chan_mgcp.c.

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

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

static int mgcp_devicestate ( void *  data  )  [static]

mgcp_devicestate: channel callback for device status monitoring

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

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

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

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

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

Definition at line 1298 of file chan_mgcp.c.

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

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

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

Definition at line 3969 of file chan_mgcp.c.

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

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

static int mgcp_hangup ( struct ast_channel ast  )  [static]

Definition at line 935 of file chan_mgcp.c.

References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_debug, ast_dsp_free(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcpdebug, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().

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

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

Definition at line 1451 of file chan_mgcp.c.

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

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

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

Definition at line 1495 of file chan_mgcp.c.

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

Referenced by handle_hd_hf(), and mgcp_request().

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

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

Definition at line 692 of file chan_mgcp.c.

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

Referenced by find_command(), and send_request().

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

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

Definition at line 623 of file chan_mgcp.c.

References AST_FRAME_CONTROL, f, and mgcp_queue_frame().

Referenced by handle_hd_hf().

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

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

Definition at line 591 of file chan_mgcp.c.

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

Referenced by handle_request(), and mgcp_queue_control().

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

static void mgcp_queue_hangup ( struct mgcp_subchannel sub  )  [static]

Definition at line 607 of file chan_mgcp.c.

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

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

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

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

Definition at line 1258 of file chan_mgcp.c.

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

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

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

Definition at line 4310 of file chan_mgcp.c.

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

Referenced by reload(), and unload_module().

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

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

Definition at line 3523 of file chan_mgcp.c.

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

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

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

Definition at line 1227 of file chan_mgcp.c.

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

Referenced by mgcp_read().

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

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

Definition at line 1314 of file chan_mgcp.c.

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

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

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

Definition at line 1335 of file chan_mgcp.c.

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

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

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

Definition at line 3984 of file chan_mgcp.c.

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

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

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

Definition at line 2662 of file chan_mgcp.c.

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

Referenced by handle_hd_hf().

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

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

Definition at line 1268 of file chan_mgcp.c.

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

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

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

Definition at line 3319 of file chan_mgcp.c.

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

Referenced by do_monitor().

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

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

Definition at line 453 of file chan_mgcp.c.

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

static void parse ( struct mgcp_request req  )  [static]

Definition at line 1762 of file chan_mgcp.c.

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

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

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

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

Definition at line 1863 of file chan_mgcp.c.

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

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

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

static void prune_gateways ( void   )  [static]

Definition at line 4058 of file chan_mgcp.c.

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

Referenced by reload_config(), and unload_module().

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

static int reload ( void   )  [static]

Definition at line 4342 of file chan_mgcp.c.

References mgcp_reload().

04343 {
04344    mgcp_reload(NULL, 0, NULL);
04345    return 0;
04346 }

static int reload_config ( int  reload  )  [static]

Definition at line 4101 of file chan_mgcp.c.

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

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

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

Definition at line 2040 of file chan_mgcp.c.

References init_req(), and oseq.

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

02041 {
02042    memset(req, 0, sizeof(struct mgcp_request));
02043    oseq++;
02044    if (oseq > 999999999)
02045       oseq = 1;
02046    init_req(p, req, verb);
02047    return 0;
02048 }

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

Definition at line 527 of file chan_mgcp.c.

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

Referenced by find_and_retrans().

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

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

Definition at line 2033 of file chan_mgcp.c.

References init_resp().

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

02034 {
02035    memset(resp, 0, sizeof(*resp));
02036    init_resp(resp, msg, req, msgrest);
02037    return 0;
02038 }

static int restart_monitor ( void   )  [static]

Definition at line 3494 of file chan_mgcp.c.

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

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

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

Definition at line 630 of file chan_mgcp.c.

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

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

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

static void sdpLineNum_iterator_init ( int *  iterator  )  [static]

Definition at line 1587 of file chan_mgcp.c.

Referenced by process_sdp().

01588 {
01589    *iterator = 0;
01590 }

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(), ast_verbose, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::data, mgcp_request::len, LOG_WARNING, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcpdebug, mgcp_request::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.

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

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          while (q) {
00778             r = q->next;
00779             ast_free(q);
00780             q = r;
00781          }
00782          *queue = NULL;
00783          break;
00784 
00785       case MGCP_CMD_CRCX:
00786       case MGCP_CMD_MDCX:
00787          queue = &sub->cx_queue;
00788          l = &sub->cx_queue_lock;
00789          ast_mutex_lock(l);
00790          break;
00791 
00792       case MGCP_CMD_RQNT:
00793          queue = &p->rqnt_queue;
00794          l = &p->rqnt_queue_lock;
00795          ast_mutex_lock(l);
00796          break;
00797 
00798       default:
00799          queue = &p->cmd_queue;
00800          l = &p->cmd_queue_lock;
00801          ast_mutex_lock(l);
00802          break;
00803       }
00804    }
00805 
00806    r = ast_malloc(sizeof(*r));
00807    if (!r) {
00808       ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
00809       ast_mutex_unlock(l);
00810       return -1;
00811    }
00812    memcpy(r, req, sizeof(*r));
00813 
00814    if (!(*queue)) {
00815       if (mgcpdebug) {
00816          ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
00817             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00818       }
00819 
00820       res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
00821    } else {
00822       if (mgcpdebug) {
00823          ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
00824             ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
00825       }
00826    }
00827 
00828    /* XXX find tail. We could also keep tail in the data struct for faster access */
00829    for (t = *queue; t && t->next; t = t->next);
00830 
00831    r->next = NULL;
00832    if (t)
00833       t->next = r;
00834    else
00835       *queue = r;
00836 
00837    ast_mutex_unlock(l);
00838 
00839    return res;
00840 }

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

Definition at line 540 of file chan_mgcp.c.

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

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

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

static void start_rtp ( struct mgcp_subchannel sub  )  [static]

Definition at line 2635 of file chan_mgcp.c.

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

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

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

static int transmit_audit_endpoint ( struct mgcp_endpoint p  )  [static]

Definition at line 2354 of file chan_mgcp.c.

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

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

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

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

Definition at line 2201 of file chan_mgcp.c.

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

Referenced by start_rtp().

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

static int transmit_connection_del ( struct mgcp_subchannel sub  )  [static]

Definition at line 2367 of file chan_mgcp.c.

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

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

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

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

Definition at line 2391 of file chan_mgcp.c.

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

Referenced by handle_response().

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

static int transmit_modify_request ( struct mgcp_subchannel sub  )  [static]

Definition at line 2309 of file chan_mgcp.c.

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

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

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

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

Definition at line 2165 of file chan_mgcp.c.

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

Referenced by handle_response(), and mgcp_set_rtp_peer().

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

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

Definition at line 2234 of file chan_mgcp.c.

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

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

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

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

Definition at line 2263 of file chan_mgcp.c.

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

Referenced by mgcp_call(), and mgcp_hangup().

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

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

Definition at line 2050 of file chan_mgcp.c.

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

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

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

static int unalloc_sub ( struct mgcp_subchannel sub  )  [static]

Definition at line 486 of file chan_mgcp.c.

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

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

static int unload_module ( void   )  [static]

Definition at line 4348 of file chan_mgcp.c.

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

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


Variable Documentation

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

Definition at line 4415 of file chan_mgcp.c.

struct in_addr __ourip [static]

Definition at line 217 of file chan_mgcp.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 182 of file chan_mgcp.c.

int adsi = 0 [static]

Definition at line 188 of file chan_mgcp.c.

int amaflags = 0 [static]

Definition at line 186 of file chan_mgcp.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 4415 of file chan_mgcp.c.

struct sockaddr_in bindaddr [static]

Definition at line 404 of file chan_mgcp.c.

int callreturn = 0 [static]

Definition at line 167 of file chan_mgcp.c.

Referenced by build_gateway().

int callwaiting = 0 [static]

Definition at line 165 of file chan_mgcp.c.

Referenced by build_gateway().

int cancallforward = 0 [static]

Definition at line 176 of file chan_mgcp.c.

Referenced by build_gateway().

int canreinvite = CANREINVITE [static]

Definition at line 180 of file chan_mgcp.c.

Referenced by build_gateway().

int capability = AST_FORMAT_ULAW [static]

Definition at line 213 of file chan_mgcp.c.

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

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 148 of file chan_mgcp.c.

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

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 147 of file chan_mgcp.c.

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

struct ast_cli_entry cli_mgcp[] [static]

Definition at line 1195 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

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

Definition at line 1194 of file chan_mgcp.c.

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

Definition at line 100 of file chan_mgcp.c.

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

Definition at line 142 of file chan_mgcp.c.

unsigned int cos

Definition at line 159 of file chan_mgcp.c.

unsigned int cos_audio

Definition at line 160 of file chan_mgcp.c.

ast_group_t cur_callergroup = 0 [static]

Definition at line 153 of file chan_mgcp.c.

Referenced by build_gateway().

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 154 of file chan_mgcp.c.

Referenced by build_gateway().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 90 of file chan_mgcp.c.

int dtmfmode = 0 [static]

Definition at line 150 of file chan_mgcp.c.

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

int firstdigittimeout = 16000 [static]

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

Definition at line 193 of file chan_mgcp.c.

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

gatelock: mutex for gateway/endpoint lists

Definition at line 400 of file chan_mgcp.c.

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

struct mgcp_gateway * gateways [static]

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

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic)

Definition at line 196 of file chan_mgcp.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 97 of file chan_mgcp.c.

int immediate = 0 [static]

Definition at line 163 of file chan_mgcp.c.

Referenced by build_gateway().

struct io_context* io [static]

Definition at line 223 of file chan_mgcp.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 144 of file chan_mgcp.c.

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 184 of file chan_mgcp.c.

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

int matchdigittimeout = 3000 [static]

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

Definition at line 199 of file chan_mgcp.c.

char* mgcp_cxmodes[] [static]

}

Definition at line 122 of file chan_mgcp.c.

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

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

Definition at line 396 of file chan_mgcp.c.

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

int mgcp_reloading = 0 [static]

Definition at line 397 of file chan_mgcp.c.

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

struct ast_rtp_protocol mgcp_rtp [static]

Initial value:

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

Definition at line 3996 of file chan_mgcp.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech mgcp_tech [static]

Definition at line 434 of file chan_mgcp.c.

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

int mgcpdebug = 0 [static]

Definition at line 220 of file chan_mgcp.c.

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

int mgcpsock = -1 [static]

Definition at line 402 of file chan_mgcp.c.

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

int* mgcpsock_read_id = NULL [static]

Definition at line 3406 of file chan_mgcp.c.

Referenced by reload_config().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 209 of file chan_mgcp.c.

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

Definition at line 205 of file chan_mgcp.c.

char musicclass[MAX_MUSICCLASS] = "" [static]

Definition at line 145 of file chan_mgcp.c.

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

int nat = 0 [static]

Definition at line 151 of file chan_mgcp.c.

Referenced by build_gateway().

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

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

Definition at line 203 of file chan_mgcp.c.

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

int nonCodecCapability = AST_RTP_DTMF [static]

Definition at line 214 of file chan_mgcp.c.

Referenced by process_sdp().

unsigned int oseq [static]

Definition at line 190 of file chan_mgcp.c.

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

char ourhost[MAXHOSTNAMELEN] [static]

Definition at line 216 of file chan_mgcp.c.

Referenced by ast_find_ourip(), and reload_config().

int ourport [static]

Definition at line 218 of file chan_mgcp.c.

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

char parkinglot[AST_MAX_CONTEXT] [static]

Definition at line 146 of file chan_mgcp.c.

struct { ... } qos [static]

struct sched_context* sched [static]

Definition at line 222 of file chan_mgcp.c.

int singlepath = 0 [static]

Definition at line 178 of file chan_mgcp.c.

Referenced by build_gateway().

int slowsequence = 0 [static]

Definition at line 169 of file chan_mgcp.c.

Referenced by build_gateway().

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

Definition at line 99 of file chan_mgcp.c.

int threewaycalling = 0 [static]

Definition at line 171 of file chan_mgcp.c.

Referenced by build_gateway().

unsigned int tos

Definition at line 157 of file chan_mgcp.c.

unsigned int tos_audio

Definition at line 158 of file chan_mgcp.c.

int transfer = 0 [static]

This is for flashhook transfers

Definition at line 174 of file chan_mgcp.c.

Referenced by build_gateway(), and leave_voicemail().


Generated on Fri Jun 19 12:10:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7