#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/signal.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/event.h"
#include "asterisk/chanvars.h"
#include "asterisk/pktccops.h"
Go to the source code of this file.
Data Structures | |
struct | mgcp_endpoint |
struct | mgcp_gateway |
struct | mgcp_message |
mgcp_message: MGCP message for queuing up More... | |
struct | mgcp_request |
struct | mgcp_response |
struct | mgcp_subchannel |
Defines | |
#define | DEFAULT_EXPIRY 120 |
#define | DEFAULT_MGCP_CA_PORT 2727 |
#define | DEFAULT_MGCP_GW_PORT 2427 |
#define | DEFAULT_RETRANS 1000 |
#define | DIRECTMEDIA 1 |
#define | INADDR_NONE (in_addr_t)(-1) |
#define | MAX_EXPIRY 3600 |
#define | MAX_RETRANS 5 |
#define | MAX_SUBS 2 |
#define | MGCP_CX_CONF 3 |
#define | MGCP_CX_CONFERENCE 3 |
#define | MGCP_CX_INACTIVE 4 |
#define | MGCP_CX_MUTE 4 |
#define | MGCP_CX_RECVONLY 1 |
#define | MGCP_CX_SENDONLY 0 |
#define | MGCP_CX_SENDRECV 2 |
#define | MGCP_DTMF_HYBRID (1 << 2) |
#define | MGCP_DTMF_INBAND (1 << 1) |
#define | MGCP_DTMF_RFC2833 (1 << 0) |
#define | MGCP_MAX_HEADERS 64 |
#define | MGCP_MAX_LINES 64 |
#define | MGCP_MAX_PACKET 1500 |
#define | MGCP_OFFHOOK 2 |
#define | MGCP_ONHOOK 1 |
#define | MGCP_SUBCHANNEL_MAGIC "!978!" |
#define | MGCPDUMPER |
#define | RESPONSE_TIMEOUT 30 |
#define | SUB_ALT 1 |
#define | SUB_REAL 0 |
#define | TYPE_LINE 2 |
#define | TYPE_TRUNK 1 |
Enumerations | |
enum | { MGCP_CMD_EPCF, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_CMD_DLCX, MGCP_CMD_RQNT, MGCP_CMD_NTFY, MGCP_CMD_AUEP, MGCP_CMD_AUCX, MGCP_CMD_RSIP } |
Functions | |
static char * | __get_header (struct mgcp_request *req, char *name, int *start, char *def) |
static int | __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len) |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen) |
static int | add_header (struct mgcp_request *req, const char *var, const char *value) |
static void | add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone) |
static int | add_line (struct mgcp_request *req, char *line) |
static int | add_sdp (struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp) |
static struct ast_variable * | add_var (const char *buf, struct ast_variable *list) |
static int | attempt_transfer (struct mgcp_endpoint *p) |
static struct mgcp_gateway * | build_gateway (char *cat, struct ast_variable *v) |
build_gateway: parse mgcp.conf and create gateway/endpoint structures | |
static char * | control2str (int ind) |
static struct ast_variable * | copy_vars (struct ast_variable *src) |
duplicate a list of channel variables, | |
static void | destroy_endpoint (struct mgcp_endpoint *e) |
static void | destroy_gateway (struct mgcp_gateway *g) |
static void * | do_monitor (void *data) |
static void | dump_cmd_queues (struct mgcp_endpoint *p, struct mgcp_subchannel *sub) |
dump_cmd_queues: (SC:) cleanup pending commands | |
static void | dump_queue (struct mgcp_gateway *gw, struct mgcp_endpoint *p) |
static int | find_and_retrans (struct mgcp_subchannel *sub, struct mgcp_request *req) |
static struct mgcp_request * | find_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_gateway * | find_realtime_gw (char *name, char *at, struct sockaddr_in *sin) |
static struct mgcp_subchannel * | find_subchannel_and_lock (char *name, int msgid, struct sockaddr_in *sin) |
static char * | get_csv (char *c, int *len, char **next) |
get_csv: (SC:) get comma separated value | |
static char * | get_header (struct mgcp_request *req, char *name) |
static char * | get_sdp (struct mgcp_request *req, char *name) |
static char * | get_sdp_by_line (char *line, char *name, int nameLen) |
static char * | get_sdp_iterate (int *iterator, struct mgcp_request *req, char *name) |
static void | handle_hd_hf (struct mgcp_subchannel *sub, char *ev) |
static char * | handle_mgcp_audit_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mgcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mgcp_show_endpoints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin) |
static void | handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp) |
static int | has_voicemail (struct mgcp_endpoint *p) |
static int | init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb) |
static int | init_resp (struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest) |
static int | load_module (void) |
load_module: PBX load module - initialization --- | |
static int | mgcp_alloc_pktcgate (struct mgcp_subchannel *sub) |
static int | mgcp_answer (struct ast_channel *ast) |
static int | mgcp_call (struct ast_channel *ast, char *dest, int timeout) |
static int | mgcp_devicestate (void *data) |
mgcp_devicestate: channel callback for device status monitoring | |
static int | mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static format_t | mgcp_get_codec (struct ast_channel *chan) |
static enum ast_rtp_glue_result | mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
static int | mgcp_hangup (struct ast_channel *ast) |
static int | mgcp_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen) |
static struct ast_channel * | mgcp_new (struct mgcp_subchannel *sub, int state, const char *linkedid) |
static int | mgcp_pktcgate_open (struct cops_gate *gate) |
static int | mgcp_pktcgate_remove (struct cops_gate *gate) |
static int | mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno) |
static int | mgcp_prune_realtime_gateway (struct mgcp_gateway *g) |
static void | mgcp_queue_control (struct mgcp_subchannel *sub, int control) |
static void | mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f) |
static void | mgcp_queue_hangup (struct mgcp_subchannel *sub) |
static struct ast_frame * | mgcp_read (struct ast_channel *ast) |
static char * | mgcp_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static struct ast_channel * | mgcp_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause) |
static struct ast_frame * | mgcp_rtp_read (struct mgcp_subchannel *sub) |
static int | mgcp_senddigit_begin (struct ast_channel *ast, char digit) |
static int | mgcp_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration) |
static int | mgcp_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active) |
static void * | mgcp_ss (void *data) |
static int | mgcp_write (struct ast_channel *ast, struct ast_frame *frame) |
static int | mgcpsock_read (int *id, int fd, short events, void *ignore) |
static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
static void | parse (struct mgcp_request *req) |
static int | process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req) |
static void | prune_gateways (void) |
static int | reload (void) |
static int | reload_config (int reload) |
static int | reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb) |
static int | resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp) |
static int | respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest) |
static int | restart_monitor (void) |
static int | retrans_pkt (const void *data) |
static void | sdpLineNum_iterator_init (int *iterator) |
static int | send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno) |
static int | send_response (struct mgcp_subchannel *sub, struct mgcp_request *req) |
static void | start_rtp (struct mgcp_subchannel *sub) |
static int | transmit_audit_endpoint (struct mgcp_endpoint *p) |
static int | transmit_connect (struct mgcp_subchannel *sub) |
static int | transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp) |
static int | transmit_connection_del (struct mgcp_subchannel *sub) |
static int | transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident) |
static int | transmit_modify_request (struct mgcp_subchannel *sub) |
static int | transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, format_t codecs) |
static int | transmit_notify_request (struct mgcp_subchannel *sub, char *tone) |
static int | transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername) |
static int | transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest) |
static int | unalloc_sub (struct mgcp_subchannel *sub) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } |
static struct in_addr | __ourip |
static char | accountcode [AST_MAX_ACCOUNT_CODE] = "" |
static int | adsi = 0 |
static int | amaflags = 0 |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct sockaddr_in | bindaddr |
static int | callreturn = 0 |
static int | callwaiting = 0 |
static int | cancallforward = 0 |
static format_t | capability = AST_FORMAT_ULAW |
static char | cid_name [AST_MAX_EXTENSION] = "" |
static char | cid_num [AST_MAX_EXTENSION] = "" |
static struct ast_cli_entry | cli_mgcp [] |
static const char | config [] = "mgcp.conf" |
static char | context [AST_MAX_EXTENSION] = "default" |
static ast_group_t | cur_callergroup = 0 |
static ast_group_t | cur_pickupgroup = 0 |
static struct ast_jb_conf | default_jbconf |
static int | directmedia = DIRECTMEDIA |
static int | dtmfmode = 0 |
static int | firstdigittimeout = 16000 |
static ast_mutex_t | gatelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
gatelock: mutex for gateway/endpoint lists | |
static struct mgcp_gateway * | gateways |
static int | gendigittimeout = 8000 |
static struct ast_jb_conf | global_jbconf |
static int | hangupongateremove = 0 |
static int | immediate = 0 |
static struct io_context * | io |
static char | language [MAX_LANGUAGE] = "" |
static char | mailbox [AST_MAX_EXTENSION] |
static int | matchdigittimeout = 3000 |
static const char *const | mgcp_cxmodes [] |
static ast_mutex_t | mgcp_reload_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
static int | mgcp_reloading = 0 |
static struct ast_rtp_glue | mgcp_rtp_glue |
static struct ast_channel_tech | mgcp_tech |
static int | mgcpdebug = 0 |
static int | mgcpsock = -1 |
static int * | mgcpsock_read_id = NULL |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
static ast_mutex_t | monlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
static char | musicclass [MAX_MUSICCLASS] = "" |
static int | nat = 0 |
static int | ncs = 0 |
static ast_mutex_t | netlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } |
static int | nonCodecCapability = AST_RTP_DTMF |
static unsigned int | oseq |
static char | ourhost [MAXHOSTNAMELEN] |
static int | ourport |
static char | parkinglot [AST_MAX_CONTEXT] |
static int | pktcgatealloc = 0 |
struct { | |
unsigned int cos | |
unsigned int cos_audio | |
unsigned int tos | |
unsigned int tos_audio | |
} | qos |
static struct sched_context * | sched |
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 |
Definition in file chan_mgcp.c.
#define DEFAULT_EXPIRY 120 |
Definition at line 88 of file chan_mgcp.c.
#define DEFAULT_MGCP_CA_PORT 2727 |
From RFC 2705
Definition at line 115 of file chan_mgcp.c.
#define DEFAULT_MGCP_GW_PORT 2427 |
From RFC 2705
Definition at line 114 of file chan_mgcp.c.
#define DEFAULT_RETRANS 1000 |
How frequently to retransmit
Definition at line 117 of file chan_mgcp.c.
Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt().
#define DIRECTMEDIA 1 |
#define INADDR_NONE (in_addr_t)(-1) |
Definition at line 93 of file chan_mgcp.c.
#define MAX_EXPIRY 3600 |
Definition at line 89 of file chan_mgcp.c.
#define MAX_RETRANS 5 |
Try only 5 times for retransmissions
Definition at line 118 of file chan_mgcp.c.
Referenced by retrans_pkt().
#define MAX_SUBS 2 |
Definition at line 281 of file chan_mgcp.c.
Referenced by mgcp_prune_realtime_gateway(), reload_config(), and unistim_info().
#define MGCP_CX_CONF 3 |
#define MGCP_CX_CONFERENCE 3 |
Definition at line 125 of file chan_mgcp.c.
#define MGCP_CX_INACTIVE 4 |
#define MGCP_CX_MUTE 4 |
#define MGCP_CX_RECVONLY 1 |
Definition at line 122 of file chan_mgcp.c.
Referenced by handle_request(), mgcp_call(), and mgcp_hangup().
#define MGCP_CX_SENDONLY 0 |
MGCP rtp stream modes {
Definition at line 121 of file chan_mgcp.c.
#define MGCP_CX_SENDRECV 2 |
Definition at line 123 of file chan_mgcp.c.
Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), and mgcp_call().
#define MGCP_DTMF_HYBRID (1 << 2) |
Definition at line 112 of file chan_mgcp.c.
Referenced by add_header_offhook(), mgcp_hangup(), mgcp_new(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().
#define MGCP_DTMF_INBAND (1 << 1) |
Definition at line 111 of file chan_mgcp.c.
Referenced by add_header_offhook(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().
#define MGCP_DTMF_RFC2833 (1 << 0) |
Definition at line 110 of file chan_mgcp.c.
Referenced by mgcp_rtp_read(), mgcp_senddigit_begin(), and mgcp_senddigit_end().
#define MGCP_MAX_HEADERS 64 |
The private structures of the mgcp channels are linked for selecting outgoing channels
Definition at line 240 of file chan_mgcp.c.
Referenced by add_header(), init_req(), init_resp(), and parse().
#define MGCP_MAX_LINES 64 |
#define MGCP_MAX_PACKET 1500 |
Also from RFC 2543, should sub headers tho
Definition at line 116 of file chan_mgcp.c.
#define MGCP_OFFHOOK 2 |
Definition at line 317 of file chan_mgcp.c.
Referenced by handle_hd_hf(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), transmit_notify_request(), and transmit_notify_request_with_callerid().
#define MGCP_ONHOOK 1 |
Definition at line 316 of file chan_mgcp.c.
Referenced by do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
#define MGCP_SUBCHANNEL_MAGIC "!978!" |
subchannel magic string. Needed to prove that any subchannel pointer passed by asterisk really points to a valid subchannel memory area. Ugly.. But serves the purpose for the time being.
Definition at line 292 of file chan_mgcp.c.
Referenced by mgcp_hangup().
#define MGCPDUMPER |
Definition at line 87 of file chan_mgcp.c.
#define RESPONSE_TIMEOUT 30 |
#define SUB_ALT 1 |
Definition at line 284 of file chan_mgcp.c.
#define SUB_REAL 0 |
Definition at line 283 of file chan_mgcp.c.
#define TYPE_LINE 2 |
Definition at line 320 of file chan_mgcp.c.
Referenced by config_line(), config_parse_variables(), do_monitor(), and mgcp_call().
#define TYPE_TRUNK 1 |
Definition at line 319 of file chan_mgcp.c.
anonymous 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 |
Definition at line 138 of file chan_mgcp.c.
00138 { 00139 MGCP_CMD_EPCF, 00140 MGCP_CMD_CRCX, 00141 MGCP_CMD_MDCX, 00142 MGCP_CMD_DLCX, 00143 MGCP_CMD_RQNT, 00144 MGCP_CMD_NTFY, 00145 MGCP_CMD_AUEP, 00146 MGCP_CMD_AUCX, 00147 MGCP_CMD_RSIP 00148 };
static char* __get_header | ( | struct mgcp_request * | req, | |
char * | name, | |||
int * | start, | |||
char * | def | |||
) | [static] |
Definition at line 1609 of file chan_mgcp.c.
References mgcp_request::header, mgcp_request::headers, and len().
Referenced by build_route(), copy_all_header(), copy_via_headers(), func_header_read(), get_header(), handle_incoming(), handle_request_subscribe(), handle_response_register(), and parse_register_contact().
01610 { 01611 int x; 01612 int len = strlen(name); 01613 char *r; 01614 for (x = *start; x < req->headers; x++) { 01615 if (!strncasecmp(req->header[x], name, len) && 01616 (req->header[x][len] == ':')) { 01617 r = req->header[x] + len + 1; 01618 while (*r && (*r < 33)) { 01619 r++; 01620 } 01621 *start = x + 1; 01622 return r; 01623 } 01624 } 01625 /* Don't return NULL, so get_header is always a valid pointer */ 01626 return def; 01627 }
static int __mgcp_xmit | ( | struct mgcp_gateway * | gw, | |
char * | data, | |||
int | len | |||
) | [static] |
Definition at line 542 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_log(), mgcp_gateway::defaddr, errno, and LOG_WARNING.
Referenced by mgcp_postrequest(), resend_response(), retrans_pkt(), and send_response().
00543 { 00544 int res; 00545 if (gw->addr.sin_addr.s_addr) 00546 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); 00547 else 00548 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); 00549 if (res != len) { 00550 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); 00551 } 00552 return res; 00553 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 4919 of file chan_mgcp.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4919 of file chan_mgcp.c.
static int acf_channel_read | ( | struct ast_channel * | chan, | |
const char * | funcname, | |||
char * | preparse, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 4440 of file chan_mgcp.c.
References ast_log(), LOG_ERROR, mgcp_tech, mgcp_endpoint::ncs, mgcp_subchannel::parent, ast_channel::tech, and ast_channel::tech_pvt.
04441 { 04442 struct mgcp_subchannel *sub = chan->tech_pvt; 04443 int res = 0; 04444 04445 /* Sanity check */ 04446 if (!chan || chan->tech != &mgcp_tech) { 04447 ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n"); 04448 return -1; 04449 } 04450 04451 if (!strcasecmp(args, "ncs")) { 04452 snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no"); 04453 } else { 04454 res = -1; 04455 } 04456 return res; 04457 }
static int add_header | ( | struct mgcp_request * | req, | |
const char * | var, | |||
const char * | value | |||
) | [static] |
Definition at line 2038 of file chan_mgcp.c.
References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_request::len, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_HEADERS.
Referenced by __transmit_response(), add_cc_call_info_to_response(), add_digit(), add_diversion_header(), add_header_max_forwards(), add_header_offhook(), add_route(), add_rpid(), add_sdp(), add_supported_header(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), finalize_content(), initreqprep(), reqprep(), respprep(), transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_invite(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sip_etag(), transmit_response_with_unsupported(), transmit_state_notify(), and update_connectedline().
02039 { 02040 if (req->len >= sizeof(req->data) - 4) { 02041 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02042 return -1; 02043 } 02044 if (req->lines) { 02045 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 02046 return -1; 02047 } 02048 req->header[req->headers] = req->data + req->len; 02049 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); 02050 req->len += strlen(req->header[req->headers]); 02051 if (req->headers < MGCP_MAX_HEADERS) { 02052 req->headers++; 02053 } else { 02054 ast_log(LOG_WARNING, "Out of header space\n"); 02055 return -1; 02056 } 02057 return 0; 02058 }
static void add_header_offhook | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | resp, | |||
char * | tone | |||
) | [static] |
Definition at line 2592 of file chan_mgcp.c.
References ast_channel::_state, add_header(), ast_debug, AST_STATE_RINGING, mgcp_endpoint::dtmfmode, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_endpoint::ncs, mgcp_subchannel::owner, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by transmit_notify_request(), and transmit_notify_request_with_callerid().
02593 { 02594 struct mgcp_endpoint *p = sub->parent; 02595 char tone_indicate_end = 0; 02596 02597 /* We also should check the tone to indicate, because it have no sense 02598 to request notify D/[0-9#*] (dtmf keys) if we are sending congestion 02599 tone for example G/cg */ 02600 if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) { 02601 tone_indicate_end = 1; 02602 } 02603 02604 if (p && p->sub && p->sub->owner && 02605 p->sub->owner->_state >= AST_STATE_RINGING && 02606 (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) { 02607 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02608 02609 } else if (!tone_indicate_end){ 02610 add_header(resp, "R", (p->ncs ? "L/hu(N),L/hf(N),L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)")); 02611 } else { 02612 ast_debug(1, "We don't want more digits if we will end the call\n"); 02613 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02614 } 02615 }
static int add_line | ( | struct mgcp_request * | req, | |
char * | line | |||
) | [static] |
Definition at line 2060 of file chan_mgcp.c.
References ast_copy_string(), ast_log(), mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES.
02061 { 02062 if (req->len >= sizeof(req->data) - 4) { 02063 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02064 return -1; 02065 } 02066 if (!req->lines) { 02067 /* Add extra empty return */ 02068 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); 02069 req->len += strlen(req->data + req->len); 02070 } 02071 req->line[req->lines] = req->data + req->len; 02072 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 02073 req->len += strlen(req->line[req->lines]); 02074 if (req->lines < MGCP_MAX_LINES) { 02075 req->lines++; 02076 } else { 02077 ast_log(LOG_WARNING, "Out of line space\n"); 02078 return -1; 02079 } 02080 return 0; 02081 }
static int add_sdp | ( | struct mgcp_request * | resp, | |
struct mgcp_subchannel * | sub, | |||
struct ast_rtp_instance * | rtp | |||
) | [static] |
Definition at line 2170 of file chan_mgcp.c.
References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, mgcp_endpoint::capability, len(), LOG_WARNING, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.
Referenced by transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and update_connectedline().
02171 { 02172 int len; 02173 int codec; 02174 char costr[80]; 02175 struct sockaddr_in sin; 02176 struct ast_sockaddr sin_tmp; 02177 char v[256]; 02178 char s[256]; 02179 char o[256]; 02180 char c[256]; 02181 char t[256]; 02182 char m[256] = ""; 02183 char a[1024] = ""; 02184 format_t x; 02185 struct sockaddr_in dest = { 0, }; 02186 struct ast_sockaddr dest_tmp; 02187 struct mgcp_endpoint *p = sub->parent; 02188 /* XXX We break with the "recommendation" and send our IP, in order that our 02189 peer doesn't have to ast_gethostbyname() us XXX */ 02190 len = 0; 02191 if (!sub->rtp) { 02192 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02193 return -1; 02194 } 02195 ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp); 02196 ast_sockaddr_to_sin(&sin_tmp, &sin); 02197 if (rtp) { 02198 ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp); 02199 ast_sockaddr_to_sin(&dest_tmp, &dest); 02200 } else { 02201 if (sub->tmpdest.sin_addr.s_addr) { 02202 dest.sin_addr = sub->tmpdest.sin_addr; 02203 dest.sin_port = sub->tmpdest.sin_port; 02204 /* Reset temporary destination */ 02205 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02206 } else { 02207 dest.sin_addr = p->parent->ourip; 02208 dest.sin_port = sin.sin_port; 02209 } 02210 } 02211 ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02212 ast_copy_string(v, "v=0\r\n", sizeof(v)); 02213 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); 02214 ast_copy_string(s, "s=session\r\n", sizeof(s)); 02215 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02216 ast_copy_string(t, "t=0 0\r\n", sizeof(t)); 02217 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02218 for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02219 if (!(x & AST_FORMAT_AUDIO_MASK)) { 02220 /* Audio is now discontiguous */ 02221 continue; 02222 } 02223 if (p->capability & x) { 02224 ast_debug(1, "Answering with capability %s\n", ast_getformatname(x)); 02225 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x); 02226 if (codec > -1) { 02227 snprintf(costr, sizeof(costr), " %d", codec); 02228 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02229 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0)); 02230 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02231 } 02232 } 02233 } 02234 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { 02235 if (p->nonCodecCapability & x) { 02236 ast_debug(1, "Answering with non-codec capability %d\n", (int) x); 02237 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x); 02238 if (codec > -1) { 02239 snprintf(costr, sizeof(costr), " %d", codec); 02240 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02241 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0)); 02242 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02243 if (x == AST_RTP_DTMF) { 02244 /* Indicate we support DTMF... Not sure about 16, 02245 but MSN supports it so dang it, we will too... */ 02246 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02247 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02248 } 02249 } 02250 } 02251 } 02252 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02253 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02254 snprintf(costr, sizeof(costr), "%d", len); 02255 add_line(resp, v); 02256 add_line(resp, o); 02257 add_line(resp, s); 02258 add_line(resp, c); 02259 add_line(resp, t); 02260 add_line(resp, m); 02261 add_line(resp, a); 02262 return 0; 02263 }
static struct ast_variable * add_var | ( | const char * | buf, | |
struct ast_variable * | list | |||
) | [static] |
Definition at line 4570 of file chan_mgcp.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
Referenced by build_peer(), and config_parse_variables().
04571 { 04572 struct ast_variable *tmpvar = NULL; 04573 char *varname = ast_strdupa(buf), *varval = NULL; 04574 04575 if ((varval = strchr(varname, '='))) { 04576 *varval++ = '\0'; 04577 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 04578 tmpvar->next = list; 04579 list = tmpvar; 04580 } 04581 } 04582 return list; 04583 }
static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 3193 of file chan_mgcp.c.
References ast_channel::_softhangup, ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verb, mgcp_subchannel::id, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().
03194 { 03195 /* ************************* 03196 * I hope this works. 03197 * Copied out of chan_zap 03198 * Cross your fingers 03199 * *************************/ 03200 03201 /* In order to transfer, we need at least one of the channels to 03202 actually be in a call bridge. We can't conference two applications 03203 together (but then, why would we want to?) */ 03204 if (ast_bridged_channel(p->sub->owner)) { 03205 /* The three-way person we're about to transfer to could still be in MOH, so 03206 stop if now if appropriate */ 03207 if (ast_bridged_channel(p->sub->next->owner)) 03208 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03209 if (p->sub->owner->_state == AST_STATE_RINGING) { 03210 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03211 } 03212 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 03213 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03214 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); 03215 return -1; 03216 } 03217 /* Orphan the channel */ 03218 unalloc_sub(p->sub->next); 03219 } else if (ast_bridged_channel(p->sub->next->owner)) { 03220 if (p->sub->owner->_state == AST_STATE_RINGING) { 03221 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03222 } 03223 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03224 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 03225 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03226 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); 03227 return -1; 03228 } 03229 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 03230 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03231 p->sub = p->sub->next; 03232 unalloc_sub(p->sub->next); 03233 /* Tell the caller not to hangup */ 03234 return 1; 03235 } else { 03236 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03237 p->sub->owner->name, p->sub->next->owner->name); 03238 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03239 if (p->sub->next->owner) { 03240 p->sub->next->alreadygone = 1; 03241 mgcp_queue_hangup(p->sub->next); 03242 } 03243 } 03244 return 0; 03245 }
static struct mgcp_gateway * build_gateway | ( | char * | cat, | |
struct ast_variable * | v | |||
) | [static] |
build_gateway: parse mgcp.conf and create gateway/endpoint structures
Definition at line 3955 of file chan_mgcp.c.
References mgcp_gateway::delme, DIRECTMEDIA, directmedia, gateways, mgcp_gateway::name, and mgcp_gateway::next.
03956 { 03957 struct mgcp_gateway *gw; 03958 struct mgcp_endpoint *e; 03959 struct mgcp_subchannel *sub; 03960 struct ast_variable *chanvars = NULL; 03961 03962 /*char txident[80];*/ 03963 int i=0, y=0; 03964 int gw_reload = 0; 03965 int ep_reload = 0; 03966 directmedia = DIRECTMEDIA; 03967 03968 /* locate existing gateway */ 03969 for (gw = gateways; gw; gw = gw->next) { 03970 if (!strcasecmp(cat, gw->name)) { 03971 /* gateway already exists */ 03972 gw->delme = 0; 03973 gw_reload = 1; 03974 break; 03975 } 03976 } 03977 03978 if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) { 03979 return NULL; 03980 } 03981 03982 if (!gw_reload) { 03983 gw->expire = -1; 03984 gw->realtime = 0; 03985 gw->retransid = -1; 03986 ast_mutex_init(&gw->msgs_lock); 03987 ast_copy_string(gw->name, cat, sizeof(gw->name)); 03988 /* check if the name is numeric ip */ 03989 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 03990 gw->isnamedottedip = 1; 03991 } 03992 for (; v; v = v->next) { 03993 if (!strcasecmp(v->name, "host")) { 03994 if (!strcasecmp(v->value, "dynamic")) { 03995 /* They'll register with us */ 03996 gw->dynamic = 1; 03997 memset(&gw->addr.sin_addr, 0, 4); 03998 if (gw->addr.sin_port) { 03999 /* If we've already got a port, make it the default rather than absolute */ 04000 gw->defaddr.sin_port = gw->addr.sin_port; 04001 gw->addr.sin_port = 0; 04002 } 04003 } else { 04004 /* Non-dynamic. Make sure we become that way if we're not */ 04005 AST_SCHED_DEL(sched, gw->expire); 04006 gw->dynamic = 0; 04007 { 04008 struct ast_sockaddr tmp; 04009 04010 ast_sockaddr_from_sin(&tmp, &gw->addr); 04011 if (ast_get_ip(&tmp, v->value)) { 04012 if (!gw_reload) { 04013 ast_mutex_destroy(&gw->msgs_lock); 04014 ast_free(gw); 04015 } 04016 return NULL; 04017 } 04018 ast_sockaddr_to_sin(&tmp, &gw->addr); 04019 } 04020 } 04021 } else if (!strcasecmp(v->name, "defaultip")) { 04022 struct ast_sockaddr tmp; 04023 04024 ast_sockaddr_from_sin(&tmp, &gw->defaddr); 04025 if (ast_get_ip(&tmp, v->value)) { 04026 if (!gw_reload) { 04027 ast_mutex_destroy(&gw->msgs_lock); 04028 ast_free(gw); 04029 } 04030 return NULL; 04031 } 04032 ast_sockaddr_to_sin(&tmp, &gw->defaddr); 04033 } else if (!strcasecmp(v->name, "permit") || 04034 !strcasecmp(v->name, "deny")) { 04035 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 04036 } else if (!strcasecmp(v->name, "port")) { 04037 gw->addr.sin_port = htons(atoi(v->value)); 04038 } else if (!strcasecmp(v->name, "context")) { 04039 ast_copy_string(context, v->value, sizeof(context)); 04040 } else if (!strcasecmp(v->name, "dtmfmode")) { 04041 if (!strcasecmp(v->value, "inband")) 04042 dtmfmode = MGCP_DTMF_INBAND; 04043 else if (!strcasecmp(v->value, "rfc2833")) 04044 dtmfmode = MGCP_DTMF_RFC2833; 04045 else if (!strcasecmp(v->value, "hybrid")) 04046 dtmfmode = MGCP_DTMF_HYBRID; 04047 else if (!strcasecmp(v->value, "none")) 04048 dtmfmode = 0; 04049 else 04050 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 04051 } else if (!strcasecmp(v->name, "nat")) { 04052 nat = ast_true(v->value); 04053 } else if (!strcasecmp(v->name, "ncs")) { 04054 ncs = ast_true(v->value); 04055 } else if (!strcasecmp(v->name, "hangupongateremove")) { 04056 hangupongateremove = ast_true(v->value); 04057 } else if (!strcasecmp(v->name, "pktcgatealloc")) { 04058 pktcgatealloc = ast_true(v->value); 04059 } else if (!strcasecmp(v->name, "callerid")) { 04060 if (!strcasecmp(v->value, "asreceived")) { 04061 cid_num[0] = '\0'; 04062 cid_name[0] = '\0'; 04063 } else { 04064 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 04065 } 04066 } else if (!strcasecmp(v->name, "language")) { 04067 ast_copy_string(language, v->value, sizeof(language)); 04068 } else if (!strcasecmp(v->name, "accountcode")) { 04069 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 04070 } else if (!strcasecmp(v->name, "amaflags")) { 04071 y = ast_cdr_amaflags2int(v->value); 04072 if (y < 0) { 04073 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 04074 } else { 04075 amaflags = y; 04076 } 04077 } else if (!strcasecmp(v->name, "setvar")) { 04078 chanvars = add_var(v->value, chanvars); 04079 } else if (!strcasecmp(v->name, "clearvars")) { 04080 if (chanvars) { 04081 ast_variables_destroy(chanvars); 04082 chanvars = NULL; 04083 } 04084 } else if (!strcasecmp(v->name, "musiconhold")) { 04085 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 04086 } else if (!strcasecmp(v->name, "parkinglot")) { 04087 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 04088 } else if (!strcasecmp(v->name, "callgroup")) { 04089 cur_callergroup = ast_get_group(v->value); 04090 } else if (!strcasecmp(v->name, "pickupgroup")) { 04091 cur_pickupgroup = ast_get_group(v->value); 04092 } else if (!strcasecmp(v->name, "immediate")) { 04093 immediate = ast_true(v->value); 04094 } else if (!strcasecmp(v->name, "cancallforward")) { 04095 cancallforward = ast_true(v->value); 04096 } else if (!strcasecmp(v->name, "singlepath")) { 04097 singlepath = ast_true(v->value); 04098 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 04099 directmedia = ast_true(v->value); 04100 } else if (!strcasecmp(v->name, "mailbox")) { 04101 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 04102 } else if (!strcasecmp(v->name, "hasvoicemail")) { 04103 if (ast_true(v->value) && ast_strlen_zero(mailbox)) { 04104 ast_copy_string(mailbox, gw->name, sizeof(mailbox)); 04105 } 04106 } else if (!strcasecmp(v->name, "adsi")) { 04107 adsi = ast_true(v->value); 04108 } else if (!strcasecmp(v->name, "callreturn")) { 04109 callreturn = ast_true(v->value); 04110 } else if (!strcasecmp(v->name, "callwaiting")) { 04111 callwaiting = ast_true(v->value); 04112 } else if (!strcasecmp(v->name, "slowsequence")) { 04113 slowsequence = ast_true(v->value); 04114 } else if (!strcasecmp(v->name, "transfer")) { 04115 transfer = ast_true(v->value); 04116 } else if (!strcasecmp(v->name, "threewaycalling")) { 04117 threewaycalling = ast_true(v->value); 04118 } else if (!strcasecmp(v->name, "wcardep")) { 04119 /* locate existing endpoint */ 04120 for (e = gw->endpoints; e; e = e->next) { 04121 if (!strcasecmp(v->value, e->name)) { 04122 /* endpoint already exists */ 04123 e->delme = 0; 04124 ep_reload = 1; 04125 break; 04126 } 04127 } 04128 04129 if (!e) { 04130 /* Allocate wildcard endpoint */ 04131 e = ast_calloc(1, sizeof(*e)); 04132 ep_reload = 0; 04133 } 04134 04135 if (e) { 04136 if (!ep_reload) { 04137 memset(e, 0, sizeof(struct mgcp_endpoint)); 04138 ast_mutex_init(&e->lock); 04139 ast_mutex_init(&e->rqnt_queue_lock); 04140 ast_mutex_init(&e->cmd_queue_lock); 04141 ast_copy_string(e->name, v->value, sizeof(e->name)); 04142 e->needaudit = 1; 04143 } 04144 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 04145 /* XXX Should we really check for uniqueness?? XXX */ 04146 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04147 ast_copy_string(e->context, context, sizeof(e->context)); 04148 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04149 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04150 ast_copy_string(e->language, language, sizeof(e->language)); 04151 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04152 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04153 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04154 if (!ast_strlen_zero(e->mailbox)) { 04155 char *mbox, *cntx; 04156 cntx = mbox = ast_strdupa(e->mailbox); 04157 strsep(&cntx, "@"); 04158 if (ast_strlen_zero(cntx)) { 04159 cntx = "default"; 04160 } 04161 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL, 04162 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 04163 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 04164 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 04165 AST_EVENT_IE_END); 04166 } 04167 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04168 e->msgstate = -1; 04169 e->amaflags = amaflags; 04170 e->capability = capability; 04171 e->parent = gw; 04172 e->ncs = ncs; 04173 e->dtmfmode = dtmfmode; 04174 if (!ep_reload && e->sub && e->sub->rtp) { 04175 e->dtmfmode |= MGCP_DTMF_INBAND; 04176 } 04177 e->adsi = adsi; 04178 e->type = TYPE_LINE; 04179 e->immediate = immediate; 04180 e->callgroup=cur_callergroup; 04181 e->pickupgroup=cur_pickupgroup; 04182 e->callreturn = callreturn; 04183 e->cancallforward = cancallforward; 04184 e->singlepath = singlepath; 04185 e->directmedia = directmedia; 04186 e->callwaiting = callwaiting; 04187 e->hascallwaiting = callwaiting; 04188 e->slowsequence = slowsequence; 04189 e->transfer = transfer; 04190 e->threewaycalling = threewaycalling; 04191 e->onhooktime = time(NULL); 04192 /* ASSUME we're onhook */ 04193 e->hookstate = MGCP_ONHOOK; 04194 e->chanvars = copy_vars(chanvars); 04195 if (!ep_reload) { 04196 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 04197 for (i = 0; i < MAX_SUBS; i++) { 04198 sub = ast_calloc(1, sizeof(*sub)); 04199 if (sub) { 04200 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04201 ast_mutex_init(&sub->lock); 04202 ast_mutex_init(&sub->cx_queue_lock); 04203 sub->parent = e; 04204 sub->id = i; 04205 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04206 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 04207 sub->cxmode = MGCP_CX_INACTIVE; 04208 sub->nat = nat; 04209 sub->gate = NULL; 04210 sub->sdpsent = 0; 04211 sub->next = e->sub; 04212 e->sub = sub; 04213 } else { 04214 /* XXX Should find a way to clean up our memory */ 04215 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04216 return NULL; 04217 } 04218 } 04219 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04220 /* find the end of the list */ 04221 for (sub = e->sub; sub && sub->next; sub = sub->next); 04222 /* set the last sub->next to the first sub */ 04223 sub->next = e->sub; 04224 04225 e->next = gw->endpoints; 04226 gw->endpoints = e; 04227 } 04228 } 04229 } else if (!strcasecmp(v->name, "trunk") || 04230 !strcasecmp(v->name, "line")) { 04231 04232 /* locate existing endpoint */ 04233 for (e = gw->endpoints; e; e = e->next) { 04234 if (!strcasecmp(v->value, e->name)) { 04235 /* endpoint already exists */ 04236 e->delme = 0; 04237 ep_reload = 1; 04238 break; 04239 } 04240 } 04241 04242 if (!e) { 04243 e = ast_calloc(1, sizeof(*e)); 04244 ep_reload = 0; 04245 } 04246 04247 if (e) { 04248 if (!ep_reload) { 04249 ast_mutex_init(&e->lock); 04250 ast_mutex_init(&e->rqnt_queue_lock); 04251 ast_mutex_init(&e->cmd_queue_lock); 04252 ast_copy_string(e->name, v->value, sizeof(e->name)); 04253 e->needaudit = 1; 04254 } 04255 /* XXX Should we really check for uniqueness?? XXX */ 04256 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04257 ast_copy_string(e->context, context, sizeof(e->context)); 04258 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04259 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04260 ast_copy_string(e->language, language, sizeof(e->language)); 04261 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04262 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04263 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04264 if (!ast_strlen_zero(mailbox)) { 04265 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 04266 } 04267 if (!ep_reload) { 04268 /* XXX potential issue due to reload */ 04269 e->msgstate = -1; 04270 e->parent = gw; 04271 } 04272 e->amaflags = amaflags; 04273 e->capability = capability; 04274 e->dtmfmode = dtmfmode; 04275 e->ncs = ncs; 04276 e->pktcgatealloc = pktcgatealloc; 04277 e->hangupongateremove = hangupongateremove; 04278 e->adsi = adsi; 04279 e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE; 04280 e->immediate = immediate; 04281 e->callgroup=cur_callergroup; 04282 e->pickupgroup=cur_pickupgroup; 04283 e->callreturn = callreturn; 04284 e->cancallforward = cancallforward; 04285 e->directmedia = directmedia; 04286 e->singlepath = singlepath; 04287 e->callwaiting = callwaiting; 04288 e->hascallwaiting = callwaiting; 04289 e->slowsequence = slowsequence; 04290 e->transfer = transfer; 04291 e->threewaycalling = threewaycalling; 04292 04293 /* If we already have a valid chanvars, it's not a new endpoint (it's a reload), 04294 so first, free previous mem 04295 */ 04296 if (e->chanvars) { 04297 ast_variables_destroy(e->chanvars); 04298 e->chanvars = NULL; 04299 } 04300 e->chanvars = copy_vars(chanvars); 04301 04302 if (!ep_reload) { 04303 e->onhooktime = time(NULL); 04304 /* ASSUME we're onhook */ 04305 e->hookstate = MGCP_ONHOOK; 04306 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04307 } 04308 04309 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 04310 if (!ep_reload) { 04311 sub = ast_calloc(1, sizeof(*sub)); 04312 } else { 04313 if (!sub) { 04314 sub = e->sub; 04315 } else { 04316 sub = sub->next; 04317 } 04318 } 04319 04320 if (sub) { 04321 if (!ep_reload) { 04322 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04323 ast_mutex_init(&sub->lock); 04324 ast_mutex_init(&sub->cx_queue_lock); 04325 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 04326 sub->parent = e; 04327 sub->id = i; 04328 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04329 sub->cxmode = MGCP_CX_INACTIVE; 04330 sub->next = e->sub; 04331 e->sub = sub; 04332 } 04333 sub->nat = nat; 04334 } else { 04335 /* XXX Should find a way to clean up our memory */ 04336 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04337 return NULL; 04338 } 04339 } 04340 if (!ep_reload) { 04341 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04342 /* find the end of the list */ 04343 for (sub = e->sub; sub && sub->next; sub = sub->next); 04344 /* set the last sub->next to the first sub */ 04345 sub->next = e->sub; 04346 04347 e->next = gw->endpoints; 04348 gw->endpoints = e; 04349 } 04350 } 04351 } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) { 04352 /* just eliminate realtime warnings */ 04353 } else { 04354 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 04355 } 04356 } 04357 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 04358 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 04359 if (!gw_reload) { 04360 ast_mutex_destroy(&gw->msgs_lock); 04361 ast_free(gw); 04362 } 04363 04364 /* Return NULL */ 04365 gw_reload = 1; 04366 } else { 04367 gw->defaddr.sin_family = AF_INET; 04368 gw->addr.sin_family = AF_INET; 04369 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) { 04370 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04371 } 04372 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) { 04373 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04374 } 04375 { 04376 struct ast_sockaddr tmp1, tmp2; 04377 struct sockaddr_in tmp3 = {0,}; 04378 04379 tmp3.sin_addr = gw->ourip; 04380 ast_sockaddr_from_sin(&tmp1, &gw->addr); 04381 ast_sockaddr_from_sin(&tmp2, &tmp3); 04382 if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) { 04383 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 04384 } else { 04385 ast_sockaddr_to_sin(&tmp2, &tmp3); 04386 gw->ourip = tmp3.sin_addr; 04387 } 04388 } 04389 } 04390 04391 if (chanvars) { 04392 ast_variables_destroy(chanvars); 04393 chanvars = NULL; 04394 } 04395 return (gw_reload ? NULL : gw); 04396 }
static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1405 of file chan_mgcp.c.
References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, and AST_CONTROL_WINK.
Referenced by mgcp_indicate(), skinny_indicate(), and unistim_indicate().
01405 { 01406 switch (ind) { 01407 case AST_CONTROL_HANGUP: 01408 return "Other end has hungup"; 01409 case AST_CONTROL_RING: 01410 return "Local ring"; 01411 case AST_CONTROL_RINGING: 01412 return "Remote end is ringing"; 01413 case AST_CONTROL_ANSWER: 01414 return "Remote end has answered"; 01415 case AST_CONTROL_BUSY: 01416 return "Remote end is busy"; 01417 case AST_CONTROL_TAKEOFFHOOK: 01418 return "Make it go off hook"; 01419 case AST_CONTROL_OFFHOOK: 01420 return "Line is off hook"; 01421 case AST_CONTROL_CONGESTION: 01422 return "Congestion (circuits busy)"; 01423 case AST_CONTROL_FLASH: 01424 return "Flash hook"; 01425 case AST_CONTROL_WINK: 01426 return "Wink"; 01427 case AST_CONTROL_OPTION: 01428 return "Set a low-level option"; 01429 case AST_CONTROL_RADIO_KEY: 01430 return "Key Radio"; 01431 case AST_CONTROL_RADIO_UNKEY: 01432 return "Un-Key Radio"; 01433 } 01434 return "UNKNOWN"; 01435 }
static struct ast_variable * copy_vars | ( | struct ast_variable * | src | ) | [static] |
duplicate a list of channel variables,
Definition at line 4588 of file chan_mgcp.c.
References ast_variable_new(), and ast_variable::next.
Referenced by check_peer_ok(), and create_addr_from_peer().
04589 { 04590 struct ast_variable *res = NULL, *tmp, *v = NULL; 04591 04592 for (v = src ; v ; v = v->next) { 04593 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 04594 tmp->next = res; 04595 res = tmp; 04596 } 04597 } 04598 return res; 04599 }
static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 4460 of file chan_mgcp.c.
References ast_mutex_lock, ast_rtp_instance_destroy(), ast_strlen_zero(), mgcp_subchannel::cxident, mgcp_subchannel::lock, mgcp_subchannel::next, mgcp_subchannel::rtp, mgcp_endpoint::sub, and transmit_connection_del().
Referenced by prune_gateways().
04461 { 04462 struct mgcp_subchannel *sub = e->sub->next, *s; 04463 int i; 04464 04465 for (i = 0; i < MAX_SUBS; i++) { 04466 ast_mutex_lock(&sub->lock); 04467 if (!ast_strlen_zero(sub->cxident)) { 04468 transmit_connection_del(sub); 04469 } 04470 if (sub->rtp) { 04471 ast_rtp_instance_destroy(sub->rtp); 04472 sub->rtp = NULL; 04473 } 04474 memset(sub->magic, 0, sizeof(sub->magic)); 04475 mgcp_queue_hangup(sub); 04476 dump_cmd_queues(NULL, sub); 04477 if(sub->gate) { 04478 sub->gate->tech_pvt = NULL; 04479 sub->gate->got_dq_gi = NULL; 04480 sub->gate->gate_remove = NULL; 04481 sub->gate->gate_open = NULL; 04482 } 04483 ast_mutex_unlock(&sub->lock); 04484 sub = sub->next; 04485 } 04486 04487 if (e->dsp) { 04488 ast_dsp_free(e->dsp); 04489 } 04490 04491 dump_queue(e->parent, e); 04492 dump_cmd_queues(e, NULL); 04493 04494 sub = e->sub; 04495 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04496 s = sub; 04497 sub = sub->next; 04498 ast_mutex_destroy(&s->lock); 04499 ast_mutex_destroy(&s->cx_queue_lock); 04500 ast_free(s); 04501 } 04502 04503 if (e->mwi_event_sub) 04504 ast_event_unsubscribe(e->mwi_event_sub); 04505 04506 if (e->chanvars) { 04507 ast_variables_destroy(e->chanvars); 04508 e->chanvars = NULL; 04509 } 04510 04511 ast_mutex_destroy(&e->lock); 04512 ast_mutex_destroy(&e->rqnt_queue_lock); 04513 ast_mutex_destroy(&e->cmd_queue_lock); 04514 ast_free(e); 04515 }
static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4517 of file chan_mgcp.c.
References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.
04518 { 04519 if (g->ha) 04520 ast_free_ha(g->ha); 04521 04522 dump_queue(g, NULL); 04523 04524 ast_free(g); 04525 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3753 of file chan_mgcp.c.
References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, free, gatelock, gateways, has_voicemail(), io, MGCP_ONHOOK, mgcp_prune_realtime_gateway(), mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), mgcpsock_read_id, monlock, mgcp_gateway::msgs_lock, netlock, mgcp_gateway::next, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.
03754 { 03755 int res; 03756 int reloading; 03757 struct mgcp_gateway *g, *gprev, *gnext; 03758 /*struct mgcp_gateway *g;*/ 03759 /*struct mgcp_endpoint *e;*/ 03760 /*time_t thispass = 0, lastpass = 0;*/ 03761 time_t lastrun = 0; 03762 03763 /* Add an I/O event to our UDP socket */ 03764 if (mgcpsock > -1) { 03765 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03766 } 03767 /* This thread monitors all the frame relay interfaces which are not yet in use 03768 (and thus do not have a separate thread) indefinitely */ 03769 /* From here on out, we die whenever asked */ 03770 for (;;) { 03771 /* Check for a reload request */ 03772 ast_mutex_lock(&mgcp_reload_lock); 03773 reloading = mgcp_reloading; 03774 mgcp_reloading = 0; 03775 ast_mutex_unlock(&mgcp_reload_lock); 03776 if (reloading) { 03777 ast_verb(1, "Reloading MGCP\n"); 03778 reload_config(1); 03779 /* Add an I/O event to our UDP socket */ 03780 if (mgcpsock > -1 && !mgcpsock_read_id) { 03781 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03782 } 03783 } 03784 03785 /* Check for interfaces needing to be killed */ 03786 /* Don't let anybody kill us right away. Nobody should lock the interface list 03787 and wait for the monitor list, but the other way around is okay. */ 03788 ast_mutex_lock(&monlock); 03789 /* Lock the network interface */ 03790 ast_mutex_lock(&netlock); 03791 03792 #if 0 03793 /* XXX THIS IS COMPLETELY HOSED */ 03794 /* The gateway goes into a state of panic */ 03795 /* If the vmwi indicator is sent while it is reseting interfaces */ 03796 lastpass = thispass; 03797 thispass = time(NULL); 03798 g = gateways; 03799 while(g) { 03800 if (thispass != lastpass) { 03801 e = g->endpoints; 03802 while(e) { 03803 if (e->type == TYPE_LINE) { 03804 res = has_voicemail(e); 03805 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03806 if (res) { 03807 transmit_notify_request(e, "L/vmwi(+)"); 03808 } else { 03809 transmit_notify_request(e, "L/vmwi(-)"); 03810 } 03811 e->msgstate = res; 03812 e->onhooktime = thispass; 03813 } 03814 } 03815 e = e->next; 03816 } 03817 } 03818 g = g->next; 03819 } 03820 #endif 03821 /* pruning unused realtime gateways, running in every 60 seconds*/ 03822 if(time(NULL) > (lastrun + 60)) { 03823 ast_mutex_lock(&gatelock); 03824 g = gateways; 03825 gprev = NULL; 03826 while(g) { 03827 gnext = g->next; 03828 if(g->realtime) { 03829 if(mgcp_prune_realtime_gateway(g)) { 03830 if(gprev) { 03831 gprev->next = gnext; 03832 gprev = g; 03833 } else { 03834 gateways = g->next; 03835 } 03836 ast_mutex_unlock(&g->msgs_lock); 03837 ast_mutex_destroy(&g->msgs_lock); 03838 free(g); 03839 } else { 03840 ast_mutex_unlock(&g->msgs_lock); 03841 gprev = g; 03842 } 03843 } else { 03844 gprev = g; 03845 } 03846 g = gnext; 03847 } 03848 ast_mutex_unlock(&gatelock); 03849 lastrun = time(NULL); 03850 } 03851 /* Okay, now that we know what to do, release the network lock */ 03852 ast_mutex_unlock(&netlock); 03853 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03854 ast_mutex_unlock(&monlock); 03855 pthread_testcancel(); 03856 /* Wait for sched or io */ 03857 res = ast_sched_wait(sched); 03858 /* copied from chan_sip.c */ 03859 if ((res < 0) || (res > 1000)) { 03860 res = 1000; 03861 } 03862 res = ast_io_wait(io, res); 03863 ast_mutex_lock(&monlock); 03864 if (res >= 0) { 03865 ast_sched_runq(sched); 03866 } 03867 ast_mutex_unlock(&monlock); 03868 } 03869 /* Never reached */ 03870 return NULL; 03871 }
static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub | |||
) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2675 of file chan_mgcp.c.
References ast_free, ast_mutex_lock, ast_mutex_unlock, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::next, mgcp_request::next, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::sub.
Referenced by handle_request(), handle_response(), and unalloc_sub().
02676 { 02677 struct mgcp_request *t, *q; 02678 02679 if (p) { 02680 ast_mutex_lock(&p->rqnt_queue_lock); 02681 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); 02682 p->rqnt_queue = NULL; 02683 ast_mutex_unlock(&p->rqnt_queue_lock); 02684 02685 ast_mutex_lock(&p->cmd_queue_lock); 02686 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); 02687 p->cmd_queue = NULL; 02688 ast_mutex_unlock(&p->cmd_queue_lock); 02689 02690 ast_mutex_lock(&p->sub->cx_queue_lock); 02691 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02692 p->sub->cx_queue = NULL; 02693 ast_mutex_unlock(&p->sub->cx_queue_lock); 02694 02695 ast_mutex_lock(&p->sub->next->cx_queue_lock); 02696 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); 02697 p->sub->next->cx_queue = NULL; 02698 ast_mutex_unlock(&p->sub->next->cx_queue_lock); 02699 } else if (sub) { 02700 ast_mutex_lock(&sub->cx_queue_lock); 02701 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02702 sub->cx_queue = NULL; 02703 ast_mutex_unlock(&sub->cx_queue_lock); 02704 } 02705 }
static void dump_queue | ( | struct mgcp_gateway * | gw, | |
struct mgcp_endpoint * | p | |||
) | [static] |
Definition at line 578 of file chan_mgcp.c.
References ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_NOTICE, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, and mgcp_message::seqno.
Referenced by destroy_gateway(), and handle_request().
00579 { 00580 struct mgcp_message *cur, *q = NULL, *w, *prev; 00581 00582 ast_mutex_lock(&gw->msgs_lock); 00583 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00584 if (!p || cur->owner_ep == p) { 00585 if (prev) { 00586 prev->next = cur->next; 00587 } else { 00588 gw->msgs = cur->next; 00589 } 00590 00591 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 00592 gw->name, cur->seqno); 00593 00594 w = cur; 00595 if (q) { 00596 w->next = q; 00597 } else { 00598 w->next = NULL; 00599 } 00600 q = w; 00601 } 00602 } 00603 ast_mutex_unlock(&gw->msgs_lock); 00604 00605 while (q) { 00606 cur = q; 00607 q = q->next; 00608 ast_free(cur); 00609 } 00610 }
static int find_and_retrans | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req | |||
) | [static] |
Definition at line 3574 of file chan_mgcp.c.
References ast_free, mgcp_request::identifier, mgcp_response::next, mgcp_endpoint::parent, mgcp_subchannel::parent, resend_response(), RESPONSE_TIMEOUT, and mgcp_gateway::responses.
Referenced by mgcpsock_read().
03575 { 03576 int seqno=0; 03577 time_t now; 03578 struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL; 03579 time(&now); 03580 if (sscanf(req->identifier, "%30d", &seqno) != 1) { 03581 seqno = 0; 03582 } 03583 for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) { 03584 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03585 /* Delete this entry */ 03586 if (prev) 03587 prev->next = next; 03588 else 03589 sub->parent->parent->responses = next; 03590 ast_free(cur); 03591 } else { 03592 if (seqno == cur->seqno) 03593 answer = cur; 03594 prev = cur; 03595 } 03596 } 03597 if (answer) { 03598 resend_response(sub, answer); 03599 return 1; 03600 } 03601 return 0; 03602 }
static struct mgcp_request* find_command | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub, | |||
struct mgcp_request ** | queue, | |||
ast_mutex_t * | l, | |||
int | ident | |||
) | [static] |
find_command: (SC:) remove command transaction from queue
Definition at line 2709 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), ast_mutex_lock, mgcp_postrequest(), mgcp_request::next, and mgcp_endpoint::parent.
Referenced by agi_handle_command(), ast_agi_register(), handle_cli_agi_show(), and handle_response().
02711 { 02712 struct mgcp_request *prev, *req; 02713 02714 ast_mutex_lock(l); 02715 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02716 if (req->trid == ident) { 02717 /* remove from queue */ 02718 if (!prev) 02719 *queue = req->next; 02720 else 02721 prev->next = req->next; 02722 02723 /* send next pending command */ 02724 if (*queue) { 02725 ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02726 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02727 02728 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02729 } 02730 break; 02731 } 02732 } 02733 ast_mutex_unlock(l); 02734 return req; 02735 }
static struct mgcp_gateway* find_realtime_gw | ( | char * | name, | |
char * | at, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 1660 of file chan_mgcp.c.
References ast_check_realtime(), ast_copy_string(), ast_debug, ast_load_realtime(), ast_strlen_zero(), ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by find_subchannel_and_lock().
01661 { 01662 struct mgcp_gateway *g = NULL; 01663 struct ast_variable *mgcpgwconfig = NULL; 01664 struct ast_variable *gwv, *epname = NULL; 01665 struct mgcp_endpoint *e; 01666 char lines[256]; 01667 int i, j; 01668 01669 ast_debug(1, "*** find Realtime MGCPGW\n"); 01670 01671 if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) { 01672 return NULL; 01673 } 01674 01675 if (ast_strlen_zero(at)) { 01676 ast_debug(1, "null gw name\n"); 01677 return NULL; 01678 } 01679 01680 if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) { 01681 return NULL; 01682 } 01683 01684 /*! 01685 * \note This is a fairly odd way of instantiating lines. Instead of each 01686 * line created by virtue of being in the database (and loaded via 01687 * ast_load_realtime_multientry), this code forces a specific order with a 01688 * "lines" entry in the "mgcpgw" record. This has benefits, because as with 01689 * chan_dahdi, values are inherited across definitions. The downside is 01690 * that it's not as clear what the values will be simply by looking at a 01691 * single row in the database, and it's probable that the sanest configuration 01692 * should have the first column in the "mgcpep" table be "clearvars", with a 01693 * static value of "all", if any variables are set at all. It may be worth 01694 * making this assumption explicit in the code in the future, and then just 01695 * using ast_load_realtime_multientry for the "mgcpep" records. 01696 */ 01697 lines[0] = '\0'; 01698 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) { 01699 if (!strcasecmp(gwv->name, "lines")) { 01700 ast_copy_string(lines, gwv->value, sizeof(lines)); 01701 break; 01702 } 01703 } 01704 /* Position gwv at the end of the list */ 01705 for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next); 01706 01707 if (!ast_strlen_zero(lines)) { 01708 AST_DECLARE_APP_ARGS(args, 01709 AST_APP_ARG(line)[100]; 01710 ); 01711 AST_STANDARD_APP_ARGS(args, lines); 01712 for (i = 0; i < args.argc; i++) { 01713 gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL); 01714 01715 /* Remove "line" AND position gwv at the end of the list. */ 01716 for (epname = NULL; gwv->next; gwv = gwv->next) { 01717 if (!strcasecmp(gwv->next->name, "line")) { 01718 /* Remove it from the list */ 01719 epname = gwv->next; 01720 gwv->next = gwv->next->next; 01721 } 01722 } 01723 /* Since "line" instantiates the configuration, we have to move it to the end. */ 01724 if (epname) { 01725 gwv->next = epname; 01726 epname->next = NULL; 01727 gwv = gwv->next; 01728 } 01729 } 01730 } 01731 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) { 01732 ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value); 01733 } 01734 01735 if (mgcpgwconfig) { 01736 g = build_gateway(at, mgcpgwconfig); 01737 ast_variables_destroy(mgcpgwconfig); 01738 } 01739 if (g) { 01740 g->next = gateways; 01741 g->realtime = 1; 01742 gateways = g; 01743 for (e = g->endpoints; e; e = e->next) { 01744 transmit_audit_endpoint(e); 01745 e->needaudit = 0; 01746 } 01747 } 01748 return g; 01749 }
static struct mgcp_subchannel* find_subchannel_and_lock | ( | char * | name, | |
int | msgid, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 1751 of file chan_mgcp.c.
References __ourip, mgcp_gateway::addr, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_ouraddrfor(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_verb, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, find_realtime_gw(), gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, mgcp_gateway::ourip, and mgcp_endpoint::sub.
Referenced by mgcp_request(), and mgcpsock_read().
01752 { 01753 struct mgcp_endpoint *p = NULL; 01754 struct mgcp_subchannel *sub = NULL; 01755 struct mgcp_gateway *g; 01756 char tmp[256] = ""; 01757 char *at = NULL, *c; 01758 int found = 0; 01759 if (name) { 01760 ast_copy_string(tmp, name, sizeof(tmp)); 01761 at = strchr(tmp, '@'); 01762 if (!at) { 01763 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); 01764 return NULL; 01765 } 01766 *at++ = '\0'; 01767 } 01768 ast_mutex_lock(&gatelock); 01769 if (at && (at[0] == '[')) { 01770 at++; 01771 c = strrchr(at, ']'); 01772 if (c) { 01773 *c = '\0'; 01774 } 01775 } 01776 for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) { 01777 if ((!name || !strcasecmp(g->name, at)) && 01778 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { 01779 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ 01780 if (sin && g->dynamic && name) { 01781 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01782 (g->addr.sin_port != sin->sin_port)) { 01783 memcpy(&g->addr, sin, sizeof(g->addr)); 01784 { 01785 struct ast_sockaddr tmp1, tmp2; 01786 struct sockaddr_in tmp3 = {0,}; 01787 01788 tmp3.sin_addr = g->ourip; 01789 ast_sockaddr_from_sin(&tmp1, &g->addr); 01790 ast_sockaddr_from_sin(&tmp2, &tmp3); 01791 if (ast_ouraddrfor(&tmp1, &tmp2)) { 01792 memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 01793 } 01794 ast_sockaddr_to_sin(&tmp2, &tmp3); 01795 g->ourip = tmp3.sin_addr; 01796 } 01797 ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port)); 01798 } 01799 /* not dynamic, check if the name matches */ 01800 } else if (name) { 01801 if (strcasecmp(g->name, at)) { 01802 g = g->next; 01803 continue; 01804 } 01805 /* not dynamic, no name, check if the addr matches */ 01806 } else if (!name && sin) { 01807 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01808 (g->addr.sin_port != sin->sin_port)) { 01809 if(!g->next) 01810 g = find_realtime_gw(name, at, sin); 01811 else 01812 g = g->next; 01813 continue; 01814 } 01815 } else { 01816 continue; 01817 } 01818 for (p = g->endpoints; p; p = p->next) { 01819 ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name); 01820 if (msgid) { 01821 sub = p->sub; 01822 found = 1; 01823 break; 01824 } else if (name && !strcasecmp(p->name, tmp)) { 01825 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 01826 p->name, g->name, p->sub->id); 01827 sub = p->sub; 01828 found = 1; 01829 break; 01830 } 01831 } 01832 if (sub && found) { 01833 ast_mutex_lock(&sub->lock); 01834 break; 01835 } 01836 } 01837 } 01838 ast_mutex_unlock(&gatelock); 01839 if (!sub) { 01840 if (name) { 01841 if (g) { 01842 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); 01843 } else { 01844 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); 01845 } 01846 } 01847 } 01848 return sub; 01849 }
static char* get_csv | ( | char * | c, | |
int * | len, | |||
char ** | next | |||
) | [static] |
get_csv: (SC:) get comma separated value
Definition at line 1636 of file chan_mgcp.c.
Referenced by handle_response().
01637 { 01638 char *s; 01639 01640 *next = NULL, *len = 0; 01641 if (!c) return NULL; 01642 01643 while (*c && (*c < 33 || *c == ',')) { 01644 c++; 01645 } 01646 01647 s = c; 01648 while (*c && (*c >= 33 && *c != ',')) { 01649 c++, (*len)++; 01650 } 01651 *next = c; 01652 01653 if (*len == 0) { 01654 s = NULL, *next = NULL; 01655 } 01656 01657 return s; 01658 }
static char* get_header | ( | struct mgcp_request * | req, | |
char * | name | |||
) | [static] |
Definition at line 1629 of file chan_mgcp.c.
References __get_header().
Referenced by __transmit_response(), _sip_tcp_helper_thread(), build_route(), cc_handle_publish_error(), change_redirecting_information(), check_auth(), check_user_full(), check_via(), check_via_response(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_pai(), get_rdnis(), get_realm(), get_refer_info(), get_rpid(), gettag(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_request(), handle_request_bye(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_register(), handle_request_subscribe(), handle_request_update(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_publish(), handle_response_refer(), handle_response_register(), handle_response_subscribe(), handle_response_update(), parse_allowed_methods(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), proc_422_rsp(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_alloc(), sip_get_cc_information(), sip_pidf_validate(), sip_sipredirect(), transmit_fake_auth_response(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_state_notify().
01630 { 01631 int start = 0; 01632 return __get_header(req, name, &start, ""); 01633 }
static char* get_sdp | ( | struct mgcp_request * | req, | |
char * | name | |||
) | [static] |
Definition at line 1580 of file chan_mgcp.c.
References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.
Referenced by process_sdp().
01581 { 01582 int x; 01583 int len = strlen(name); 01584 char *r; 01585 01586 for (x = 0; x < req->lines; x++) { 01587 r = get_sdp_by_line(req->line[x], name, len); 01588 if (r[0] != '\0') return r; 01589 } 01590 return ""; 01591 }
static char* get_sdp_by_line | ( | char * | line, | |
char * | name, | |||
int | nameLen | |||
) | [static] |
Definition at line 1570 of file chan_mgcp.c.
Referenced by get_sdp(), and get_sdp_iterate().
01571 { 01572 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { 01573 char *r = line + nameLen + 1; 01574 while (*r && (*r < 33)) ++r; 01575 return r; 01576 } 01577 return ""; 01578 }
static char* get_sdp_iterate | ( | int * | iterator, | |
struct mgcp_request * | req, | |||
char * | name | |||
) | [static] |
Definition at line 1598 of file chan_mgcp.c.
References get_sdp_by_line(), len(), and mgcp_request::line.
Referenced by get_ip_and_port_from_sdp(), and process_sdp().
01599 { 01600 int len = strlen(name); 01601 char *r; 01602 while (*iterator < req->lines) { 01603 r = get_sdp_by_line(req->line[(*iterator)++], name, len); 01604 if (r[0] != '\0') return r; 01605 } 01606 return ""; 01607 }
static void handle_hd_hf | ( | struct mgcp_subchannel * | sub, | |
char * | ev | |||
) | [static] |
Definition at line 3247 of file chan_mgcp.c.
References ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_UNHOLD, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), AST_STATE_DOWN, AST_STATE_RING, mgcp_subchannel::cxmode, errno, has_voicemail(), mgcp_endpoint::hookstate, mgcp_endpoint::immediate, LOG_WARNING, MGCP_CX_SENDRECV, mgcp_new(), MGCP_OFFHOOK, mgcp_queue_control(), mgcp_ss(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), mgcp_endpoint::sub, transmit_modify_request(), and transmit_notify_request().
Referenced by handle_request().
03248 { 03249 struct mgcp_endpoint *p = sub->parent; 03250 struct ast_channel *c; 03251 pthread_t t; 03252 03253 /* Off hook / answer */ 03254 if (sub->outgoing) { 03255 /* Answered */ 03256 if (sub->owner) { 03257 if (ast_bridged_channel(sub->owner)) 03258 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03259 sub->cxmode = MGCP_CX_SENDRECV; 03260 if (!sub->rtp) { 03261 start_rtp(sub); 03262 } else { 03263 transmit_modify_request(sub); 03264 } 03265 /*transmit_notify_request(sub, "aw");*/ 03266 transmit_notify_request(sub, ""); 03267 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 03268 } 03269 } else { 03270 /* Start switch */ 03271 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 03272 if (!sub->owner) { 03273 if (!sub->rtp) { 03274 start_rtp(sub); 03275 } else { 03276 transmit_modify_request(sub); 03277 } 03278 if (p->immediate) { 03279 /* The channel is immediately up. Start right away */ 03280 #ifdef DLINK_BUGGY_FIRMWARE 03281 transmit_notify_request(sub, "rt"); 03282 #else 03283 transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt"); 03284 #endif 03285 c = mgcp_new(sub, AST_STATE_RING, NULL); 03286 if (!c) { 03287 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 03288 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03289 ast_hangup(c); 03290 } 03291 } else { 03292 if (has_voicemail(p)) { 03293 transmit_notify_request(sub, "L/sl"); 03294 } else { 03295 transmit_notify_request(sub, "L/dl"); 03296 } 03297 c = mgcp_new(sub, AST_STATE_DOWN, NULL); 03298 if (c) { 03299 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { 03300 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 03301 ast_hangup(c); 03302 } 03303 } else { 03304 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 03305 } 03306 } 03307 } else { 03308 if (p->hookstate == MGCP_OFFHOOK) { 03309 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03310 } else { 03311 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03312 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 03313 } 03314 if (ast_bridged_channel(sub->owner)) 03315 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03316 sub->cxmode = MGCP_CX_SENDRECV; 03317 if (!sub->rtp) { 03318 start_rtp(sub); 03319 } else { 03320 transmit_modify_request(sub); 03321 } 03322 /*transmit_notify_request(sub, "aw");*/ 03323 transmit_notify_request(sub, ""); 03324 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03325 } 03326 } 03327 }
static char* handle_mgcp_audit_endpoint | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1078 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, ast_strdupa, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, mgcp_gateway::endpoints, gatelock, gateways, mgcpdebug, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, transmit_audit_endpoint(), and ast_cli_entry::usage.
01079 { 01080 struct mgcp_gateway *mg; 01081 struct mgcp_endpoint *me; 01082 int found = 0; 01083 char *ename,*gname, *c; 01084 01085 switch (cmd) { 01086 case CLI_INIT: 01087 e->command = "mgcp audit endpoint"; 01088 e->usage = 01089 "Usage: mgcp audit endpoint <endpointid>\n" 01090 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n" 01091 " mgcp debug MUST be on to see the results of this command.\n"; 01092 return NULL; 01093 case CLI_GENERATE: 01094 return NULL; 01095 } 01096 01097 if (!mgcpdebug) { 01098 return CLI_SHOWUSAGE; 01099 } 01100 if (a->argc != 4) 01101 return CLI_SHOWUSAGE; 01102 /* split the name into parts by null */ 01103 ename = ast_strdupa(a->argv[3]); 01104 for (gname = ename; *gname; gname++) { 01105 if (*gname == '@') { 01106 *gname = 0; 01107 gname++; 01108 break; 01109 } 01110 } 01111 if (gname[0] == '[') { 01112 gname++; 01113 } 01114 if ((c = strrchr(gname, ']'))) { 01115 *c = '\0'; 01116 } 01117 ast_mutex_lock(&gatelock); 01118 for (mg = gateways; mg; mg = mg->next) { 01119 if (!strcasecmp(mg->name, gname)) { 01120 for (me = mg->endpoints; me; me = me->next) { 01121 if (!strcasecmp(me->name, ename)) { 01122 found = 1; 01123 transmit_audit_endpoint(me); 01124 break; 01125 } 01126 } 01127 if (found) { 01128 break; 01129 } 01130 } 01131 } 01132 if (!found) { 01133 ast_cli(a->fd, " << Could not find endpoint >> "); 01134 } 01135 ast_mutex_unlock(&gatelock); 01136 return CLI_SUCCESS; 01137 }
static char* handle_mgcp_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1139 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mgcpdebug, and ast_cli_entry::usage.
01140 { 01141 switch (cmd) { 01142 case CLI_INIT: 01143 e->command = "mgcp set debug {on|off}"; 01144 e->usage = 01145 "Usage: mgcp set debug {on|off}\n" 01146 " Enables/Disables dumping of MGCP packets for debugging purposes\n"; 01147 return NULL; 01148 case CLI_GENERATE: 01149 return NULL; 01150 } 01151 01152 if (a->argc != e->args) 01153 return CLI_SHOWUSAGE; 01154 01155 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 01156 mgcpdebug = 1; 01157 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01158 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01159 mgcpdebug = 0; 01160 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01161 } else { 01162 return CLI_SHOWUSAGE; 01163 } 01164 return CLI_SUCCESS; 01165 }
static char* handle_mgcp_show_endpoints | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1036 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock, mgcp_endpoint::chanvars, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, mgcp_endpoint::context, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_subchannel::owner, mgcp_gateway::realtime, mgcp_endpoint::sub, ast_cli_entry::usage, and ast_variable::value.
01037 { 01038 struct mgcp_gateway *mg; 01039 struct mgcp_endpoint *me; 01040 int hasendpoints = 0; 01041 struct ast_variable * v = NULL; 01042 01043 switch (cmd) { 01044 case CLI_INIT: 01045 e->command = "mgcp show endpoints"; 01046 e->usage = 01047 "Usage: mgcp show endpoints\n" 01048 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n"; 01049 return NULL; 01050 case CLI_GENERATE: 01051 return NULL; 01052 } 01053 01054 if (a->argc != 3) { 01055 return CLI_SHOWUSAGE; 01056 } 01057 ast_mutex_lock(&gatelock); 01058 for (mg = gateways; mg; mg = mg->next) { 01059 ast_cli(a->fd, "Gateway '%s' at %s (%s%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->realtime ? "Realtime, " : "", mg->dynamic ? "Dynamic" : "Static"); 01060 for (me = mg->endpoints; me; me = me->next) { 01061 ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle"); 01062 if (me->chanvars) { 01063 ast_cli(a->fd, " Variables:\n"); 01064 for (v = me->chanvars ; v ; v = v->next) { 01065 ast_cli(a->fd, " %s = '%s'\n", v->name, v->value); 01066 } 01067 } 01068 hasendpoints = 1; 01069 } 01070 if (!hasendpoints) { 01071 ast_cli(a->fd, " << No Endpoints Defined >> "); 01072 } 01073 } 01074 ast_mutex_unlock(&gatelock); 01075 return CLI_SUCCESS; 01076 }
static int handle_request | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 3329 of file chan_mgcp.c.
References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_queue_control(), AST_STATE_DOWN, AST_STATE_UP, ast_verb, attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmf_buf, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, f, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_CONF, MGCP_CX_MUTE, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_frame(), mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, transmit_audit_endpoint(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_response(), mgcp_request::verb, and mgcp_gateway::wcardep.
Referenced by mgcpsock_read().
03330 { 03331 char *ev, *s; 03332 struct ast_frame f = { 0, }; 03333 struct mgcp_endpoint *p = sub->parent; 03334 struct mgcp_gateway *g = NULL; 03335 int res; 03336 03337 ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03338 /* Clear out potential response */ 03339 if (!strcasecmp(req->verb, "RSIP")) { 03340 /* Test if this RSIP request is just a keepalive */ 03341 if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03342 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03343 transmit_response(sub, "200", req, "OK"); 03344 } else { 03345 dump_queue(p->parent, p); 03346 dump_cmd_queues(p, NULL); 03347 03348 if ((strcmp(p->name, p->parent->wcardep) != 0)) { 03349 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); 03350 } 03351 /* For RSIP on wildcard we reset all endpoints */ 03352 if (!strcmp(p->name, p->parent->wcardep)) { 03353 /* Reset all endpoints */ 03354 struct mgcp_endpoint *tmp_ep; 03355 03356 g = p->parent; 03357 for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) { 03358 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03359 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03360 struct mgcp_subchannel *tmp_sub, *first_sub; 03361 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03362 03363 first_sub = tmp_ep->sub; 03364 tmp_sub = tmp_ep->sub; 03365 while (tmp_sub) { 03366 mgcp_queue_hangup(tmp_sub); 03367 tmp_sub = tmp_sub->next; 03368 if (tmp_sub == first_sub) 03369 break; 03370 } 03371 } 03372 } 03373 } else if (sub->owner) { 03374 mgcp_queue_hangup(sub); 03375 } 03376 transmit_response(sub, "200", req, "OK"); 03377 /* We don't send NTFY or AUEP to wildcard ep */ 03378 if (strcmp(p->name, p->parent->wcardep) != 0) { 03379 transmit_notify_request(sub, ""); 03380 /* Audit endpoint. 03381 Idea is to prevent lost lines due to race conditions 03382 */ 03383 transmit_audit_endpoint(p); 03384 } 03385 } 03386 } else if (!strcasecmp(req->verb, "NTFY")) { 03387 /* Acknowledge and be sure we keep looking for the same things */ 03388 transmit_response(sub, "200", req, "OK"); 03389 /* Notified of an event */ 03390 ev = get_header(req, "O"); 03391 s = strchr(ev, '/'); 03392 if (s) ev = s + 1; 03393 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03394 /* Keep looking for events unless this was a hangup */ 03395 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03396 transmit_notify_request(sub, p->curtone); 03397 } 03398 if (!strcasecmp(ev, "hd")) { 03399 p->hookstate = MGCP_OFFHOOK; 03400 sub->cxmode = MGCP_CX_SENDRECV; 03401 03402 if (p) { 03403 /* When the endpoint have a Off hook transition we allways 03404 starts without any previous dtmfs */ 03405 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03406 } 03407 03408 handle_hd_hf(sub, ev); 03409 } else if (!strcasecmp(ev, "hf")) { 03410 /* We can assume we are offhook if we received a hookflash */ 03411 /* First let's just do call wait and ignore threeway */ 03412 /* We're currently in charge */ 03413 if (p->hookstate != MGCP_OFFHOOK) { 03414 /* Cisco c7940 sends hf even if the phone is onhook */ 03415 /* Thanks to point on IRC for pointing this out */ 03416 return -1; 03417 } 03418 /* do not let * conference two down channels */ 03419 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) 03420 return -1; 03421 03422 if (p->callwaiting || p->transfer || p->threewaycalling) { 03423 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03424 p->sub = p->sub->next; 03425 03426 /* transfer control to our next subchannel */ 03427 if (!sub->next->owner) { 03428 /* plave the first call on hold and start up a new call */ 03429 sub->cxmode = MGCP_CX_MUTE; 03430 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03431 transmit_modify_request(sub); 03432 if (sub->owner && ast_bridged_channel(sub->owner)) 03433 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03434 sub->next->cxmode = MGCP_CX_RECVONLY; 03435 handle_hd_hf(sub->next, ev); 03436 } else if (sub->owner && sub->next->owner) { 03437 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03438 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03439 /* We made both calls lets conferenct */ 03440 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", 03441 sub->id, sub->next->id, p->name, p->parent->name); 03442 sub->cxmode = MGCP_CX_CONF; 03443 sub->next->cxmode = MGCP_CX_CONF; 03444 if (ast_bridged_channel(sub->next->owner)) 03445 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03446 transmit_modify_request(sub); 03447 transmit_modify_request(sub->next); 03448 } else { 03449 /* Let's flipflop between calls */ 03450 /* XXX Need to check for state up ??? */ 03451 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03452 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03453 sub->id, sub->next->id, p->name, p->parent->name); 03454 sub->cxmode = MGCP_CX_MUTE; 03455 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03456 transmit_modify_request(sub); 03457 if (ast_bridged_channel(sub->owner)) 03458 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03459 03460 if (ast_bridged_channel(sub->next->owner)) 03461 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03462 03463 handle_hd_hf(sub->next, ev); 03464 } 03465 } else { 03466 /* We've most likely lost one of our calls find an active call and bring it up */ 03467 if (sub->owner) { 03468 p->sub = sub; 03469 } else if (sub->next->owner) { 03470 p->sub = sub->next; 03471 } else { 03472 /* We seem to have lost both our calls */ 03473 /* XXX - What do we do now? */ 03474 return -1; 03475 } 03476 if (ast_bridged_channel(p->sub->owner)) 03477 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03478 p->sub->cxmode = MGCP_CX_SENDRECV; 03479 transmit_modify_request(p->sub); 03480 } 03481 } else { 03482 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03483 p->name, p->parent->name); 03484 } 03485 } else if (!strcasecmp(ev, "hu")) { 03486 p->hookstate = MGCP_ONHOOK; 03487 sub->cxmode = MGCP_CX_RECVONLY; 03488 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03489 /* Do we need to send MDCX before a DLCX ? 03490 if (sub->rtp) { 03491 transmit_modify_request(sub); 03492 } 03493 */ 03494 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03495 /* We're allowed to transfer, we have two avtive calls and */ 03496 /* we made at least one of the calls. Let's try and transfer */ 03497 ast_mutex_lock(&p->sub->next->lock); 03498 res = attempt_transfer(p); 03499 if (res < 0) { 03500 if (p->sub->next->owner) { 03501 sub->next->alreadygone = 1; 03502 mgcp_queue_hangup(sub->next); 03503 } 03504 } else if (res) { 03505 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03506 ast_mutex_unlock(&p->sub->next->lock); 03507 return -1; 03508 } 03509 ast_mutex_unlock(&p->sub->next->lock); 03510 } else { 03511 /* Hangup the current call */ 03512 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03513 if (sub->owner) { 03514 sub->alreadygone = 1; 03515 mgcp_queue_hangup(sub); 03516 } else { 03517 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03518 p->name, p->parent->name, sub->id); 03519 /* Instruct the other side to remove the connection since it apparently * 03520 * still thinks the channel is active. * 03521 * For Cisco IAD2421 /BAK/ */ 03522 transmit_connection_del(sub); 03523 } 03524 } 03525 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03526 p->hidecallerid = 0; 03527 if (p->hascallwaiting && !p->callwaiting) { 03528 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03529 p->callwaiting = -1; 03530 } 03531 if (has_voicemail(p)) { 03532 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03533 transmit_notify_request(sub, "L/vmwi(+)"); 03534 } else { 03535 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03536 transmit_notify_request(sub, "L/vmwi(-)"); 03537 } 03538 } 03539 } else if ((strlen(ev) == 1) && 03540 (((ev[0] >= '0') && (ev[0] <= '9')) || 03541 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03542 (ev[0] == '*') || (ev[0] == '#'))) { 03543 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) { 03544 f.frametype = AST_FRAME_DTMF; 03545 f.subclass.integer = ev[0]; 03546 f.src = "mgcp"; 03547 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03548 mgcp_queue_frame(sub, &f); 03549 ast_mutex_lock(&sub->next->lock); 03550 if (sub->next->owner) 03551 mgcp_queue_frame(sub->next, &f); 03552 ast_mutex_unlock(&sub->next->lock); 03553 if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) { 03554 memset(p->curtone, 0, sizeof(p->curtone)); 03555 } 03556 } else { 03557 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; 03558 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; 03559 } 03560 } else if (!strcasecmp(ev, "T")) { 03561 /* Digit timeout -- unimportant */ 03562 } else if (!strcasecmp(ev, "ping")) { 03563 /* ping -- unimportant */ 03564 } else { 03565 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03566 } 03567 } else { 03568 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03569 transmit_response(sub, "510", req, "Unknown verb"); 03570 } 03571 return 0; 03572 }
static void handle_response | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub, | |||
int | result, | |||
unsigned int | ident, | |||
struct mgcp_request * | resp | |||
) | [static] |
Definition at line 2738 of file chan_mgcp.c.
References AST_CONTROL_RINGING, ast_copy_string(), ast_free, ast_log(), ast_queue_control(), AST_STATE_RINGING, ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, dump_cmd_queues(), find_command(), get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, len(), mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_response().
Referenced by handle_incoming(), mgcpsock_read(), and retrans_pkt().
02740 { 02741 char *c; 02742 struct mgcp_request *req; 02743 struct mgcp_gateway *gw = p->parent; 02744 02745 if (result < 200) { 02746 /* provisional response */ 02747 return; 02748 } 02749 02750 if (p->slowsequence) 02751 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02752 else if (sub) 02753 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02754 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02755 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02756 02757 if (!req) { 02758 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", 02759 gw->name, ident); 02760 return; 02761 } 02762 02763 if (p && (result >= 400) && (result <= 599)) { 02764 switch (result) { 02765 case 401: 02766 p->hookstate = MGCP_OFFHOOK; 02767 break; 02768 case 402: 02769 p->hookstate = MGCP_ONHOOK; 02770 break; 02771 case 406: 02772 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02773 break; 02774 case 407: 02775 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02776 break; 02777 } 02778 if (sub) { 02779 if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) { 02780 ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result); 02781 transmit_connection_del(sub); 02782 } 02783 if (sub->owner) { 02784 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02785 result, p->name, p->parent->name, sub ? sub->id:-1); 02786 mgcp_queue_hangup(sub); 02787 } 02788 } else { 02789 if (p->sub->next->owner) { 02790 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02791 result, p->name, p->parent->name, sub ? sub->id:-1); 02792 mgcp_queue_hangup(p->sub); 02793 } 02794 02795 if (p->sub->owner) { 02796 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02797 result, p->name, p->parent->name, sub ? sub->id:-1); 02798 mgcp_queue_hangup(p->sub); 02799 } 02800 02801 dump_cmd_queues(p, NULL); 02802 } 02803 } 02804 02805 if (resp) { 02806 /* responseAck: */ 02807 if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) { 02808 if (sub) { 02809 transmit_response(sub, "000", resp, "OK"); 02810 if (sub->owner && sub->owner->_state == AST_STATE_RINGING) { 02811 ast_queue_control(sub->owner, AST_CONTROL_RINGING); 02812 } 02813 } 02814 } 02815 if (req->cmd == MGCP_CMD_CRCX) { 02816 if ((c = get_header(resp, "I"))) { 02817 if (!ast_strlen_zero(c) && sub) { 02818 /* if we are hanging up do not process this conn. */ 02819 if (sub->owner) { 02820 if (!ast_strlen_zero(sub->cxident)) { 02821 if (strcasecmp(c, sub->cxident)) { 02822 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02823 } 02824 } 02825 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02826 if (sub->tmpdest.sin_addr.s_addr) { 02827 transmit_modify_with_sdp(sub, NULL, 0); 02828 } 02829 } else { 02830 /* XXX delete this one 02831 callid and conn id may already be lost. 02832 so the following del conn may have a side effect of 02833 cleaning up the next subchannel */ 02834 transmit_connection_del(sub); 02835 } 02836 } 02837 } 02838 } 02839 02840 if (req->cmd == MGCP_CMD_AUEP) { 02841 /* check stale connection ids */ 02842 if ((c = get_header(resp, "I"))) { 02843 char *v, *n; 02844 int len; 02845 while ((v = get_csv(c, &len, &n))) { 02846 if (len) { 02847 if (strncasecmp(v, p->sub->cxident, len) && 02848 strncasecmp(v, p->sub->next->cxident, len)) { 02849 /* connection id not found. delete it */ 02850 char cxident[80] = ""; 02851 02852 if (len > (sizeof(cxident) - 1)) 02853 len = sizeof(cxident) - 1; 02854 ast_copy_string(cxident, v, len); 02855 ast_verb(3, "Non existing connection id %s on %s@%s \n", 02856 cxident, p->name, gw->name); 02857 transmit_connection_del_w_params(p, NULL, cxident); 02858 } 02859 } 02860 c = n; 02861 } 02862 } 02863 02864 /* Try to determine the hookstate returned from an audit endpoint command */ 02865 if ((c = get_header(resp, "ES"))) { 02866 if (!ast_strlen_zero(c)) { 02867 if (strstr(c, "hu")) { 02868 if (p->hookstate != MGCP_ONHOOK) { 02869 /* XXX cleanup if we think we are offhook XXX */ 02870 if ((p->sub->owner || p->sub->next->owner ) && 02871 p->hookstate == MGCP_OFFHOOK) 02872 mgcp_queue_hangup(sub); 02873 p->hookstate = MGCP_ONHOOK; 02874 02875 /* update the requested events according to the new hookstate */ 02876 transmit_notify_request(p->sub, ""); 02877 02878 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02879 } 02880 } else if (strstr(c, "hd")) { 02881 if (p->hookstate != MGCP_OFFHOOK) { 02882 p->hookstate = MGCP_OFFHOOK; 02883 02884 /* update the requested events according to the new hookstate */ 02885 transmit_notify_request(p->sub, ""); 02886 02887 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02888 } 02889 } 02890 } 02891 } 02892 } 02893 02894 if (resp && resp->lines) { 02895 /* do not process sdp if we are hanging up. this may be a late response */ 02896 if (sub && sub->owner) { 02897 if (!sub->rtp) 02898 start_rtp(sub); 02899 if (sub->rtp) 02900 process_sdp(sub, resp); 02901 } 02902 } 02903 } 02904 02905 ast_free(req); 02906 }
static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 489 of file chan_mgcp.c.
References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), mgcp_endpoint::mailbox, mbox(), and strsep().
00490 { 00491 int new_msgs; 00492 struct ast_event *event; 00493 char *mbox, *cntx; 00494 00495 cntx = mbox = ast_strdupa(p->mailbox); 00496 strsep(&cntx, "@"); 00497 if (ast_strlen_zero(cntx)) 00498 cntx = "default"; 00499 00500 event = ast_event_get_cached(AST_EVENT_MWI, 00501 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 00502 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 00503 AST_EVENT_IE_END); 00504 00505 if (event) { 00506 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 00507 ast_event_destroy(event); 00508 } else 00509 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 00510 00511 return new_msgs; 00512 }
static int init_req | ( | struct mgcp_endpoint * | p, | |
struct mgcp_request * | req, | |||
char * | verb | |||
) | [static] |
Definition at line 2101 of file chan_mgcp.c.
References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_gateway::isnamedottedip, mgcp_request::len, LOG_WARNING, MGCP_MAX_HEADERS, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, oseq, and mgcp_endpoint::parent.
Referenced by initreqprep(), reqprep(), and transmit_register().
02102 { 02103 /* Initialize a response */ 02104 if (req->headers || req->len) { 02105 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02106 return -1; 02107 } 02108 req->header[req->headers] = req->data + req->len; 02109 /* check if we need brackets around the gw name */ 02110 if (p->parent->isnamedottedip) { 02111 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : ""); 02112 } else { 02113 + snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : ""); 02114 } 02115 req->len += strlen(req->header[req->headers]); 02116 if (req->headers < MGCP_MAX_HEADERS) { 02117 req->headers++; 02118 } else { 02119 ast_log(LOG_WARNING, "Out of header space\n"); 02120 } 02121 return 0; 02122 }
static int init_resp | ( | struct mgcp_request * | req, | |
char * | resp, | |||
struct mgcp_request * | orig, | |||
char * | resprest | |||
) | [static] |
Definition at line 2083 of file chan_mgcp.c.
References ast_log(), mgcp_request::data, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, LOG_WARNING, and MGCP_MAX_HEADERS.
Referenced by respprep().
02084 { 02085 /* Initialize a response */ 02086 if (req->headers || req->len) { 02087 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02088 return -1; 02089 } 02090 req->header[req->headers] = req->data + req->len; 02091 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 02092 req->len += strlen(req->header[req->headers]); 02093 if (req->headers < MGCP_MAX_HEADERS) { 02094 req->headers++; 02095 } else { 02096 ast_log(LOG_WARNING, "Out of header space\n"); 02097 } 02098 return 0; 02099 }
static int load_module | ( | void | ) | [static] |
load_module: PBX load module - initialization ---
Definition at line 4777 of file chan_mgcp.c.
References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, cli_mgcp, io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, mgcp_rtp_glue, mgcp_tech, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().
04778 { 04779 if (!(sched = sched_context_create())) { 04780 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 04781 return AST_MODULE_LOAD_FAILURE; 04782 } 04783 04784 if (!(io = io_context_create())) { 04785 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 04786 sched_context_destroy(sched); 04787 return AST_MODULE_LOAD_FAILURE; 04788 } 04789 04790 if (reload_config(0)) 04791 return AST_MODULE_LOAD_DECLINE; 04792 04793 /* Make sure we can register our mgcp channel type */ 04794 if (ast_channel_register(&mgcp_tech)) { 04795 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); 04796 io_context_destroy(io); 04797 sched_context_destroy(sched); 04798 return AST_MODULE_LOAD_FAILURE; 04799 } 04800 04801 ast_rtp_glue_register(&mgcp_rtp_glue); 04802 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04803 04804 /* And start the monitor for the first time */ 04805 restart_monitor(); 04806 04807 return AST_MODULE_LOAD_SUCCESS; 04808 }
static int mgcp_alloc_pktcgate | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2403 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_pktccops_gate_alloc(), mgcp_subchannel::gate, cops_gate::gate_open, GATE_SET, mgcp_pktcgate_open(), mgcp_pktcgate_remove(), mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::sub, and cops_gate::tech_pvt.
Referenced by start_rtp().
02404 { 02405 struct mgcp_endpoint *p = sub->parent; 02406 sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr), 02407 8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove); 02408 02409 if (!sub->gate) { 02410 return 0; 02411 } 02412 sub->gate->tech_pvt = sub; 02413 sub->gate->gate_open = &mgcp_pktcgate_open; 02414 return 1; 02415 }
static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1174 of file chan_mgcp.c.
References ast_channel::_state, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, ast_verb, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_subchannel::lock, MGCP_CX_SENDRECV, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01175 { 01176 int res = 0; 01177 struct mgcp_subchannel *sub = ast->tech_pvt; 01178 struct mgcp_endpoint *p = sub->parent; 01179 01180 ast_mutex_lock(&sub->lock); 01181 sub->cxmode = MGCP_CX_SENDRECV; 01182 if (!sub->rtp) { 01183 start_rtp(sub); 01184 } else { 01185 transmit_modify_request(sub); 01186 } 01187 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", 01188 ast->name, p->name, p->parent->name, sub->id); 01189 if (ast->_state != AST_STATE_UP) { 01190 ast_setstate(ast, AST_STATE_UP); 01191 ast_debug(1, "mgcp_answer(%s)\n", ast->name); 01192 transmit_notify_request(sub, ""); 01193 transmit_modify_request(sub); 01194 } 01195 ast_mutex_unlock(&sub->lock); 01196 return res; 01197 }
static int mgcp_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 834 of file chan_mgcp.c.
References ast_channel::_state, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), mgcp_subchannel::callid, ast_channel::connected, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, ast_party_connected_line::id, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, ast_party_id::name, ast_channel::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, S_COR, start_rtp(), ast_party_name::str, ast_party_number::str, ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, ast_party_name::valid, ast_party_number::valid, and ast_channel::varshead.
00835 { 00836 int res; 00837 struct mgcp_endpoint *p; 00838 struct mgcp_subchannel *sub; 00839 char tone[50] = ""; 00840 const char *distinctive_ring = NULL; 00841 struct varshead *headp; 00842 struct ast_var_t *current; 00843 00844 ast_debug(3, "MGCP mgcp_call(%s)\n", ast->name); 00845 sub = ast->tech_pvt; 00846 p = sub->parent; 00847 headp = &ast->varshead; 00848 AST_LIST_TRAVERSE(headp,current,entries) { 00849 /* Check whether there is an ALERT_INFO variable */ 00850 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { 00851 distinctive_ring = ast_var_value(current); 00852 } 00853 } 00854 00855 ast_mutex_lock(&sub->lock); 00856 switch (p->hookstate) { 00857 case MGCP_OFFHOOK: 00858 if (!ast_strlen_zero(distinctive_ring)) { 00859 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); 00860 ast_debug(3, "MGCP distinctive callwait %s\n", tone); 00861 } else { 00862 ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone)); 00863 ast_debug(3, "MGCP normal callwait %s\n", tone); 00864 } 00865 break; 00866 case MGCP_ONHOOK: 00867 default: 00868 if (!ast_strlen_zero(distinctive_ring)) { 00869 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); 00870 ast_debug(3, "MGCP distinctive ring %s\n", tone); 00871 } else { 00872 ast_copy_string(tone, "L/rg", sizeof(tone)); 00873 ast_debug(3, "MGCP default ring\n"); 00874 } 00875 break; 00876 } 00877 00878 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00879 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name); 00880 ast_mutex_unlock(&sub->lock); 00881 return -1; 00882 } 00883 00884 res = 0; 00885 sub->outgoing = 1; 00886 sub->cxmode = MGCP_CX_RECVONLY; 00887 ast_setstate(ast, AST_STATE_RINGING); 00888 if (p->type == TYPE_LINE) { 00889 if (!sub->rtp) { 00890 start_rtp(sub); 00891 } else { 00892 transmit_modify_request(sub); 00893 } 00894 00895 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00896 /* try to prevent a callwait from disturbing the other connection */ 00897 sub->next->cxmode = MGCP_CX_RECVONLY; 00898 transmit_modify_request(sub->next); 00899 } 00900 00901 transmit_notify_request_with_callerid(sub, tone, 00902 S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""), 00903 S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, "")); 00904 ast_setstate(ast, AST_STATE_RINGING); 00905 00906 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00907 /* Put the connection back in sendrecv */ 00908 sub->next->cxmode = MGCP_CX_SENDRECV; 00909 transmit_modify_request(sub->next); 00910 } 00911 } else { 00912 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); 00913 res = -1; 00914 } 00915 ast_mutex_unlock(&sub->lock); 00916 return res; 00917 }
static int mgcp_devicestate | ( | void * | data | ) | [static] |
mgcp_devicestate: channel callback for device status monitoring
data | tech/resource name of MGCP device to query |
Definition at line 1359 of file chan_mgcp.c.
References AST_DEVICE_INVALID, ast_mutex_lock, ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_gateway::name, and mgcp_gateway::next.
01360 { 01361 struct mgcp_gateway *g; 01362 struct mgcp_endpoint *e = NULL; 01363 char *tmp, *endpt, *gw; 01364 int ret = AST_DEVICE_INVALID; 01365 01366 endpt = ast_strdupa(data); 01367 if ((tmp = strchr(endpt, '@'))) { 01368 *tmp++ = '\0'; 01369 gw = tmp; 01370 } else 01371 goto error; 01372 01373 ast_mutex_lock(&gatelock); 01374 for (g = gateways; g; g = g->next) { 01375 if (strcasecmp(g->name, gw) == 0) { 01376 e = g->endpoints; 01377 break; 01378 } 01379 } 01380 01381 if (!e) 01382 goto error; 01383 01384 for (; e; e = e->next) { 01385 if (strcasecmp(e->name, endpt) == 0) { 01386 break; 01387 } 01388 } 01389 01390 if (!e) 01391 goto error; 01392 01393 /* 01394 * As long as the gateway/endpoint is valid, we'll 01395 * assume that the device is available and its state 01396 * can be tracked. 01397 */ 01398 ret = AST_DEVICE_UNKNOWN; 01399 01400 error: 01401 ast_mutex_unlock(&gatelock); 01402 return ret; 01403 }
static int mgcp_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 1281 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, ast_channel::name, mgcp_subchannel::owner, and ast_channel::tech_pvt.
01282 { 01283 struct mgcp_subchannel *sub = newchan->tech_pvt; 01284 01285 ast_mutex_lock(&sub->lock); 01286 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name); 01287 if (sub->owner != oldchan) { 01288 ast_mutex_unlock(&sub->lock); 01289 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01290 return -1; 01291 } 01292 sub->owner = newchan; 01293 ast_mutex_unlock(&sub->lock); 01294 return 0; 01295 }
static format_t mgcp_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 4425 of file chan_mgcp.c.
References mgcp_endpoint::capability, mgcp_subchannel::parent, mgcp_endpoint::sub, and ast_channel::tech_pvt.
04426 { 04427 struct mgcp_subchannel *sub = chan->tech_pvt; 04428 struct mgcp_endpoint *p = sub->parent; 04429 return p->capability; 04430 }
static enum ast_rtp_glue_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp_instance ** | instance | |||
) | [static] |
Definition at line 4398 of file chan_mgcp.c.
References ao2_ref, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, mgcp_endpoint::directmedia, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
04399 { 04400 struct mgcp_subchannel *sub = NULL; 04401 04402 if (!(sub = chan->tech_pvt) || !(sub->rtp)) 04403 return AST_RTP_GLUE_RESULT_FORBID; 04404 04405 *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL; 04406 04407 if (sub->parent->directmedia) 04408 return AST_RTP_GLUE_RESULT_REMOTE; 04409 else 04410 return AST_RTP_GLUE_RESULT_LOCAL; 04411 }
static int mgcp_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 919 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_debug, ast_dsp_free(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, ast_pktccops_gate_alloc(), ast_rtp_instance_destroy(), ast_strlen_zero(), ast_verb, ast_channel::caller, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, cops_gate::deltimer, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, mgcp_subchannel::gate, GATE_ALLOC_PROGRESS, GATE_ALLOCATED, GATE_DEL, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, ast_party_caller::id, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, ast_party_id::name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, mgcp_subchannel::rtp, S_COR, cops_gate::state, ast_party_name::str, ast_party_number::str, mgcp_endpoint::sub, cops_gate::tech_pvt, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), ast_party_name::valid, and ast_party_number::valid.
00920 { 00921 struct mgcp_subchannel *sub = ast->tech_pvt; 00922 struct mgcp_endpoint *p = sub->parent; 00923 struct ast_channel *bridged; 00924 00925 ast_debug(1, "mgcp_hangup(%s)\n", ast->name); 00926 if (!ast->tech_pvt) { 00927 ast_debug(1, "Asked to hangup channel not connected\n"); 00928 return 0; 00929 } 00930 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) { 00931 ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n"); 00932 return 0; 00933 } 00934 ast_mutex_lock(&sub->lock); 00935 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name); 00936 00937 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) { 00938 /* check whether other channel is active. */ 00939 if (!sub->next->owner) { 00940 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 00941 p->dtmfmode &= ~MGCP_DTMF_INBAND; 00942 } 00943 ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name); 00944 ast_dsp_free(p->dsp); 00945 p->dsp = NULL; 00946 } 00947 } 00948 00949 sub->owner = NULL; 00950 00951 /* for deleting gate */ 00952 if (p->pktcgatealloc && sub->gate) { 00953 sub->gate->gate_open = NULL; 00954 sub->gate->gate_remove = NULL; 00955 sub->gate->got_dq_gi = NULL; 00956 sub->gate->tech_pvt = NULL; 00957 if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) { 00958 ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL); 00959 } else { 00960 sub->gate->deltimer = time(NULL) + 5; 00961 } 00962 sub->gate = NULL; 00963 } 00964 00965 if (!ast_strlen_zero(sub->cxident)) { 00966 transmit_connection_del(sub); 00967 } 00968 sub->cxident[0] = '\0'; 00969 if ((sub == p->sub) && sub->next->owner) { 00970 if (p->hookstate == MGCP_OFFHOOK) { 00971 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00972 /* ncs fix! */ 00973 bridged = ast_bridged_channel(sub->next->owner); 00974 transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"), 00975 S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""), 00976 S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, "")); 00977 } 00978 } else { 00979 /* set our other connection as the primary and swith over to it */ 00980 p->sub = sub->next; 00981 p->sub->cxmode = MGCP_CX_RECVONLY; 00982 transmit_modify_request(p->sub); 00983 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00984 bridged = ast_bridged_channel(sub->next->owner); 00985 transmit_notify_request_with_callerid(p->sub, "L/rg", 00986 S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""), 00987 S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, "")); 00988 } 00989 } 00990 00991 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) { 00992 transmit_notify_request(sub, p->ncs ? "" : "L/v"); 00993 } else if (p->hookstate == MGCP_OFFHOOK) { 00994 transmit_notify_request(sub, "L/ro"); 00995 } else { 00996 transmit_notify_request(sub, ""); 00997 } 00998 00999 ast->tech_pvt = NULL; 01000 sub->alreadygone = 0; 01001 sub->outgoing = 0; 01002 sub->cxmode = MGCP_CX_INACTIVE; 01003 sub->callid[0] = '\0'; 01004 if (p) { 01005 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 01006 } 01007 /* Reset temporary destination */ 01008 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 01009 if (sub->rtp) { 01010 ast_rtp_instance_destroy(sub->rtp); 01011 sub->rtp = NULL; 01012 } 01013 01014 ast_module_unref(ast_module_info->self); 01015 01016 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) { 01017 p->hidecallerid = 0; 01018 if (p->hascallwaiting && !p->callwaiting) { 01019 ast_verb(3, "Enabling call waiting on %s\n", ast->name); 01020 p->callwaiting = -1; 01021 } 01022 if (has_voicemail(p)) { 01023 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 01024 ast->name, p->name, p->parent->name); 01025 transmit_notify_request(sub, "L/vmwi(+)"); 01026 } else { 01027 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 01028 ast->name, p->name, p->parent->name); 01029 transmit_notify_request(sub, "L/vmwi(-)"); 01030 } 01031 } 01032 ast_mutex_unlock(&sub->lock); 01033 return 0; 01034 }
static int mgcp_indicate | ( | struct ast_channel * | ast, | |
int | ind, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 1437 of file chan_mgcp.c.
References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), control2str(), mgcp_subchannel::lock, LOG_WARNING, ast_channel::name, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01438 { 01439 struct mgcp_subchannel *sub = ast->tech_pvt; 01440 int res = 0; 01441 01442 ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", 01443 ind, control2str(ind), ast->name); 01444 ast_mutex_lock(&sub->lock); 01445 switch(ind) { 01446 case AST_CONTROL_RINGING: 01447 #ifdef DLINK_BUGGY_FIRMWARE 01448 transmit_notify_request(sub, "rt"); 01449 #else 01450 if (!sub->sdpsent) { /* will hide the inband progress!!! */ 01451 transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt"); 01452 } 01453 #endif 01454 break; 01455 case AST_CONTROL_BUSY: 01456 transmit_notify_request(sub, "L/bz"); 01457 break; 01458 case AST_CONTROL_CONGESTION: 01459 transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg"); 01460 break; 01461 case AST_CONTROL_HOLD: 01462 ast_moh_start(ast, data, NULL); 01463 break; 01464 case AST_CONTROL_UNHOLD: 01465 ast_moh_stop(ast); 01466 break; 01467 case AST_CONTROL_SRCUPDATE: 01468 ast_rtp_instance_update_source(sub->rtp); 01469 break; 01470 case AST_CONTROL_SRCCHANGE: 01471 ast_rtp_instance_change_source(sub->rtp); 01472 break; 01473 case AST_CONTROL_PROGRESS: 01474 case AST_CONTROL_PROCEEDING: 01475 transmit_modify_request(sub); 01476 case -1: 01477 transmit_notify_request(sub, ""); 01478 break; 01479 default: 01480 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); 01481 res = -1; 01482 } 01483 ast_mutex_unlock(&sub->lock); 01484 return res; 01485 }
static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, | |
int | state, | |||
const char * | linkedid | |||
) | [static] |
Definition at line 1487 of file chan_mgcp.c.
References accountcode, mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_get_encoded_str(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_instance_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, ast_channel::caller, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, mgcp_endpoint::chanvars, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, ast_channel::exten, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, language, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_tech, ast_channel::name, ast_variable::name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, ast_variable::next, ast_party_id::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, ast_party_number::str, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, and ast_channel::writeformat.
Referenced by handle_hd_hf(), and mgcp_request().
01488 { 01489 struct ast_channel *tmp; 01490 struct ast_variable *v = NULL; 01491 struct mgcp_endpoint *i = sub->parent; 01492 int fmt; 01493 01494 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); 01495 if (tmp) { 01496 tmp->tech = &mgcp_tech; 01497 tmp->nativeformats = i->capability; 01498 if (!tmp->nativeformats) { 01499 tmp->nativeformats = capability; 01500 } 01501 fmt = ast_best_codec(tmp->nativeformats); 01502 if (sub->rtp) { 01503 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); 01504 } 01505 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { 01506 i->dsp = ast_dsp_new(); 01507 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); 01508 /* this is to prevent clipping of dtmf tones during dsp processing */ 01509 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); 01510 } else { 01511 i->dsp = NULL; 01512 } 01513 if (state == AST_STATE_RING) 01514 tmp->rings = 1; 01515 tmp->writeformat = fmt; 01516 tmp->rawwriteformat = fmt; 01517 tmp->readformat = fmt; 01518 tmp->rawreadformat = fmt; 01519 tmp->tech_pvt = sub; 01520 if (!ast_strlen_zero(i->language)) 01521 ast_string_field_set(tmp, language, i->language); 01522 if (!ast_strlen_zero(i->accountcode)) 01523 ast_string_field_set(tmp, accountcode, i->accountcode); 01524 if (i->amaflags) 01525 tmp->amaflags = i->amaflags; 01526 sub->owner = tmp; 01527 ast_module_ref(ast_module_info->self); 01528 tmp->callgroup = i->callgroup; 01529 tmp->pickupgroup = i->pickupgroup; 01530 ast_string_field_set(tmp, call_forward, i->call_forward); 01531 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 01532 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 01533 01534 /* Don't use ast_set_callerid() here because it will 01535 * generate a needless NewCallerID event */ 01536 if (!ast_strlen_zero(i->cid_num)) { 01537 tmp->caller.ani.number.valid = 1; 01538 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 01539 } 01540 01541 if (!i->adsi) { 01542 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01543 } 01544 tmp->priority = 1; 01545 01546 /* Set channel variables for this call from configuration */ 01547 for (v = i->chanvars ; v ; v = v->next) { 01548 char valuebuf[1024]; 01549 pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf))); 01550 } 01551 01552 if (sub->rtp) { 01553 ast_jb_configure(tmp, &global_jbconf); 01554 } 01555 if (state != AST_STATE_DOWN) { 01556 if (ast_pbx_start(tmp)) { 01557 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 01558 ast_hangup(tmp); 01559 tmp = NULL; 01560 } 01561 } 01562 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", 01563 tmp->name, ast_state2str(state)); 01564 } else { 01565 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01566 } 01567 return tmp; 01568 }
static int mgcp_pktcgate_open | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2390 of file chan_mgcp.c.
References ast_debug, ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::gate, cops_gate::gateid, mgcp_subchannel::lock, mgcp_subchannel::sdpsent, cops_gate::tech_pvt, and transmit_modify_with_sdp().
Referenced by mgcp_alloc_pktcgate().
02391 { 02392 struct mgcp_subchannel *sub = gate->tech_pvt; 02393 if (!sub) { 02394 return 1; 02395 } 02396 ast_mutex_lock(&sub->lock); 02397 ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid); 02398 if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0); 02399 ast_mutex_unlock(&sub->lock); 02400 return 1; 02401 }
static int mgcp_pktcgate_remove | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2367 of file chan_mgcp.c.
References AST_CAUSE_REQUESTED_CHAN_UNAVAIL, ast_channel_unlock, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), mgcp_subchannel::gate, GATE_CLOSED, cops_gate::gateid, mgcp_endpoint::hangupongateremove, mgcp_subchannel::lock, mgcp_subchannel::owner, mgcp_subchannel::parent, cops_gate::state, and cops_gate::tech_pvt.
Referenced by mgcp_alloc_pktcgate().
02368 { 02369 struct mgcp_subchannel *sub = gate->tech_pvt; 02370 02371 if (!sub) { 02372 return 1; 02373 } 02374 02375 ast_mutex_lock(&sub->lock); 02376 ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid); 02377 if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) { 02378 sub->gate = NULL; 02379 if (sub->owner) { 02380 ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL); 02381 ast_channel_unlock(sub->owner); 02382 } 02383 } else { 02384 sub->gate = NULL; 02385 } 02386 ast_mutex_unlock(&sub->lock); 02387 return 1; 02388 }
static int mgcp_postrequest | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub, | |||
char * | data, | |||
int | len, | |||
unsigned int | seqno | |||
) | [static] |
Definition at line 707 of file chan_mgcp.c.
References __mgcp_xmit(), ast_free, ast_malloc, ast_mutex_lock, ast_mutex_unlock, ast_sched_add(), ast_tvnow(), DEFAULT_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, mgcp_endpoint::next, mgcp_endpoint::parent, retrans_pkt(), and mgcp_gateway::retransid.
Referenced by find_command(), and send_request().
00709 { 00710 struct mgcp_message *msg; 00711 struct mgcp_message *cur; 00712 struct mgcp_gateway *gw; 00713 struct timeval now; 00714 00715 if (!(msg = ast_malloc(sizeof(*msg) + len))) { 00716 return -1; 00717 } 00718 if (!(gw = ((p && p->parent) ? p->parent : NULL))) { 00719 ast_free(msg); 00720 return -1; 00721 } 00722 00723 msg->owner_sub = sub; 00724 msg->owner_ep = p; 00725 msg->seqno = seqno; 00726 msg->next = NULL; 00727 msg->len = len; 00728 msg->retrans = 0; 00729 memcpy(msg->buf, data, msg->len); 00730 00731 ast_mutex_lock(&gw->msgs_lock); 00732 for (cur = gw->msgs; cur && cur->next; cur = cur->next); 00733 if (cur) { 00734 cur->next = msg; 00735 } else { 00736 gw->msgs = msg; 00737 } 00738 00739 now = ast_tvnow(); 00740 msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS; 00741 00742 if (gw->retransid == -1) 00743 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw); 00744 ast_mutex_unlock(&gw->msgs_lock); 00745 __mgcp_xmit(gw, msg->buf, msg->len); 00746 /* XXX Should schedule retransmission XXX */ 00747 return 0; 00748 }
static int mgcp_prune_realtime_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 3695 of file chan_mgcp.c.
References ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_strlen_zero(), mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, mgcp_gateway::endpoints, mgcp_subchannel::gate, mgcp_gateway::ha, mgcp_subchannel::lock, mgcp_endpoint::lock, MAX_SUBS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::realtime, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, and mgcp_endpoint::sub.
Referenced by do_monitor().
03696 { 03697 struct mgcp_endpoint *enext, *e; 03698 struct mgcp_subchannel *s, *sub; 03699 int i, prune = 1; 03700 03701 if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) { 03702 ast_mutex_unlock(&g->msgs_lock); 03703 return 0; 03704 } 03705 03706 for (e = g->endpoints; e; e = e->next) { 03707 ast_mutex_lock(&e->lock); 03708 if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) { 03709 prune = 0; 03710 } else if (e->rqnt_queue || e->cmd_queue) { 03711 prune = 0; 03712 } 03713 s = e->sub; 03714 for (i = 0; (i < MAX_SUBS) && s; i++) { 03715 ast_mutex_lock(&s->lock); 03716 if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) { 03717 prune = 0; 03718 } else if (s->cx_queue) { 03719 prune = 0; 03720 } 03721 s = s->next; 03722 } 03723 } 03724 03725 for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) { 03726 for (i = 0; (i < MAX_SUBS) && sub; i++) { 03727 s = sub; 03728 sub = sub->next; 03729 ast_mutex_unlock(&s->lock); 03730 ast_mutex_unlock(&s->cx_queue_lock); 03731 if (prune) { 03732 ast_mutex_destroy(&s->lock); 03733 ast_mutex_destroy(&s->cx_queue_lock); 03734 free(s); 03735 } 03736 } 03737 ast_mutex_unlock(&e->lock); 03738 ast_mutex_unlock(&e->rqnt_queue_lock); 03739 ast_mutex_unlock(&e->cmd_queue_lock); 03740 if (prune) { 03741 ast_mutex_destroy(&e->lock); 03742 ast_mutex_destroy(&e->rqnt_queue_lock); 03743 ast_mutex_destroy(&e->cmd_queue_lock); 03744 free(e); 03745 } 03746 } 03747 if (prune) { 03748 ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name); 03749 } 03750 return prune; 03751 }
static void mgcp_queue_control | ( | struct mgcp_subchannel * | sub, | |
int | control | |||
) | [static] |
Definition at line 646 of file chan_mgcp.c.
References AST_FRAME_CONTROL, f, and mgcp_queue_frame().
Referenced by handle_hd_hf().
00647 { 00648 struct ast_frame f = { AST_FRAME_CONTROL, { control } }; 00649 return mgcp_queue_frame(sub, &f); 00650 }
static void mgcp_queue_frame | ( | struct mgcp_subchannel * | sub, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 612 of file chan_mgcp.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, f, mgcp_subchannel::lock, and mgcp_subchannel::owner.
Referenced by handle_request(), and mgcp_queue_control().
00613 { 00614 for (;;) { 00615 if (sub->owner) { 00616 if (!ast_channel_trylock(sub->owner)) { 00617 ast_queue_frame(sub->owner, f); 00618 ast_channel_unlock(sub->owner); 00619 break; 00620 } else { 00621 DEADLOCK_AVOIDANCE(&sub->lock); 00622 } 00623 } else { 00624 break; 00625 } 00626 } 00627 }
static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 629 of file chan_mgcp.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.
Referenced by attempt_transfer(), handle_request(), handle_response(), and start_rtp().
00630 { 00631 for (;;) { 00632 if (sub->owner) { 00633 if (!ast_channel_trylock(sub->owner)) { 00634 ast_queue_hangup(sub->owner); 00635 ast_channel_unlock(sub->owner); 00636 break; 00637 } else { 00638 DEADLOCK_AVOIDANCE(&sub->lock); 00639 } 00640 } else { 00641 break; 00642 } 00643 } 00644 }
static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1230 of file chan_mgcp.c.
References ast_mutex_lock, ast_mutex_unlock, f, mgcp_subchannel::lock, mgcp_rtp_read(), and ast_channel::tech_pvt.
01231 { 01232 struct ast_frame *f; 01233 struct mgcp_subchannel *sub = ast->tech_pvt; 01234 ast_mutex_lock(&sub->lock); 01235 f = mgcp_rtp_read(sub); 01236 ast_mutex_unlock(&sub->lock); 01237 return f; 01238 }
static char * mgcp_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4810 of file chan_mgcp.c.
References ast_cli_args::argc, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, LOG_WARNING, mgcp_reload_lock, mgcp_reloading, restart_monitor(), and ast_cli_entry::usage.
Referenced by reload(), and unload_module().
04811 { 04812 static int deprecated = 0; 04813 04814 if (e) { 04815 switch (cmd) { 04816 case CLI_INIT: 04817 e->command = "mgcp reload"; 04818 e->usage = 04819 "Usage: mgcp reload\n" 04820 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; 04821 return NULL; 04822 case CLI_GENERATE: 04823 return NULL; 04824 } 04825 } 04826 04827 if (!deprecated && a && a->argc > 0) { 04828 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); 04829 deprecated = 1; 04830 } 04831 04832 ast_mutex_lock(&mgcp_reload_lock); 04833 if (mgcp_reloading) { 04834 ast_verbose("Previous mgcp reload not yet done\n"); 04835 } else { 04836 mgcp_reloading = 1; 04837 } 04838 ast_mutex_unlock(&mgcp_reload_lock); 04839 restart_monitor(); 04840 return CLI_SUCCESS; 04841 }
static struct ast_channel * mgcp_request | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 3902 of file chan_mgcp.c.
References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_getformatname_multiple(), ast_log(), ast_mutex_unlock, AST_STATE_DOWN, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, capability, mgcp_endpoint::dnd, find_subchannel_and_lock(), has_voicemail(), mgcp_endpoint::hookstate, ast_channel::linkedid, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), MGCP_ONHOOK, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), and transmit_notify_request().
03903 { 03904 format_t oldformat; 03905 struct mgcp_subchannel *sub; 03906 struct ast_channel *tmpc = NULL; 03907 char tmp[256]; 03908 char *dest = data; 03909 03910 oldformat = format; 03911 format &= capability; 03912 if (!format) { 03913 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format)); 03914 /*return NULL;*/ 03915 } 03916 ast_copy_string(tmp, dest, sizeof(tmp)); 03917 if (ast_strlen_zero(tmp)) { 03918 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); 03919 return NULL; 03920 } 03921 if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) { 03922 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); 03923 *cause = AST_CAUSE_UNREGISTERED; 03924 return NULL; 03925 } 03926 03927 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); 03928 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 03929 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); 03930 /* Must be busy */ 03931 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || 03932 ((!sub->parent->callwaiting) && (sub->owner)) || 03933 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { 03934 if (sub->parent->hookstate == MGCP_ONHOOK) { 03935 if (has_voicemail(sub->parent)) { 03936 transmit_notify_request(sub,"L/vmwi(+)"); 03937 } else { 03938 transmit_notify_request(sub,"L/vmwi(-)"); 03939 } 03940 } 03941 *cause = AST_CAUSE_BUSY; 03942 ast_mutex_unlock(&sub->lock); 03943 return NULL; 03944 } 03945 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL); 03946 ast_mutex_unlock(&sub->lock); 03947 if (!tmpc) 03948 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); 03949 restart_monitor(); 03950 return tmpc; 03951 }
static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 1199 of file chan_mgcp.c.
References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, f, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, and ast_channel::writeformat.
Referenced by mgcp_read().
01200 { 01201 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ 01202 struct ast_frame *f; 01203 01204 f = ast_rtp_instance_read(sub->rtp, 0); 01205 /* Don't send RFC2833 if we're not supposed to */ 01206 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) 01207 return &ast_null_frame; 01208 if (sub->owner) { 01209 /* We already hold the channel lock */ 01210 if (f->frametype == AST_FRAME_VOICE) { 01211 if (f->subclass.codec != sub->owner->nativeformats) { 01212 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); 01213 sub->owner->nativeformats = f->subclass.codec; 01214 ast_set_read_format(sub->owner, sub->owner->readformat); 01215 ast_set_write_format(sub->owner, sub->owner->writeformat); 01216 } 01217 /* Courtesy fearnor aka alex@pilosoft.com */ 01218 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { 01219 #if 0 01220 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); 01221 #endif 01222 f = ast_dsp_process(sub->owner, sub->parent->dsp, f); 01223 } 01224 } 01225 } 01226 return f; 01227 }
static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1297 of file chan_mgcp.c.
References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, and ast_channel::tech_pvt.
01298 { 01299 struct mgcp_subchannel *sub = ast->tech_pvt; 01300 struct mgcp_endpoint *p = sub->parent; 01301 int res = 0; 01302 01303 ast_mutex_lock(&sub->lock); 01304 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01305 ast_debug(1, "Sending DTMF using inband/hybrid\n"); 01306 res = -1; /* Let asterisk play inband indications */ 01307 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01308 ast_debug(1, "Sending DTMF using RFC2833"); 01309 ast_rtp_instance_dtmf_begin(sub->rtp, digit); 01310 } else { 01311 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01312 } 01313 ast_mutex_unlock(&sub->lock); 01314 01315 return res; 01316 }
static int mgcp_senddigit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1318 of file chan_mgcp.c.
References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_end(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_endpoint::ncs, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, and transmit_notify_request().
01319 { 01320 struct mgcp_subchannel *sub = ast->tech_pvt; 01321 struct mgcp_endpoint *p = sub->parent; 01322 int res = 0; 01323 char tmp[4]; 01324 01325 ast_mutex_lock(&sub->lock); 01326 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01327 ast_debug(1, "Stopping DTMF using inband/hybrid\n"); 01328 res = -1; /* Tell Asterisk to stop inband indications */ 01329 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01330 ast_debug(1, "Stopping DTMF using RFC2833\n"); 01331 if (sub->parent->ncs) { 01332 tmp[0] = digit; 01333 tmp[1] = '\0'; 01334 } else { 01335 tmp[0] = 'D'; 01336 tmp[1] = '/'; 01337 tmp[2] = digit; 01338 tmp[3] = '\0'; 01339 } 01340 transmit_notify_request(sub, tmp); 01341 ast_rtp_instance_dtmf_end(sub->rtp, digit); 01342 } else { 01343 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01344 } 01345 ast_mutex_unlock(&sub->lock); 01346 01347 return res; 01348 }
static int mgcp_set_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp_instance * | rtp, | |||
struct ast_rtp_instance * | vrtp, | |||
struct ast_rtp_instance * | trtp, | |||
format_t | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 4413 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_modify_with_sdp().
04414 { 04415 /* XXX Is there such thing as video support with MGCP? XXX */ 04416 struct mgcp_subchannel *sub; 04417 sub = chan->tech_pvt; 04418 if (sub && !sub->alreadygone) { 04419 transmit_modify_with_sdp(sub, rtp, codecs); 04420 return 0; 04421 } 04422 return -1; 04423 }
static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2941 of file chan_mgcp.c.
References ast_party_caller::ani, ast_bridged_channel(), ast_canmatch_extension(), ast_copy_string(), ast_db_put(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext_valid(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, ast_channel::caller, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, ast_channel::dialed, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_party_caller::id, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, ast_party_dialed::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, ast_channel::rings, S_COR, start_rtp(), ast_party_number::str, ast_party_dialed::str, mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_notify_request(), and ast_party_number::valid.
Referenced by handle_hd_hf().
02942 { 02943 struct ast_channel *chan = data; 02944 struct mgcp_subchannel *sub = chan->tech_pvt; 02945 struct mgcp_endpoint *p = sub->parent; 02946 /* char exten[AST_MAX_EXTENSION] = ""; */ 02947 int len = 0; 02948 int timeout = firstdigittimeout; 02949 int res= 0; 02950 int getforward = 0; 02951 int loop_pause = 100; 02952 02953 len = strlen(p->dtmf_buf); 02954 02955 while (len < AST_MAX_EXTENSION - 1) { 02956 ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name); 02957 res = 1; /* Assume that we will get a digit */ 02958 while (strlen(p->dtmf_buf) == len) { 02959 ast_safe_sleep(chan, loop_pause); 02960 timeout -= loop_pause; 02961 if (timeout <= 0){ 02962 res = 0; 02963 break; 02964 } 02965 res = 1; 02966 } 02967 02968 timeout = 0; 02969 len = strlen(p->dtmf_buf); 02970 02971 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) { 02972 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02973 ast_indicate(chan, -1); 02974 } else { 02975 /* XXX Redundant? We should already be playing dialtone */ 02976 /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02977 transmit_notify_request(sub, "L/dl"); 02978 } 02979 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02980 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02981 if (getforward) { 02982 /* Record this as the forwarding extension */ 02983 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 02984 ast_verb(3, "Setting call forward to '%s' on channel %s\n", 02985 p->call_forward, chan->name); 02986 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02987 transmit_notify_request(sub, "L/sl"); 02988 if (res) 02989 break; 02990 usleep(500000); 02991 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02992 ast_indicate(chan, -1); 02993 sleep(1); 02994 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02995 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02996 transmit_notify_request(sub, "L/dl"); 02997 len = 0; 02998 getforward = 0; 02999 } else { 03000 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03001 ast_indicate(chan, -1); 03002 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten)); 03003 chan->dialed.number.str = ast_strdup(p->dtmf_buf); 03004 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03005 ast_set_callerid(chan, 03006 p->hidecallerid ? "" : p->cid_num, 03007 p->hidecallerid ? "" : p->cid_name, 03008 chan->caller.ani.number.valid ? NULL : p->cid_num); 03009 ast_setstate(chan, AST_STATE_RING); 03010 /*dahdi_enable_ec(p);*/ 03011 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 03012 p->dtmfmode |= MGCP_DTMF_INBAND; 03013 ast_indicate(chan, -1); 03014 } 03015 res = ast_pbx_run(chan); 03016 if (res) { 03017 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 03018 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03019 /*transmit_notify_request(p, "nbz", 1);*/ 03020 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03021 } 03022 return NULL; 03023 } 03024 } else { 03025 /* It's a match, but they just typed a digit, and there is an ambiguous match, 03026 so just set the timeout to matchdigittimeout and wait some more */ 03027 timeout = matchdigittimeout; 03028 } 03029 } else if (res == 0) { 03030 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 03031 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03032 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03033 /*dahdi_wait_event(p->subs[index].zfd);*/ 03034 ast_hangup(chan); 03035 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03036 return NULL; 03037 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { 03038 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 03039 /* Disable call waiting if enabled */ 03040 p->callwaiting = 0; 03041 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03042 transmit_notify_request(sub, "L/sl"); 03043 len = 0; 03044 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03045 timeout = firstdigittimeout; 03046 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { 03047 /* Scan all channels and see if any there 03048 * ringing channqels with that have call groups 03049 * that equal this channels pickup group 03050 */ 03051 if (ast_pickup_call(chan)) { 03052 ast_log(LOG_WARNING, "No call pickup possible...\n"); 03053 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03054 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03055 } 03056 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03057 ast_hangup(chan); 03058 return NULL; 03059 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { 03060 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 03061 /* Disable Caller*ID if enabled */ 03062 p->hidecallerid = 1; 03063 ast_set_callerid(chan, "", "", NULL); 03064 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03065 transmit_notify_request(sub, "L/sl"); 03066 len = 0; 03067 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03068 timeout = firstdigittimeout; 03069 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { 03070 res = 0; 03071 if (!ast_strlen_zero(p->lastcallerid)) { 03072 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language); 03073 } 03074 if (!res) 03075 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03076 transmit_notify_request(sub, "L/sl"); 03077 break; 03078 } else if (!strcmp(p->dtmf_buf, "*78")) { 03079 /* Do not disturb */ 03080 ast_verb(3, "Enabled DND on channel %s\n", chan->name); 03081 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03082 transmit_notify_request(sub, "L/sl"); 03083 p->dnd = 1; 03084 getforward = 0; 03085 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03086 len = 0; 03087 } else if (!strcmp(p->dtmf_buf, "*79")) { 03088 /* Do not disturb */ 03089 ast_verb(3, "Disabled DND on channel %s\n", chan->name); 03090 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03091 transmit_notify_request(sub, "L/sl"); 03092 p->dnd = 0; 03093 getforward = 0; 03094 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03095 len = 0; 03096 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { 03097 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03098 transmit_notify_request(sub, "L/sl"); 03099 getforward = 1; 03100 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03101 len = 0; 03102 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { 03103 ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name); 03104 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03105 transmit_notify_request(sub, "L/sl"); 03106 memset(p->call_forward, 0, sizeof(p->call_forward)); 03107 getforward = 0; 03108 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03109 len = 0; 03110 } else if (ast_parking_ext_valid(p->dtmf_buf, chan, chan->context) && 03111 sub->next->owner && ast_bridged_channel(sub->next->owner)) { 03112 /* This is a three way call, the main call being a real channel, 03113 and we're parking the first call. */ 03114 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL); 03115 ast_verb(3, "Parking call to '%s'\n", chan->name); 03116 break; 03117 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { 03118 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); 03119 res = ast_db_put("blacklist", p->lastcallerid, "1"); 03120 if (!res) { 03121 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03122 transmit_notify_request(sub, "L/sl"); 03123 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03124 len = 0; 03125 } 03126 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { 03127 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 03128 /* Enable Caller*ID if enabled */ 03129 p->hidecallerid = 0; 03130 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 03131 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03132 transmit_notify_request(sub, "L/sl"); 03133 len = 0; 03134 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03135 timeout = firstdigittimeout; 03136 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, 03137 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 03138 && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 03139 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, 03140 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 03141 chan->context); 03142 break; 03143 } 03144 if (!timeout) 03145 timeout = gendigittimeout; 03146 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf)) 03147 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03148 ast_indicate(chan, -1); 03149 } 03150 #if 0 03151 for (;;) { 03152 res = ast_waitfordigit(chan, to); 03153 if (!res) { 03154 ast_debug(1, "Timeout...\n"); 03155 break; 03156 } 03157 if (res < 0) { 03158 ast_debug(1, "Got hangup...\n"); 03159 ast_hangup(chan); 03160 break; 03161 } 03162 exten[pos++] = res; 03163 if (!ast_ignore_pattern(chan->context, exten)) 03164 ast_indicate(chan, -1); 03165 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { 03166 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 03167 to = 3000; 03168 else 03169 to = 8000; 03170 } else 03171 break; 03172 } 03173 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { 03174 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); 03175 if (!p->rtp) { 03176 start_rtp(p); 03177 } 03178 ast_setstate(chan, AST_STATE_RING); 03179 chan->rings = 1; 03180 if (ast_pbx_run(chan)) { 03181 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); 03182 } else { 03183 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03184 return NULL; 03185 } 03186 } 03187 #endif 03188 ast_hangup(chan); 03189 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03190 return NULL; 03191 }
static int mgcp_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 1240 of file chan_mgcp.c.
References ast_debug, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::codec, ast_frame::frametype, mgcp_subchannel::gate, GATE_ALLOCATED, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, cops_gate::state, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, transmit_modify_with_sdp(), and ast_channel::writeformat.
01241 { 01242 struct mgcp_subchannel *sub = ast->tech_pvt; 01243 int res = 0; 01244 char buf[256]; 01245 01246 if (frame->frametype != AST_FRAME_VOICE) { 01247 if (frame->frametype == AST_FRAME_IMAGE) 01248 return 0; 01249 else { 01250 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); 01251 return 0; 01252 } 01253 } else { 01254 if (!(frame->subclass.codec & ast->nativeformats)) { 01255 ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01256 ast_getformatname(frame->subclass.codec), 01257 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), 01258 ast_getformatname(ast->readformat), 01259 ast_getformatname(ast->writeformat)); 01260 /* return -1; */ 01261 } 01262 } 01263 if (sub) { 01264 ast_mutex_lock(&sub->lock); 01265 if (!sub->sdpsent && sub->gate) { 01266 if (sub->gate->state == GATE_ALLOCATED) { 01267 ast_debug(1, "GATE ALLOCATED, sending sdp\n"); 01268 transmit_modify_with_sdp(sub, NULL, 0); 01269 } 01270 } 01271 if ((sub->parent->sub == sub) || !sub->parent->singlepath) { 01272 if (sub->rtp) { 01273 res = ast_rtp_instance_write(sub->rtp, frame); 01274 } 01275 } 01276 ast_mutex_unlock(&sub->lock); 01277 } 01278 return res; 01279 }
static int mgcpsock_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | ignore | |||
) | [static] |
Definition at line 3604 of file chan_mgcp.c.
References ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_SCHED_DEL, ast_strlen_zero(), errno, find_and_retrans(), find_subchannel_and_lock(), handle_request(), handle_response(), len(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcpsock, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_subchannel::parent, parse(), mgcp_gateway::retransid, and mgcp_message::seqno.
Referenced by do_monitor().
03605 { 03606 struct mgcp_request req; 03607 struct sockaddr_in sin; 03608 struct mgcp_subchannel *sub; 03609 int res; 03610 socklen_t len; 03611 int result; 03612 int ident; 03613 len = sizeof(sin); 03614 memset(&req, 0, sizeof(req)); 03615 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 03616 if (res < 0) { 03617 if (errno != ECONNREFUSED) 03618 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 03619 return 1; 03620 } 03621 req.data[res] = '\0'; 03622 req.len = res; 03623 ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 03624 parse(&req); 03625 if (req.headers < 1) { 03626 /* Must have at least one header */ 03627 return 1; 03628 } 03629 if (ast_strlen_zero(req.identifier)) { 03630 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); 03631 return 1; 03632 } 03633 03634 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { 03635 if (result < 200) { 03636 ast_debug(1, "Ignoring provisional response on transaction %d\n", ident); 03637 return 1; 03638 } 03639 /* Try to find who this message is for, if it's important */ 03640 sub = find_subchannel_and_lock(NULL, ident, &sin); 03641 if (sub) { 03642 struct mgcp_gateway *gw = sub->parent->parent; 03643 struct mgcp_message *cur, *prev; 03644 03645 ast_mutex_unlock(&sub->lock); 03646 ast_mutex_lock(&gw->msgs_lock); 03647 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 03648 if (cur->seqno == ident) { 03649 ast_debug(1, "Got response back on transaction %d\n", ident); 03650 if (prev) 03651 prev->next = cur->next; 03652 else 03653 gw->msgs = cur->next; 03654 break; 03655 } 03656 } 03657 03658 /* stop retrans timer if the queue is empty */ 03659 if (!gw->msgs) { 03660 AST_SCHED_DEL(sched, gw->retransid); 03661 } 03662 03663 ast_mutex_unlock(&gw->msgs_lock); 03664 if (cur) { 03665 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); 03666 ast_free(cur); 03667 return 1; 03668 } 03669 03670 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 03671 gw->name, ident); 03672 } 03673 } else { 03674 if (ast_strlen_zero(req.endpoint) || 03675 ast_strlen_zero(req.version) || 03676 ast_strlen_zero(req.verb)) { 03677 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); 03678 return 1; 03679 } 03680 /* Process request, with iflock held */ 03681 sub = find_subchannel_and_lock(req.endpoint, 0, &sin); 03682 if (sub) { 03683 /* look first to find a matching response in the queue */ 03684 if (!find_and_retrans(sub, &req)) 03685 /* pass the request off to the currently mastering subchannel */ 03686 handle_request(sub, &req, &sin); 03687 ast_mutex_unlock(&sub->lock); 03688 } 03689 } 03690 return 1; 03691 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 481 of file chan_mgcp.c.
00482 { 00483 /* This module does not handle MWI in an event-based manner. However, it 00484 * subscribes to MWI for each mailbox that is configured so that the core 00485 * knows that we care about it. Then, chan_mgcp will get the MWI from the 00486 * event cache instead of checking the mailbox directly. */ 00487 }
static void parse | ( | struct mgcp_request * | req | ) | [static] |
Definition at line 1851 of file chan_mgcp.c.
References ast_debug, ast_log(), ast_strlen_zero(), mgcp_request::data, mgcp_request::endpoint, f, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::line, mgcp_request::lines, LOG_WARNING, MGCP_MAX_HEADERS, MGCP_MAX_LINES, mgcp_request::verb, and mgcp_request::version.
Referenced by acf_jabberreceive_read(), acf_meetme_info(), add_agent(), app_exec(), aqm_exec(), ast_parse_allow_disallow(), astman_get_variables(), celgenuserevent_exec(), chanspy_exec(), conf_exec(), conf_run(), confbridge_exec(), config_function_read(), cut_internal(), dahdi_accept_r2_call_exec(), dahdi_send_callrerouting_facility_exec(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), extenspy_exec(), find_conf(), function_agent(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), mgcpsock_read(), mixmonitor_exec(), originate_exec(), oss_call(), oss_request(), page_exec(), park_call_exec(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_waitexten(), pickupchan_exec(), play_moh_exec(), pqm_exec(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), rcvfax_exec(), receivefax_exec(), record_exec(), reload_single_member(), retrydial_exec(), rqm_exec(), saycountedadj_exec(), saycountednoun_exec(), sayunixtime_exec(), sendfax_exec(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), srv_result_read(), start_moh_exec(), start_monitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), and zapateller_exec().
01852 { 01853 /* Divide fields by NULL's */ 01854 char *c; 01855 int f = 0; 01856 c = req->data; 01857 01858 /* First header starts immediately */ 01859 req->header[f] = c; 01860 for (; *c; c++) { 01861 if (*c == '\n') { 01862 /* We've got a new header */ 01863 *c = 0; 01864 ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f])); 01865 if (ast_strlen_zero(req->header[f])) { 01866 /* Line by itself means we're now in content */ 01867 c++; 01868 break; 01869 } 01870 if (f >= MGCP_MAX_HEADERS - 1) { 01871 ast_log(LOG_WARNING, "Too many MGCP headers...\n"); 01872 } else { 01873 f++; 01874 } 01875 req->header[f] = c + 1; 01876 } else if (*c == '\r') { 01877 /* Ignore but eliminate \r's */ 01878 *c = 0; 01879 } 01880 } 01881 /* Check for last header */ 01882 if (!ast_strlen_zero(req->header[f])) { 01883 f++; 01884 } 01885 req->headers = f; 01886 /* Now we process any mime content */ 01887 f = 0; 01888 req->line[f] = c; 01889 for (; *c; c++) { 01890 if (*c == '\n') { 01891 /* We've got a new line */ 01892 *c = 0; 01893 ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f])); 01894 if (f >= MGCP_MAX_LINES - 1) { 01895 ast_log(LOG_WARNING, "Too many SDP lines...\n"); 01896 } else { 01897 f++; 01898 } 01899 req->line[f] = c + 1; 01900 } else if (*c == '\r') { 01901 /* Ignore and eliminate \r's */ 01902 *c = 0; 01903 } 01904 } 01905 /* Check for last line */ 01906 if (!ast_strlen_zero(req->line[f])) { 01907 f++; 01908 } 01909 req->lines = f; 01910 /* Parse up the initial header */ 01911 c = req->header[0]; 01912 while (*c && *c < 33) c++; 01913 /* First the verb */ 01914 req->verb = c; 01915 while (*c && (*c > 32)) c++; 01916 if (*c) { 01917 *c = '\0'; 01918 c++; 01919 while (*c && (*c < 33)) c++; 01920 req->identifier = c; 01921 while (*c && (*c > 32)) c++; 01922 if (*c) { 01923 *c = '\0'; 01924 c++; 01925 while (*c && (*c < 33)) c++; 01926 req->endpoint = c; 01927 while (*c && (*c > 32)) c++; 01928 if (*c) { 01929 *c = '\0'; 01930 c++; 01931 while (*c && (*c < 33)) c++; 01932 req->version = c; 01933 while (*c && (*c > 32)) c++; 01934 while (*c && (*c < 33)) c++; 01935 while (*c && (*c > 32)) c++; 01936 *c = '\0'; 01937 } 01938 } 01939 } 01940 01941 ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", 01942 req->verb, req->identifier, req->endpoint, req->version); 01943 ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines); 01944 if (*c) { 01945 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); 01946 } 01947 }
static int process_sdp | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req | |||
) | [static] |
Definition at line 1949 of file chan_mgcp.c.
References ahp, ast_debug, ast_getformatname_multiple(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_formats(), ast_rtp_codecs_payloads_clear(), ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_sockaddr_from_sin, ast_strdupa, ast_strlen_zero(), capability, mgcp_endpoint::capability, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, nonCodecCapability, mgcp_subchannel::parent, mgcp_subchannel::rtp, sdpLineNum_iterator_init(), and mgcp_endpoint::sub.
Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().
01950 { 01951 char *m; 01952 char *c; 01953 char *a; 01954 char host[258]; 01955 int len; 01956 int portno; 01957 format_t peercapability; 01958 int peerNonCodecCapability; 01959 struct sockaddr_in sin; 01960 struct ast_sockaddr sin_tmp; 01961 char *codecs; 01962 struct ast_hostent ahp; struct hostent *hp; 01963 int codec, codec_count=0; 01964 int iterator; 01965 struct mgcp_endpoint *p = sub->parent; 01966 char tmp1[256], tmp2[256], tmp3[256]; 01967 01968 /* Get codec and RTP info from SDP */ 01969 m = get_sdp(req, "m"); 01970 c = get_sdp(req, "c"); 01971 if (ast_strlen_zero(m) || ast_strlen_zero(c)) { 01972 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); 01973 return -1; 01974 } 01975 if (sscanf(c, "IN IP4 %256s", host) != 1) { 01976 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 01977 return -1; 01978 } 01979 /* XXX This could block for a long time, and block the main thread! XXX */ 01980 hp = ast_gethostbyname(host, &ahp); 01981 if (!hp) { 01982 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); 01983 return -1; 01984 } 01985 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) { 01986 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 01987 return -1; 01988 } 01989 sin.sin_family = AF_INET; 01990 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01991 sin.sin_port = htons(portno); 01992 ast_sockaddr_from_sin(&sin_tmp, &sin); 01993 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp); 01994 ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 01995 /* Scan through the RTP payload types specified in a "m=" line: */ 01996 ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp); 01997 codecs = ast_strdupa(m + len); 01998 while (!ast_strlen_zero(codecs)) { 01999 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) { 02000 if (codec_count) { 02001 break; 02002 } 02003 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs); 02004 return -1; 02005 } 02006 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec); 02007 codec_count++; 02008 codecs += len; 02009 } 02010 02011 /* Next, scan through each "a=rtpmap:" line, noting each */ 02012 /* specified RTP payload type (with corresponding MIME subtype): */ 02013 sdpLineNum_iterator_init(&iterator); 02014 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 02015 char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */ 02016 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2) 02017 continue; 02018 /* Note: should really look at the 'freq' and '#chans' params too */ 02019 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0); 02020 } 02021 02022 /* Now gather all of the codecs that were asked for: */ 02023 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability); 02024 p->capability = capability & peercapability; 02025 ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n", 02026 ast_getformatname_multiple(tmp1, sizeof(tmp1), capability), 02027 ast_getformatname_multiple(tmp2, sizeof(tmp2), peercapability), 02028 ast_getformatname_multiple(tmp3, sizeof(tmp3), p->capability)); 02029 ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n", 02030 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); 02031 if (!p->capability) { 02032 ast_log(LOG_WARNING, "No compatible codecs!\n"); 02033 return -1; 02034 } 02035 return 0; 02036 }
static void prune_gateways | ( | void | ) | [static] |
Definition at line 4527 of file chan_mgcp.c.
References ast_mutex_lock, mgcp_gateway::delme, mgcp_endpoint::delme, destroy_endpoint(), mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::next, and mgcp_gateway::realtime.
Referenced by unload_module().
04528 { 04529 struct mgcp_gateway *g, *z, *r; 04530 struct mgcp_endpoint *e, *p, *t; 04531 04532 ast_mutex_lock(&gatelock); 04533 04534 /* prune gateways */ 04535 for (z = NULL, g = gateways; g;) { 04536 /* prune endpoints */ 04537 for (p = NULL, e = g->endpoints; e; ) { 04538 if (!g->realtime && (e->delme || g->delme)) { 04539 t = e; 04540 e = e->next; 04541 if (!p) 04542 g->endpoints = e; 04543 else 04544 p->next = e; 04545 destroy_endpoint(t); 04546 } else { 04547 p = e; 04548 e = e->next; 04549 } 04550 } 04551 04552 if (g->delme) { 04553 r = g; 04554 g = g->next; 04555 if (!z) 04556 gateways = g; 04557 else 04558 z->next = g; 04559 04560 destroy_gateway(r); 04561 } else { 04562 z = g; 04563 g = g->next; 04564 } 04565 } 04566 04567 ast_mutex_unlock(&gatelock); 04568 }
static int reload | ( | void | ) | [static] |
Definition at line 4843 of file chan_mgcp.c.
References mgcp_reload().
04844 { 04845 mgcp_reload(NULL, 0, NULL); 04846 return 0; 04847 }
static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4602 of file chan_mgcp.c.
References ahp, ast_config_load, ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_variable_browse(), bindaddr, config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, default_jbconf, dtmfmode, format, global_jbconf, hp, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, ourhost, and ast_variable::value.
04603 { 04604 struct ast_config *cfg; 04605 struct ast_variable *v; 04606 struct mgcp_gateway *g; 04607 struct mgcp_endpoint *e; 04608 char *cat; 04609 struct ast_hostent ahp; 04610 struct hostent *hp; 04611 int format; 04612 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04613 04614 if (gethostname(ourhost, sizeof(ourhost)-1)) { 04615 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); 04616 return 0; 04617 } 04618 cfg = ast_config_load(config, config_flags); 04619 04620 /* We *must* have a config file otherwise stop immediately */ 04621 if (!cfg) { 04622 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); 04623 return 0; 04624 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 04625 return 0; 04626 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04627 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 04628 return 0; 04629 } 04630 04631 memset(&bindaddr, 0, sizeof(bindaddr)); 04632 dtmfmode = 0; 04633 04634 /* Copy the default jb config over global_jbconf */ 04635 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 04636 04637 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 04638 /* handle jb conf */ 04639 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { 04640 continue; 04641 } 04642 04643 /* Create the interface list */ 04644 if (!strcasecmp(v->name, "bindaddr")) { 04645 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 04646 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 04647 } else { 04648 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 04649 } 04650 } else if (!strcasecmp(v->name, "allow")) { 04651 format = ast_getformatbyname(v->value); 04652 if (format < 1) { 04653 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04654 } else { 04655 capability |= format; 04656 } 04657 } else if (!strcasecmp(v->name, "disallow")) { 04658 format = ast_getformatbyname(v->value); 04659 if (format < 1) { 04660 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value); 04661 } else { 04662 capability &= ~format; 04663 } 04664 } else if (!strcasecmp(v->name, "tos")) { 04665 if (ast_str2tos(v->value, &qos.tos)) { 04666 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04667 } 04668 } else if (!strcasecmp(v->name, "tos_audio")) { 04669 if (ast_str2tos(v->value, &qos.tos_audio)) 04670 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04671 } else if (!strcasecmp(v->name, "cos")) { 04672 if (ast_str2cos(v->value, &qos.cos)) 04673 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 04674 } else if (!strcasecmp(v->name, "cos_audio")) { 04675 if (ast_str2cos(v->value, &qos.cos_audio)) 04676 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04677 } else if (!strcasecmp(v->name, "port")) { 04678 if (sscanf(v->value, "%5d", &ourport) == 1) { 04679 bindaddr.sin_port = htons(ourport); 04680 } else { 04681 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 04682 } 04683 } else if (!strcasecmp(v->name, "firstdigittimeout")) { 04684 firstdigittimeout = atoi(v->value); 04685 } else if (!strcasecmp(v->name, "gendigittimeout")) { 04686 gendigittimeout = atoi(v->value); 04687 } else if (!strcasecmp(v->name, "matchdigittimeout")) { 04688 matchdigittimeout = atoi(v->value); 04689 } 04690 } 04691 04692 /* mark existing entries for deletion */ 04693 ast_mutex_lock(&gatelock); 04694 for (g = gateways; g; g = g->next) { 04695 g->delme = 1; 04696 for (e = g->endpoints; e; e = e->next) { 04697 e->delme = 1; 04698 } 04699 } 04700 ast_mutex_unlock(&gatelock); 04701 04702 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) { 04703 if (strcasecmp(cat, "general")) { 04704 ast_mutex_lock(&gatelock); 04705 if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) { 04706 ast_verb(3, "Added gateway '%s'\n", g->name); 04707 g->next = gateways; 04708 gateways = g; 04709 } 04710 ast_mutex_unlock(&gatelock); 04711 04712 /* FS: process queue and IO */ 04713 if (monitor_thread == pthread_self()) { 04714 if (sched) ast_sched_runq(sched); 04715 if (io) ast_io_wait(io, 10); 04716 } 04717 } 04718 } 04719 04720 /* prune deleted entries etc. */ 04721 prune_gateways(); 04722 04723 if (ntohl(bindaddr.sin_addr.s_addr)) { 04724 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); 04725 } else { 04726 hp = ast_gethostbyname(ourhost, &ahp); 04727 if (!hp) { 04728 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); 04729 ast_config_destroy(cfg); 04730 return 0; 04731 } 04732 memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); 04733 } 04734 if (!ntohs(bindaddr.sin_port)) 04735 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT); 04736 bindaddr.sin_family = AF_INET; 04737 ast_mutex_lock(&netlock); 04738 if (mgcpsock > -1) 04739 close(mgcpsock); 04740 04741 if (mgcpsock_read_id != NULL) 04742 ast_io_remove(io, mgcpsock_read_id); 04743 mgcpsock_read_id = NULL; 04744 04745 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); 04746 if (mgcpsock < 0) { 04747 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); 04748 } else { 04749 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 04750 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 04751 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 04752 strerror(errno)); 04753 close(mgcpsock); 04754 mgcpsock = -1; 04755 } else { 04756 ast_verb(2, "MGCP Listening on %s:%d\n", 04757 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 04758 ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); 04759 } 04760 } 04761 ast_mutex_unlock(&netlock); 04762 ast_config_destroy(cfg); 04763 04764 /* send audit only to the new endpoints */ 04765 for (g = gateways; g; g = g->next) { 04766 for (e = g->endpoints; e && e->needaudit; e = e->next) { 04767 e->needaudit = 0; 04768 transmit_audit_endpoint(e); 04769 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); 04770 } 04771 } 04772 04773 return 0; 04774 }
static int reqprep | ( | struct mgcp_request * | req, | |
struct mgcp_endpoint * | p, | |||
char * | verb | |||
) | [static] |
Definition at line 2132 of file chan_mgcp.c.
References init_req(), and oseq.
Referenced by transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_state_notify(), and update_connectedline().
02133 { 02134 memset(req, 0, sizeof(struct mgcp_request)); 02135 oseq++; 02136 if (oseq > 999999999) { 02137 oseq = 1; 02138 } 02139 init_req(p, req, verb); 02140 return 0; 02141 }
static int resend_response | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_response * | resp | |||
) | [static] |
Definition at line 555 of file chan_mgcp.c.
References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), mgcp_response::buf, mgcp_response::len, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by find_and_retrans().
00556 { 00557 struct mgcp_endpoint *p = sub->parent; 00558 int res; 00559 ast_debug(1, "Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00560 res = __mgcp_xmit(p->parent, resp->buf, resp->len); 00561 if (res > 0) 00562 res = 0; 00563 return res; 00564 }
static int respprep | ( | struct mgcp_request * | resp, | |
struct mgcp_endpoint * | p, | |||
char * | msg, | |||
struct mgcp_request * | req, | |||
char * | msgrest | |||
) | [static] |
Definition at line 2125 of file chan_mgcp.c.
References init_resp().
Referenced by __transmit_response(), transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sdp(), transmit_response_with_sip_etag(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), update_connectedline(), and update_redirecting().
02126 { 02127 memset(resp, 0, sizeof(*resp)); 02128 init_resp(resp, msg, req, msgrest); 02129 return 0; 02130 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 3873 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, and monlock.
03874 { 03875 /* If we're supposed to be stopped -- stay stopped */ 03876 if (monitor_thread == AST_PTHREADT_STOP) 03877 return 0; 03878 if (ast_mutex_lock(&monlock)) { 03879 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 03880 return -1; 03881 } 03882 if (monitor_thread == pthread_self()) { 03883 ast_mutex_unlock(&monlock); 03884 ast_log(LOG_WARNING, "Cannot kill myself\n"); 03885 return -1; 03886 } 03887 if (monitor_thread != AST_PTHREADT_NULL) { 03888 /* Wake up the thread */ 03889 pthread_kill(monitor_thread, SIGURG); 03890 } else { 03891 /* Start a new monitor */ 03892 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 03893 ast_mutex_unlock(&monlock); 03894 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 03895 return -1; 03896 } 03897 } 03898 ast_mutex_unlock(&monlock); 03899 return 0; 03900 }
static int retrans_pkt | ( | const void * | data | ) | [static] |
Definition at line 652 of file chan_mgcp.c.
References __mgcp_xmit(), ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_message::buf, handle_response(), mgcp_message::len, LOG_WARNING, MAX_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_message::retrans, mgcp_gateway::retransid, and mgcp_message::seqno.
Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and sip_show_sched().
00653 { 00654 struct mgcp_gateway *gw = (struct mgcp_gateway *)data; 00655 struct mgcp_message *cur, *exq = NULL, *w, *prev; 00656 int res = 0; 00657 00658 /* find out expired msgs */ 00659 ast_mutex_lock(&gw->msgs_lock); 00660 00661 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00662 if (cur->retrans < MAX_RETRANS) { 00663 cur->retrans++; 00664 ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n", 00665 cur->retrans, cur->seqno, gw->name); 00666 __mgcp_xmit(gw, cur->buf, cur->len); 00667 } else { 00668 if (prev) 00669 prev->next = cur->next; 00670 else 00671 gw->msgs = cur->next; 00672 00673 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", 00674 cur->seqno, gw->name); 00675 00676 w = cur; 00677 00678 if (exq) { 00679 w->next = exq; 00680 } else { 00681 w->next = NULL; 00682 } 00683 exq = w; 00684 } 00685 } 00686 00687 if (!gw->msgs) { 00688 gw->retransid = -1; 00689 res = 0; 00690 } else { 00691 res = 1; 00692 } 00693 ast_mutex_unlock(&gw->msgs_lock); 00694 00695 while (exq) { 00696 cur = exq; 00697 /* time-out transaction */ 00698 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 00699 exq = exq->next; 00700 ast_free(cur); 00701 } 00702 00703 return res; 00704 }
static void sdpLineNum_iterator_init | ( | int * | iterator | ) | [static] |
static int send_request | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub, | |||
struct mgcp_request * | req, | |||
unsigned int | seqno | |||
) | [static] |
Definition at line 751 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_malloc, ast_mutex_lock, ast_mutex_unlock, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::data, mgcp_request::len, LOG_WARNING, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcp_endpoint::ncs, mgcp_request::next, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.
Referenced by transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_state_notify(), and update_connectedline().
00753 { 00754 int res = 0; 00755 struct mgcp_request **queue, *q, *r, *t; 00756 ast_mutex_t *l; 00757 00758 ast_debug(1, "Slow sequence is %d\n", p->slowsequence); 00759 if (p->slowsequence) { 00760 queue = &p->cmd_queue; 00761 l = &p->cmd_queue_lock; 00762 ast_mutex_lock(l); 00763 } else { 00764 switch (req->cmd) { 00765 case MGCP_CMD_DLCX: 00766 queue = &sub->cx_queue; 00767 l = &sub->cx_queue_lock; 00768 ast_mutex_lock(l); 00769 q = sub->cx_queue; 00770 /* delete pending cx cmds */ 00771 /* buggy sb5120 */ 00772 if (!sub->parent->ncs) { 00773 while (q) { 00774 r = q->next; 00775 ast_free(q); 00776 q = r; 00777 } 00778 *queue = NULL; 00779 } 00780 break; 00781 00782 case MGCP_CMD_CRCX: 00783 case MGCP_CMD_MDCX: 00784 queue = &sub->cx_queue; 00785 l = &sub->cx_queue_lock; 00786 ast_mutex_lock(l); 00787 break; 00788 00789 case MGCP_CMD_RQNT: 00790 queue = &p->rqnt_queue; 00791 l = &p->rqnt_queue_lock; 00792 ast_mutex_lock(l); 00793 break; 00794 00795 default: 00796 queue = &p->cmd_queue; 00797 l = &p->cmd_queue_lock; 00798 ast_mutex_lock(l); 00799 break; 00800 } 00801 } 00802 00803 if (!(r = ast_malloc(sizeof(*r)))) { 00804 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n"); 00805 ast_mutex_unlock(l); 00806 return -1; 00807 } 00808 memcpy(r, req, sizeof(*r)); 00809 00810 if (!(*queue)) { 00811 ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data, 00812 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00813 00814 res = mgcp_postrequest(p, sub, req->data, req->len, seqno); 00815 } else { 00816 ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data, 00817 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00818 } 00819 00820 /* XXX find tail. We could also keep tail in the data struct for faster access */ 00821 for (t = *queue; t && t->next; t = t->next); 00822 00823 r->next = NULL; 00824 if (t) 00825 t->next = r; 00826 else 00827 *queue = r; 00828 00829 ast_mutex_unlock(l); 00830 00831 return res; 00832 }
static int send_response | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req | |||
) | [static] |
Definition at line 566 of file chan_mgcp.c.
References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), mgcp_request::data, mgcp_request::len, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by __transmit_response(), transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sdp(), transmit_response_with_sip_etag(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), update_connectedline(), and update_redirecting().
00567 { 00568 struct mgcp_endpoint *p = sub->parent; 00569 int res; 00570 ast_debug(1, "Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00571 res = __mgcp_xmit(p->parent, req->data, req->len); 00572 if (res > 0) 00573 res = 0; 00574 return res; 00575 }
static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2908 of file chan_mgcp.c.
References ast_channel_set_fd(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_destroy(), ast_rtp_instance_fd(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, ast_sockaddr_from_sin, bindaddr, mgcp_subchannel::callid, mgcp_subchannel::gate, mgcp_subchannel::lock, mgcp_alloc_pktcgate(), mgcp_queue_hangup(), mgcp_subchannel::nat, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, qos, mgcp_subchannel::rtp, transmit_connect(), transmit_connect_with_sdp(), and mgcp_subchannel::txident.
Referenced by handle_hd_hf(), handle_offhook_message(), handle_response(), handle_soft_key_event_message(), handle_stimulus_message(), HandleCallIncoming(), HandleCallOutgoing(), mgcp_answer(), mgcp_call(), mgcp_ss(), skinny_answer(), skinny_newcall(), and unistim_answer().
02909 { 02910 struct ast_sockaddr bindaddr_tmp; 02911 02912 ast_mutex_lock(&sub->lock); 02913 /* check again to be on the safe side */ 02914 if (sub->rtp) { 02915 ast_rtp_instance_destroy(sub->rtp); 02916 sub->rtp = NULL; 02917 } 02918 /* Allocate the RTP now */ 02919 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 02920 sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); 02921 if (sub->rtp && sub->owner) 02922 ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0)); 02923 if (sub->rtp) { 02924 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); 02925 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat); 02926 } 02927 /* Make a call*ID */ 02928 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); 02929 /* Transmit the connection create */ 02930 if(!sub->parent->pktcgatealloc) { 02931 transmit_connect_with_sdp(sub, NULL); 02932 } else { 02933 transmit_connect(sub); 02934 sub->gate = NULL; 02935 if(!mgcp_alloc_pktcgate(sub)) 02936 mgcp_queue_hangup(sub); 02937 } 02938 ast_mutex_unlock(&sub->lock); 02939 }
static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2620 of file chan_mgcp.c.
References add_header(), mgcp_request::cmd, MGCP_CMD_AUEP, oseq, reqprep(), send_request(), and mgcp_request::trid.
Referenced by handle_mgcp_audit_endpoint(), and handle_request().
02621 { 02622 struct mgcp_request resp; 02623 reqprep(&resp, p, "AUEP"); 02624 /* removed unknown param VS */ 02625 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ 02626 add_header(&resp, "F", "A"); 02627 /* fill in new fields */ 02628 resp.cmd = MGCP_CMD_AUEP; 02629 resp.trid = oseq; 02630 return send_request(p, NULL, &resp, oseq); 02631 }
static int transmit_connect | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2417 of file chan_mgcp.c.
References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), mgcp_endpoint::capability, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by skinny_unhold(), and start_rtp().
02418 { 02419 struct mgcp_request resp; 02420 char local[256]; 02421 char tmp[80]; 02422 format_t x; 02423 struct mgcp_endpoint *p = sub->parent; 02424 02425 ast_copy_string(local, "p:20, s:off, e:on", sizeof(local)); 02426 02427 for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02428 if (p->capability & x) { 02429 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02430 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02431 } 02432 } 02433 02434 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02435 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02436 sub->sdpsent = 0; 02437 reqprep(&resp, p, "CRCX"); 02438 add_header(&resp, "C", sub->callid); 02439 add_header(&resp, "L", local); 02440 add_header(&resp, "M", "inactive"); 02441 /* X header should not be sent. kept for compatibility */ 02442 add_header(&resp, "X", sub->txident); 02443 /*add_header(&resp, "S", "");*/ 02444 /* fill in new fields */ 02445 resp.cmd = MGCP_CMD_CRCX; 02446 resp.trid = oseq; 02447 return send_request(p, sub, &resp, oseq); 02448 }
static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, | |
struct ast_rtp_instance * | rtp | |||
) | [static] |
Definition at line 2322 of file chan_mgcp.c.
References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by start_rtp().
02323 { 02324 struct mgcp_request resp; 02325 char local[256]; 02326 char tmp[80]; 02327 int x; 02328 struct mgcp_endpoint *p = sub->parent; 02329 02330 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02331 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02332 02333 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02334 02335 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02336 if (!(x & AST_FORMAT_AUDIO_MASK)) { 02337 /* No longer contiguous */ 02338 continue; 02339 } 02340 if (p->capability & x) { 02341 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02342 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02343 } 02344 } 02345 02346 if (sub->gate) { 02347 if(sub->gate->state == GATE_ALLOCATED) { 02348 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02349 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02350 } 02351 } 02352 sub->sdpsent = 1; 02353 reqprep(&resp, p, "CRCX"); 02354 add_header(&resp, "C", sub->callid); 02355 add_header(&resp, "L", local); 02356 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02357 /* X header should not be sent. kept for compatibility */ 02358 add_header(&resp, "X", sub->txident); 02359 /*add_header(&resp, "S", "");*/ 02360 add_sdp(&resp, sub, rtp); 02361 /* fill in new fields */ 02362 resp.cmd = MGCP_CMD_CRCX; 02363 resp.trid = oseq; 02364 return send_request(p, sub, &resp, oseq); 02365 }
static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2633 of file chan_mgcp.c.
References add_header(), ast_debug, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_DLCX, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_endpoint::sub, mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by destroy_endpoint(), handle_request(), handle_response(), mgcp_hangup(), and unalloc_sub().
02634 { 02635 struct mgcp_endpoint *p = sub->parent; 02636 struct mgcp_request resp; 02637 02638 ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 02639 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02640 reqprep(&resp, p, "DLCX"); 02641 /* check if call id is avail */ 02642 if (sub->callid[0]) 02643 add_header(&resp, "C", sub->callid); 02644 /* X header should not be sent. kept for compatibility */ 02645 add_header(&resp, "X", sub->txident); 02646 /* check if cxident is avail */ 02647 if (sub->cxident[0]) 02648 add_header(&resp, "I", sub->cxident); 02649 /* fill in new fields */ 02650 resp.cmd = MGCP_CMD_DLCX; 02651 resp.trid = oseq; 02652 return send_request(p, sub, &resp, oseq); 02653 }
static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, | |
char * | callid, | |||
char * | cxident | |||
) | [static] |
Definition at line 2655 of file chan_mgcp.c.
References add_header(), ast_debug, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, reqprep(), send_request(), and mgcp_endpoint::sub.
Referenced by handle_response().
02656 { 02657 struct mgcp_request resp; 02658 02659 ast_debug(3, "Delete connection %s %s@%s on callid: %s\n", 02660 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); 02661 reqprep(&resp, p, "DLCX"); 02662 /* check if call id is avail */ 02663 if (callid && *callid) 02664 add_header(&resp, "C", callid); 02665 /* check if cxident is avail */ 02666 if (cxident && *cxident) 02667 add_header(&resp, "I", cxident); 02668 /* fill in new fields */ 02669 resp.cmd = MGCP_CMD_DLCX; 02670 resp.trid = oseq; 02671 return send_request(p, p->sub, &resp, oseq); 02672 }
static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2521 of file chan_mgcp.c.
References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), mgcp_call(), mgcp_hangup(), and mgcp_indicate().
02522 { 02523 struct mgcp_request resp; 02524 struct mgcp_endpoint *p = sub->parent; 02525 format_t x; 02526 int fc = 1; 02527 char local[256]; 02528 char tmp[80]; 02529 02530 if (ast_strlen_zero(sub->cxident)) { 02531 /* We don't have a CXident yet, store the destination and 02532 wait a bit */ 02533 return 0; 02534 } 02535 ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", 02536 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02537 02538 ast_copy_string(local, "", sizeof(local)); 02539 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02540 if (p->capability & x) { 02541 if (p->ncs && !fc) { 02542 p->capability = x; /* sb5120e bug */ 02543 break; 02544 } else { 02545 fc = 0; 02546 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02547 } 02548 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02549 } 02550 } 02551 02552 if (!sub->sdpsent) { 02553 if (sub->gate) { 02554 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { 02555 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02556 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02557 } else { 02558 /* we still don't have gateid wait */ 02559 return 0; 02560 } 02561 } 02562 } 02563 02564 reqprep(&resp, p, "MDCX"); 02565 add_header(&resp, "C", sub->callid); 02566 if (!sub->sdpsent) { 02567 add_header(&resp, "L", local); 02568 } 02569 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02570 /* X header should not be sent. kept for compatibility */ 02571 add_header(&resp, "X", sub->txident); 02572 add_header(&resp, "I", sub->cxident); 02573 switch (sub->parent->hookstate) { 02574 case MGCP_ONHOOK: 02575 add_header(&resp, "R", "L/hd(N)"); 02576 break; 02577 case MGCP_OFFHOOK: 02578 add_header_offhook(sub, &resp, ""); 02579 break; 02580 } 02581 if (!sub->sdpsent) { 02582 add_sdp(&resp, sub, NULL); 02583 sub->sdpsent = 1; 02584 } 02585 /* fill in new fields */ 02586 resp.cmd = MGCP_CMD_MDCX; 02587 resp.trid = oseq; 02588 return send_request(p, sub, &resp, oseq); 02589 }
static int transmit_modify_with_sdp | ( | struct mgcp_subchannel * | sub, | |
struct ast_rtp_instance * | rtp, | |||
format_t | codecs | |||
) | [static] |
Definition at line 2265 of file chan_mgcp.c.
References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, ast_strlen_zero(), mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::parent, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.
Referenced by handle_response(), mgcp_pktcgate_open(), mgcp_set_rtp_peer(), and mgcp_write().
02266 { 02267 struct mgcp_request resp; 02268 char local[256]; 02269 char tmp[80]; 02270 struct mgcp_endpoint *p = sub->parent; 02271 format_t x; 02272 struct ast_sockaddr sub_tmpdest_tmp; 02273 02274 if (ast_strlen_zero(sub->cxident) && rtp) { 02275 /* We don't have a CXident yet, store the destination and 02276 wait a bit */ 02277 ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp); 02278 ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest); 02279 return 0; 02280 } 02281 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02282 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02283 if (!(x & AST_FORMAT_AUDIO_MASK)) { 02284 /* No longer contiguous */ 02285 continue; 02286 } 02287 if (p->capability & x) { 02288 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02289 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02290 } 02291 } 02292 02293 if (sub->gate) { 02294 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { 02295 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02296 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02297 sub->sdpsent = 1; 02298 } else { 02299 /* oops wait */ 02300 ast_debug(1, "Waiting for opened gate...\n"); 02301 sub->sdpsent = 0; 02302 return 0; 02303 } 02304 } 02305 02306 02307 reqprep(&resp, p, "MDCX"); 02308 add_header(&resp, "C", sub->callid); 02309 add_header(&resp, "L", local); 02310 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02311 /* X header should not be sent. kept for compatibility */ 02312 add_header(&resp, "X", sub->txident); 02313 add_header(&resp, "I", sub->cxident); 02314 /*add_header(&resp, "S", "");*/ 02315 add_sdp(&resp, sub, rtp); 02316 /* fill in new fields */ 02317 resp.cmd = MGCP_CMD_MDCX; 02318 resp.trid = oseq; 02319 return send_request(p, sub, &resp, oseq); 02320 }
static int transmit_notify_request | ( | struct mgcp_subchannel * | sub, | |
char * | tone | |||
) | [static] |
Definition at line 2450 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_strlen_zero(), mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), mgcp_endpoint::sub, and mgcp_request::trid.
Referenced by do_monitor(), handle_hd_hf(), handle_request(), handle_response(), mgcp_answer(), mgcp_hangup(), mgcp_indicate(), mgcp_request(), mgcp_senddigit_end(), and mgcp_ss().
02451 { 02452 struct mgcp_request resp; 02453 struct mgcp_endpoint *p = sub->parent; 02454 02455 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02456 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02457 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02458 reqprep(&resp, p, "RQNT"); 02459 add_header(&resp, "X", p->rqnt_ident); 02460 switch (p->hookstate) { 02461 case MGCP_ONHOOK: 02462 add_header(&resp, "R", "L/hd(N)"); 02463 break; 02464 case MGCP_OFFHOOK: 02465 add_header_offhook(sub, &resp, tone); 02466 break; 02467 } 02468 if (!ast_strlen_zero(tone)) { 02469 add_header(&resp, "S", tone); 02470 } 02471 /* fill in new fields */ 02472 resp.cmd = MGCP_CMD_RQNT; 02473 resp.trid = oseq; 02474 return send_request(p, NULL, &resp, oseq); 02475 }
static int transmit_notify_request_with_callerid | ( | struct mgcp_subchannel * | sub, | |
char * | tone, | |||
char * | callernum, | |||
char * | callername | |||
) | [static] |
Definition at line 2477 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_localtime(), ast_strlen_zero(), ast_tvnow(), mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::lastcallerid, MGCP_CMD_RQNT, mgcp_cxmodes, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), mgcp_endpoint::sub, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, and mgcp_request::trid.
Referenced by mgcp_call(), and mgcp_hangup().
02478 { 02479 struct mgcp_request resp; 02480 char tone2[256]; 02481 char *l, *n; 02482 struct timeval t = ast_tvnow(); 02483 struct ast_tm tm; 02484 struct mgcp_endpoint *p = sub->parent; 02485 02486 ast_localtime(&t, &tm, NULL); 02487 n = callername; 02488 l = callernum; 02489 if (!n) 02490 n = ""; 02491 if (!l) 02492 l = ""; 02493 02494 /* Keep track of last callerid for blacklist and callreturn */ 02495 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid)); 02496 02497 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 02498 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n); 02499 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02500 reqprep(&resp, p, "RQNT"); 02501 add_header(&resp, "X", p->rqnt_ident); 02502 switch (p->hookstate) { 02503 case MGCP_ONHOOK: 02504 add_header(&resp, "R", "L/hd(N)"); 02505 break; 02506 case MGCP_OFFHOOK: 02507 add_header_offhook(sub, &resp, tone); 02508 break; 02509 } 02510 if (!ast_strlen_zero(tone2)) { 02511 add_header(&resp, "S", tone2); 02512 } 02513 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02514 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02515 /* fill in new fields */ 02516 resp.cmd = MGCP_CMD_RQNT; 02517 resp.trid = oseq; 02518 return send_request(p, NULL, &resp, oseq); 02519 }
static int transmit_response | ( | struct mgcp_subchannel * | sub, | |
char * | msg, | |||
struct mgcp_request * | req, | |||
char * | msgrest | |||
) | [static] |
Definition at line 2143 of file chan_mgcp.c.
References ast_calloc, mgcp_request::data, mgcp_request::identifier, mgcp_request::len, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_gateway::responses, respprep(), send_response(), and mgcp_endpoint::sub.
Referenced by cc_esc_publish_handler(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_invite_replaces(), handle_keep_alive_message(), handle_register_message(), handle_request(), handle_request_bye(), handle_request_cancel(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_refer(), handle_request_subscribe(), handle_request_update(), handle_response(), handle_sip_publish_initial(), handle_sip_publish_modify(), handle_sip_publish_refresh(), handle_sip_publish_remove(), handle_skinny_reset(), receive_message(), register_verify(), send_provisional_keepalive_full(), sip_cc_agent_ack(), sip_cc_agent_destructor(), sip_indicate(), sip_park_thread(), sip_sendhtml(), skinny_reload(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_linestatres(), transmit_provisional_response(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speaker_mode(), transmit_speeddialstatres(), transmit_start_tone(), transmit_startmediatransmission(), transmit_stop_tone(), transmit_stopmediatransmission(), and transmit_versionres().
02144 { 02145 struct mgcp_request resp; 02146 struct mgcp_endpoint *p = sub->parent; 02147 struct mgcp_response *mgr; 02148 02149 if (!sub) { 02150 return -1; 02151 } 02152 02153 respprep(&resp, p, msg, req, msgrest); 02154 if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) { 02155 return send_response(sub, &resp); 02156 } 02157 /* Store MGCP response in case we have to retransmit */ 02158 sscanf(req->identifier, "%30d", &mgr->seqno); 02159 time(&mgr->whensent); 02160 mgr->len = resp.len; 02161 memcpy(mgr->buf, resp.data, resp.len); 02162 mgr->buf[resp.len] = '\0'; 02163 mgr->next = p->parent->responses; 02164 p->parent->responses = mgr; 02165 02166 return send_response(sub, &resp); 02167 }
static int unalloc_sub | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 514 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_instance_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_WARNING, MGCP_CX_INACTIVE, mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_subchannel::tmpdest, and transmit_connection_del().
00515 { 00516 struct mgcp_endpoint *p = sub->parent; 00517 if (p->sub == sub) { 00518 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name); 00519 return -1; 00520 } 00521 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name); 00522 00523 sub->owner = NULL; 00524 if (!ast_strlen_zero(sub->cxident)) { 00525 transmit_connection_del(sub); 00526 } 00527 sub->cxident[0] = '\0'; 00528 sub->callid[0] = '\0'; 00529 sub->cxmode = MGCP_CX_INACTIVE; 00530 sub->outgoing = 0; 00531 sub->alreadygone = 0; 00532 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 00533 if (sub->rtp) { 00534 ast_rtp_instance_destroy(sub->rtp); 00535 sub->rtp = NULL; 00536 } 00537 dump_cmd_queues(NULL, sub); 00538 return 0; 00539 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4849 of file chan_mgcp.c.
References ast_channel_register(), ast_channel_unregister(), ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, AST_PTHREADT_STOP, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, LOG_WARNING, mgcp_reload(), mgcp_reload_lock, mgcp_reloading, mgcp_tech, monitor_thread, monlock, mgcp_endpoint::next, mgcp_gateway::next, and prune_gateways().
04850 { 04851 struct mgcp_endpoint *e; 04852 struct mgcp_gateway *g; 04853 04854 /* Check to see if we're reloading */ 04855 if (ast_mutex_trylock(&mgcp_reload_lock)) { 04856 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n"); 04857 return -1; 04858 } else { 04859 mgcp_reloading = 1; 04860 ast_mutex_unlock(&mgcp_reload_lock); 04861 } 04862 04863 /* First, take us out of the channel loop */ 04864 ast_channel_unregister(&mgcp_tech); 04865 04866 /* Shut down the monitoring thread */ 04867 if (!ast_mutex_lock(&monlock)) { 04868 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { 04869 pthread_cancel(monitor_thread); 04870 pthread_kill(monitor_thread, SIGURG); 04871 pthread_join(monitor_thread, NULL); 04872 } 04873 monitor_thread = AST_PTHREADT_STOP; 04874 ast_mutex_unlock(&monlock); 04875 } else { 04876 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 04877 /* We always want to leave this in a consistent state */ 04878 ast_channel_register(&mgcp_tech); 04879 mgcp_reloading = 0; 04880 mgcp_reload(NULL, 0, NULL); 04881 return -1; 04882 } 04883 04884 if (!ast_mutex_lock(&gatelock)) { 04885 for (g = gateways; g; g = g->next) { 04886 g->delme = 1; 04887 for (e = g->endpoints; e; e = e->next) { 04888 e->delme = 1; 04889 } 04890 } 04891 04892 prune_gateways(); 04893 ast_mutex_unlock(&gatelock); 04894 } else { 04895 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n"); 04896 /* We always want to leave this in a consistent state */ 04897 ast_channel_register(&mgcp_tech); 04898 /* Allow the monitor to restart */ 04899 monitor_thread = AST_PTHREADT_NULL; 04900 mgcp_reloading = 0; 04901 mgcp_reload(NULL, 0, NULL); 04902 return -1; 04903 } 04904 04905 close(mgcpsock); 04906 ast_rtp_glue_unregister(&mgcp_rtp_glue); 04907 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04908 sched_context_destroy(sched); 04909 04910 return 0; 04911 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } [static] |
Definition at line 4919 of file chan_mgcp.c.
struct in_addr __ourip [static] |
Definition at line 229 of file chan_mgcp.c.
char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static] |
Definition at line 193 of file chan_mgcp.c.
int adsi = 0 [static] |
Definition at line 199 of file chan_mgcp.c.
int amaflags = 0 [static] |
Definition at line 197 of file chan_mgcp.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4919 of file chan_mgcp.c.
struct sockaddr_in bindaddr [static] |
Definition at line 424 of file chan_mgcp.c.
int callreturn = 0 [static] |
Definition at line 178 of file chan_mgcp.c.
int callwaiting = 0 [static] |
Definition at line 176 of file chan_mgcp.c.
int cancallforward = 0 [static] |
Definition at line 187 of file chan_mgcp.c.
format_t capability = AST_FORMAT_ULAW [static] |
Definition at line 225 of file chan_mgcp.c.
Referenced by add_sdp(), build_setup(), iax2_call(), mgcp_new(), mgcp_request(), parse_setup(), process_sdp(), set_config(), and set_local_capabilities().
char cid_name[AST_MAX_EXTENSION] = "" [static] |
Definition at line 156 of file chan_mgcp.c.
Referenced by __analog_handle_event(), __oh323_new(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), dial_exec_full(), get_pai(), get_rpid(), misdn_new(), read_config(), set_peer_defaults(), set_pvt_defaults(), sip_call(), socket_process(), and store_callerid().
char cid_num[AST_MAX_EXTENSION] = "" [static] |
Definition at line 155 of file chan_mgcp.c.
Referenced by __analog_handle_event(), __oh323_new(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), dial_exec_full(), get_pai(), get_rpid(), misdn_new(), read_config(), set_peer_defaults(), set_pvt_defaults(), socket_process(), state_notify_build_xml(), and store_callerid().
struct ast_cli_entry cli_mgcp[] [static] |
const char config[] = "mgcp.conf" [static] |
Definition at line 108 of file chan_mgcp.c.
char context[AST_MAX_EXTENSION] = "default" [static] |
Definition at line 150 of file chan_mgcp.c.
unsigned int cos |
Definition at line 170 of file chan_mgcp.c.
unsigned int cos_audio |
Definition at line 171 of file chan_mgcp.c.
ast_group_t cur_callergroup = 0 [static] |
Definition at line 164 of file chan_mgcp.c.
ast_group_t cur_pickupgroup = 0 [static] |
Definition at line 165 of file chan_mgcp.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 97 of file chan_mgcp.c.
int directmedia = DIRECTMEDIA [static] |
int dtmfmode = 0 [static] |
Definition at line 158 of file chan_mgcp.c.
Referenced by reload_config(), and set_local_capabilities().
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic)
Definition at line 204 of file chan_mgcp.c.
ast_mutex_t gatelock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
gatelock: mutex for gateway/endpoint lists
Definition at line 420 of file chan_mgcp.c.
Referenced by do_monitor(), find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), and unload_module().
struct mgcp_gateway * gateways [static] |
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic)
Definition at line 207 of file chan_mgcp.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 105 of file chan_mgcp.c.
int hangupongateremove = 0 [static] |
Definition at line 162 of file chan_mgcp.c.
int immediate = 0 [static] |
Definition at line 174 of file chan_mgcp.c.
struct io_context* io [static] |
Definition at line 235 of file chan_mgcp.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 152 of file chan_mgcp.c.
char mailbox[AST_MAX_EXTENSION] [static] |
Definition at line 195 of file chan_mgcp.c.
Referenced by action_mailboxcount(), action_mailboxstatus(), add_peer_mailboxes(), add_peer_mwi_subs(), aji_mwi_cb(), append_mailbox_mapping(), ast_event_hash_mwi(), build_peer(), chanspy_exec(), clear_peer_mailboxes(), disa_exec(), extenspy_exec(), get_cached_mwi(), handle_request_notify(), has_voicemail(), minivm_mwi_exec(), notify_message(), peer_mailboxes_to_str(), peers_data_provider_get(), queue_mwi_event(), realtime_directory(), sip_subscribe_mwi(), unistim_send_mwi_to_peer(), and update_registry().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match
Definition at line 210 of file chan_mgcp.c.
const char* const mgcp_cxmodes[] [static] |
}
Definition at line 130 of file chan_mgcp.c.
Referenced by transmit_connect_with_sdp(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
ast_mutex_t mgcp_reload_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
Definition at line 416 of file chan_mgcp.c.
Referenced by do_monitor(), mgcp_reload(), and unload_module().
int mgcp_reloading = 0 [static] |
Definition at line 417 of file chan_mgcp.c.
Referenced by do_monitor(), mgcp_reload(), and unload_module().
struct ast_rtp_glue mgcp_rtp_glue [static] |
struct ast_channel_tech mgcp_tech [static] |
Definition at line 461 of file chan_mgcp.c.
Referenced by acf_channel_read(), load_module(), mgcp_new(), and unload_module().
int mgcpdebug = 0 [static] |
Definition at line 232 of file chan_mgcp.c.
Referenced by handle_mgcp_audit_endpoint(), and handle_mgcp_set_debug().
int mgcpsock = -1 [static] |
int* mgcpsock_read_id = NULL [static] |
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 221 of file chan_mgcp.c.
ast_mutex_t monlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
Definition at line 216 of file chan_mgcp.c.
char musicclass[MAX_MUSICCLASS] = "" [static] |
Definition at line 153 of file chan_mgcp.c.
Referenced by ast_do_masquerade(), begin_dial_channel(), dial_exec_full(), findmeexec(), func_channel_write_real(), gtalk_new(), jingle_new(), local_call(), moh_handle_digit(), monitor_dial(), and set_moh_exec().
int nat = 0 [static] |
Definition at line 159 of file chan_mgcp.c.
int ncs = 0 [static] |
Definition at line 160 of file chan_mgcp.c.
ast_mutex_t netlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 214 of file chan_mgcp.c.
Referenced by config_load(), do_monitor(), handle_request_do(), and unload_module().
int nonCodecCapability = AST_RTP_DTMF [static] |
unsigned int oseq [static] |
Definition at line 201 of file chan_mgcp.c.
Referenced by init_req(), reqprep(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_notify_request(), and transmit_notify_request_with_callerid().
char ourhost[MAXHOSTNAMELEN] [static] |
int ourport [static] |
Definition at line 230 of file chan_mgcp.c.
Referenced by initreqprep(), and transmit_notify_with_mwi().
char parkinglot[AST_MAX_CONTEXT] [static] |
Definition at line 154 of file chan_mgcp.c.
int pktcgatealloc = 0 [static] |
Definition at line 161 of file chan_mgcp.c.
struct { ... } qos [static] |
struct sched_context* sched [static] |
Definition at line 234 of file chan_mgcp.c.
int singlepath = 0 [static] |
Definition at line 189 of file chan_mgcp.c.
int slowsequence = 0 [static] |
Definition at line 180 of file chan_mgcp.c.
const char tdesc[] = "Media Gateway Control Protocol (MGCP)" [static] |
Definition at line 107 of file chan_mgcp.c.
int threewaycalling = 0 [static] |
Definition at line 182 of file chan_mgcp.c.
unsigned int tos |
Definition at line 168 of file chan_mgcp.c.
unsigned int tos_audio |
Definition at line 169 of file chan_mgcp.c.
int transfer = 0 [static] |
This is for flashhook transfers
Definition at line 185 of file chan_mgcp.c.