Implementation of Media Gateway Control Protocol. More...
#include "asterisk.h"#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>#include <fcntl.h>#include <netdb.h>#include <sys/signal.h>#include <signal.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <arpa/inet.h>#include <ctype.h>#include "asterisk/lock.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/sched.h"#include "asterisk/io.h"#include "asterisk/rtp.h"#include "asterisk/acl.h"#include "asterisk/callerid.h"#include "asterisk/cli.h"#include "asterisk/say.h"#include "asterisk/cdr.h"#include "asterisk/astdb.h"#include "asterisk/features.h"#include "asterisk/app.h"#include "asterisk/musiconhold.h"#include "asterisk/utils.h"#include "asterisk/netsock.h"#include "asterisk/causes.h"#include "asterisk/dsp.h"#include "asterisk/devicestate.h"#include "asterisk/stringfields.h"#include "asterisk/abstract_jb.h"#include "asterisk/event.h"
Go to the source code of this file.
Data Structures | |
| struct | mgcp_endpoint |
| struct | mgcp_gateway |
| struct | mgcp_message |
| mgcp_message: MGCP message for queuing up More... | |
| struct | mgcp_request |
| struct | mgcp_response |
| struct | mgcp_subchannel |
Defines | |
| #define | CANREINVITE 1 |
| #define | DEFAULT_EXPIRY 120 |
| #define | DEFAULT_MGCP_CA_PORT 2727 |
| #define | DEFAULT_MGCP_GW_PORT 2427 |
| #define | DEFAULT_RETRANS 1000 |
| #define | INADDR_NONE (in_addr_t)(-1) |
| #define | MAX_EXPIRY 3600 |
| #define | MAX_RETRANS 5 |
| #define | MAX_SUBS 2 |
| #define | MGCP_CX_CONF 3 |
| #define | MGCP_CX_CONFERENCE 3 |
| #define | MGCP_CX_INACTIVE 4 |
| #define | MGCP_CX_MUTE 4 |
| #define | MGCP_CX_RECVONLY 1 |
| #define | MGCP_CX_SENDONLY 0 |
| #define | MGCP_CX_SENDRECV 2 |
| #define | MGCP_DTMF_HYBRID (1 << 2) |
| #define | MGCP_DTMF_INBAND (1 << 1) |
| #define | MGCP_DTMF_RFC2833 (1 << 0) |
| #define | MGCP_MAX_HEADERS 64 |
| #define | MGCP_MAX_LINES 64 |
| #define | MGCP_MAX_PACKET 1500 |
| #define | MGCP_OFFHOOK 2 |
| #define | MGCP_ONHOOK 1 |
| #define | MGCP_SUBCHANNEL_MAGIC "!978!" |
| #define | MGCPDUMPER |
| #define | RESPONSE_TIMEOUT 30 |
| #define | SUB_ALT 1 |
| #define | SUB_REAL 0 |
| #define | TYPE_LINE 2 |
| #define | TYPE_TRUNK 1 |
Enumerations | |
| enum | { MGCP_CMD_EPCF, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_CMD_DLCX, MGCP_CMD_RQNT, MGCP_CMD_NTFY, MGCP_CMD_AUEP, MGCP_CMD_AUCX, MGCP_CMD_RSIP } |
Functions | |
| static char * | __get_header (struct mgcp_request *req, char *name, int *start) |
| static int | __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len) |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | add_header (struct mgcp_request *req, char *var, char *value) |
| static void | add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp) |
| static int | add_line (struct mgcp_request *req, char *line) |
| static int | add_sdp (struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp) |
| static int | attempt_transfer (struct mgcp_endpoint *p) |
| static struct mgcp_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 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_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_set_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_mgcp_show_endpoints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin) |
| static void | handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp) |
| static int | has_voicemail (struct mgcp_endpoint *p) |
| static int | init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb) |
| static int | init_resp (struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest) |
| static int | load_module (void) |
| load_module: PBX load module - initialization --- | |
| static int | mgcp_answer (struct ast_channel *ast) |
| static int | mgcp_call (struct ast_channel *ast, char *dest, int timeout) |
| static int | mgcp_devicestate (void *data) |
| mgcp_devicestate: channel callback for device status monitoring | |
| static int | mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static enum ast_rtp_get_result | mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| static int | mgcp_hangup (struct ast_channel *ast) |
| static int | mgcp_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen) |
| static struct ast_channel * | mgcp_new (struct mgcp_subchannel *sub, int state) |
| static int | mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno) |
| static void | mgcp_queue_control (struct mgcp_subchannel *sub, int control) |
| static void | mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f) |
| static void | mgcp_queue_hangup (struct mgcp_subchannel *sub) |
| static struct ast_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, int format, 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 *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active) |
| static void * | mgcp_ss (void *data) |
| static int | mgcp_write (struct ast_channel *ast, struct ast_frame *frame) |
| static int | mgcpsock_read (int *id, int fd, short events, void *ignore) |
| static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
| static void | parse (struct mgcp_request *req) |
| static int | process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req) |
| static void | prune_gateways (void) |
| static int | reload (void) |
| static int | reload_config (int reload) |
| static int | reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb) |
| static int | resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp) |
| static int | respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest) |
| static int | restart_monitor (void) |
| static int | retrans_pkt (const void *data) |
| static void | sdpLineNum_iterator_init (int *iterator) |
| static int | send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno) |
| static int | send_response (struct mgcp_subchannel *sub, struct mgcp_request *req) |
| static void | start_rtp (struct mgcp_subchannel *sub) |
| static int | transmit_audit_endpoint (struct mgcp_endpoint *p) |
| static int | transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp) |
| static int | transmit_connection_del (struct mgcp_subchannel *sub) |
| static int | transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident) |
| static int | transmit_modify_request (struct mgcp_subchannel *sub) |
| static int | transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs) |
| static int | transmit_notify_request (struct mgcp_subchannel *sub, char *tone) |
| static int | transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername) |
| static int | transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest) |
| static int | unalloc_sub (struct mgcp_subchannel *sub) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct in_addr | __ourip |
| static char | accountcode [AST_MAX_ACCOUNT_CODE] = "" |
| static int | adsi = 0 |
| static int | amaflags = 0 |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sockaddr_in | bindaddr |
| static int | callreturn = 0 |
| static int | callwaiting = 0 |
| static int | cancallforward = 0 |
| static int | canreinvite = CANREINVITE |
| static int | capability = AST_FORMAT_ULAW |
| static char | cid_name [AST_MAX_EXTENSION] = "" |
| static char | cid_num [AST_MAX_EXTENSION] = "" |
| static struct ast_cli_entry | cli_mgcp [] |
| static struct ast_cli_entry | cli_mgcp_set_debug_deprecated = AST_CLI_DEFINE(handle_mgcp_set_debug_deprecated, "Enable/Disable MGCP debugging") |
| static const char | config [] = "mgcp.conf" |
| static char | context [AST_MAX_EXTENSION] = "default" |
| static ast_group_t | cur_callergroup = 0 |
| static ast_group_t | cur_pickupgroup = 0 |
| static struct ast_jb_conf | default_jbconf |
| static int | dtmfmode = 0 |
| static int | firstdigittimeout = 16000 |
| static ast_mutex_t | gatelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| gatelock: mutex for gateway/endpoint lists | |
| static struct mgcp_gateway * | gateways |
| static int | gendigittimeout = 8000 |
| static struct ast_jb_conf | global_jbconf |
| 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 char * | mgcp_cxmodes [] |
| static ast_mutex_t | mgcp_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | mgcp_reloading = 0 |
| static struct ast_rtp_protocol | mgcp_rtp |
| static struct ast_channel_tech | mgcp_tech |
| static int | mgcpdebug = 0 |
| static int | mgcpsock = -1 |
| static int * | mgcpsock_read_id = NULL |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static char | musicclass [MAX_MUSICCLASS] = "" |
| static int | nat = 0 |
| static ast_mutex_t | netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | nonCodecCapability = AST_RTP_DTMF |
| static unsigned int | oseq |
| static char | ourhost [MAXHOSTNAMELEN] |
| static int | ourport |
| static char | parkinglot [AST_MAX_CONTEXT] |
| struct { | |
| unsigned int cos | |
| unsigned int cos_audio | |
| unsigned int tos | |
| unsigned int tos_audio | |
| } | qos |
| static struct sched_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 |
Implementation of Media Gateway Control Protocol.
Definition in file chan_mgcp.c.
| #define CANREINVITE 1 |
Definition at line 83 of file chan_mgcp.c.
Referenced by build_gateway().
| #define DEFAULT_EXPIRY 120 |
Definition at line 81 of file chan_mgcp.c.
| #define DEFAULT_MGCP_CA_PORT 2727 |
| #define DEFAULT_MGCP_GW_PORT 2427 |
| #define DEFAULT_RETRANS 1000 |
How frequently to retransmit
Definition at line 110 of file chan_mgcp.c.
Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt().
| #define INADDR_NONE (in_addr_t)(-1) |
Definition at line 86 of file chan_mgcp.c.
Referenced by build_gateway().
| #define MAX_EXPIRY 3600 |
Definition at line 82 of file chan_mgcp.c.
| #define MAX_RETRANS 5 |
Try only 5 times for retransmissions
Definition at line 111 of file chan_mgcp.c.
Referenced by retrans_pkt().
| #define MAX_SUBS 2 |
Definition at line 269 of file chan_mgcp.c.
Referenced by build_gateway(), destroy_endpoint(), reload_config(), and unistim_info().
| #define MGCP_CX_CONF 3 |
Definition at line 117 of file chan_mgcp.c.
Referenced by handle_request().
| #define MGCP_CX_CONFERENCE 3 |
Definition at line 118 of file chan_mgcp.c.
| #define MGCP_CX_INACTIVE 4 |
Definition at line 120 of file chan_mgcp.c.
Referenced by build_gateway(), mgcp_hangup(), and unalloc_sub().
| #define MGCP_CX_MUTE 4 |
Definition at line 119 of file chan_mgcp.c.
Referenced by handle_request().
| #define MGCP_CX_RECVONLY 1 |
Definition at line 115 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 114 of file chan_mgcp.c.
| #define MGCP_CX_SENDRECV 2 |
Definition at line 116 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 105 of file chan_mgcp.c.
Referenced by add_header_offhook(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().
| #define MGCP_DTMF_INBAND (1 << 1) |
Definition at line 104 of file chan_mgcp.c.
Referenced by add_header_offhook(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().
| #define MGCP_DTMF_RFC2833 (1 << 0) |
Definition at line 103 of file chan_mgcp.c.
Referenced by build_gateway(), mgcp_rtp_read(), mgcp_senddigit_begin(), and mgcp_senddigit_end().
| #define MGCP_MAX_HEADERS 64 |
The private structures of the mgcp channels are linked for ! selecting outgoing channels
Definition at line 228 of file chan_mgcp.c.
Referenced by add_header(), init_req(), init_resp(), and parse().
| #define MGCP_MAX_LINES 64 |
Definition at line 229 of file chan_mgcp.c.
Referenced by add_line(), and parse().
| #define MGCP_MAX_PACKET 1500 |
Also from RFC 2543, should sub headers tho
Definition at line 109 of file chan_mgcp.c.
| #define MGCP_OFFHOOK 2 |
Definition at line 303 of file chan_mgcp.c.
Referenced by handle_hd_hf(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
| #define MGCP_ONHOOK 1 |
Definition at line 302 of file chan_mgcp.c.
Referenced by build_gateway(), do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_request(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
| #define MGCP_SUBCHANNEL_MAGIC "!978!" |
subchannel magic string. Needed to prove that any subchannel pointer passed by asterisk really points to a valid subchannel memory area. Ugly.. But serves the purpose for the time being.
Definition at line 280 of file chan_mgcp.c.
Referenced by build_gateway(), and mgcp_hangup().
| #define MGCPDUMPER |
Definition at line 80 of file chan_mgcp.c.
| #define RESPONSE_TIMEOUT 30 |
| #define SUB_ALT 1 |
Definition at line 272 of file chan_mgcp.c.
| #define SUB_REAL 0 |
Definition at line 271 of file chan_mgcp.c.
| #define TYPE_LINE 2 |
Definition at line 306 of file chan_mgcp.c.
Referenced by build_device(), build_gateway(), do_monitor(), and mgcp_call().
| #define TYPE_TRUNK 1 |
Definition at line 305 of file chan_mgcp.c.
Referenced by build_device(), and build_gateway().
| 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 131 of file chan_mgcp.c.
00131 { 00132 MGCP_CMD_EPCF, 00133 MGCP_CMD_CRCX, 00134 MGCP_CMD_MDCX, 00135 MGCP_CMD_DLCX, 00136 MGCP_CMD_RQNT, 00137 MGCP_CMD_NTFY, 00138 MGCP_CMD_AUEP, 00139 MGCP_CMD_AUCX, 00140 MGCP_CMD_RSIP 00141 };
| static char* __get_header | ( | struct mgcp_request * | req, | |
| char * | name, | |||
| int * | start | |||
| ) | [static] |
Definition at line 1604 of file chan_mgcp.c.
References mgcp_request::header, mgcp_request::headers, and len().
Referenced by get_header().
01605 { 01606 int x; 01607 int len = strlen(name); 01608 char *r; 01609 for (x=*start;x<req->headers;x++) { 01610 if (!strncasecmp(req->header[x], name, len) && 01611 (req->header[x][len] == ':')) { 01612 r = req->header[x] + len + 1; 01613 while(*r && (*r < 33)) 01614 r++; 01615 *start = x+1; 01616 return r; 01617 } 01618 } 01619 /* Don't return NULL, so get_header is always a valid pointer */ 01620 return ""; 01621 }
| static int __mgcp_xmit | ( | struct mgcp_gateway * | gw, | |
| char * | data, | |||
| int | len | |||
| ) | [static] |
Definition at line 515 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().
00516 { 00517 int res; 00518 if (gw->addr.sin_addr.s_addr) 00519 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); 00520 else 00521 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); 00522 if (res != len) { 00523 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); 00524 } 00525 return res; 00526 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 4416 of file chan_mgcp.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4416 of file chan_mgcp.c.
| static int add_header | ( | struct mgcp_request * | req, | |
| char * | var, | |||
| char * | value | |||
| ) | [static] |
Definition at line 1950 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 add_header_offhook(), transmit_audit_endpoint(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
01951 { 01952 if (req->len >= sizeof(req->data) - 4) { 01953 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 01954 return -1; 01955 } 01956 if (req->lines) { 01957 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 01958 return -1; 01959 } 01960 req->header[req->headers] = req->data + req->len; 01961 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); 01962 req->len += strlen(req->header[req->headers]); 01963 if (req->headers < MGCP_MAX_HEADERS) 01964 req->headers++; 01965 else { 01966 ast_log(LOG_WARNING, "Out of header space\n"); 01967 return -1; 01968 } 01969 return 0; 01970 }
| static void add_header_offhook | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | resp | |||
| ) | [static] |
Definition at line 2345 of file chan_mgcp.c.
References ast_channel::_state, add_header(), AST_STATE_RINGING, mgcp_endpoint::dtmfmode, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_subchannel::owner, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
02346 { 02347 struct mgcp_endpoint *p = sub->parent; 02348 02349 if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) 02350 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02351 else 02352 add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)"); 02353 }
| static int add_line | ( | struct mgcp_request * | req, | |
| char * | line | |||
| ) | [static] |
Definition at line 1972 of file chan_mgcp.c.
References ast_copy_string(), ast_log(), mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES.
Referenced by add_sdp().
01973 { 01974 if (req->len >= sizeof(req->data) - 4) { 01975 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 01976 return -1; 01977 } 01978 if (!req->lines) { 01979 /* Add extra empty return */ 01980 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); 01981 req->len += strlen(req->data + req->len); 01982 } 01983 req->line[req->lines] = req->data + req->len; 01984 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 01985 req->len += strlen(req->line[req->lines]); 01986 if (req->lines < MGCP_MAX_LINES) 01987 req->lines++; 01988 else { 01989 ast_log(LOG_WARNING, "Out of line space\n"); 01990 return -1; 01991 } 01992 return 0; 01993 }
| static int add_sdp | ( | struct mgcp_request * | resp, | |
| struct mgcp_subchannel * | sub, | |||
| struct ast_rtp * | rtp | |||
| ) | [static] |
Definition at line 2073 of file chan_mgcp.c.
References add_line(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_get_peer(), ast_rtp_get_us(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, ast_verbose, mgcp_endpoint::capability, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, and mgcp_subchannel::tmpdest.
Referenced by transmit_connect_with_sdp(), and transmit_modify_with_sdp().
02074 { 02075 int len; 02076 int codec; 02077 char costr[80]; 02078 struct sockaddr_in sin; 02079 char v[256]; 02080 char s[256]; 02081 char o[256]; 02082 char c[256]; 02083 char t[256]; 02084 char m[256] = ""; 02085 char a[1024] = ""; 02086 int x; 02087 struct sockaddr_in dest; 02088 struct mgcp_endpoint *p = sub->parent; 02089 /* XXX We break with the "recommendation" and send our IP, in order that our 02090 peer doesn't have to ast_gethostbyname() us XXX */ 02091 len = 0; 02092 if (!sub->rtp) { 02093 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02094 return -1; 02095 } 02096 ast_rtp_get_us(sub->rtp, &sin); 02097 if (rtp) { 02098 ast_rtp_get_peer(rtp, &dest); 02099 } else { 02100 if (sub->tmpdest.sin_addr.s_addr) { 02101 dest.sin_addr = sub->tmpdest.sin_addr; 02102 dest.sin_port = sub->tmpdest.sin_port; 02103 /* Reset temporary destination */ 02104 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02105 } else { 02106 dest.sin_addr = p->parent->ourip; 02107 dest.sin_port = sin.sin_port; 02108 } 02109 } 02110 if (mgcpdebug) { 02111 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02112 } 02113 ast_copy_string(v, "v=0\r\n", sizeof(v)); 02114 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); 02115 ast_copy_string(s, "s=session\r\n", sizeof(s)); 02116 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02117 ast_copy_string(t, "t=0 0\r\n", sizeof(t)); 02118 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02119 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02120 if (p->capability & x) { 02121 if (mgcpdebug) { 02122 ast_verbose("Answering with capability %d\n", x); 02123 } 02124 codec = ast_rtp_lookup_code(sub->rtp, 1, x); 02125 if (codec > -1) { 02126 snprintf(costr, sizeof(costr), " %d", codec); 02127 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02128 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0)); 02129 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02130 } 02131 } 02132 } 02133 for (x = 1; x <= AST_RTP_MAX; x <<= 1) { 02134 if (p->nonCodecCapability & x) { 02135 if (mgcpdebug) { 02136 ast_verbose("Answering with non-codec capability %d\n", x); 02137 } 02138 codec = ast_rtp_lookup_code(sub->rtp, 0, x); 02139 if (codec > -1) { 02140 snprintf(costr, sizeof(costr), " %d", codec); 02141 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02142 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0)); 02143 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02144 if (x == AST_RTP_DTMF) { 02145 /* Indicate we support DTMF... Not sure about 16, 02146 but MSN supports it so dang it, we will too... */ 02147 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02148 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02149 } 02150 } 02151 } 02152 } 02153 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02154 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02155 snprintf(costr, sizeof(costr), "%d", len); 02156 add_line(resp, v); 02157 add_line(resp, o); 02158 add_line(resp, s); 02159 add_line(resp, c); 02160 add_line(resp, t); 02161 add_line(resp, m); 02162 add_line(resp, a); 02163 return 0; 02164 }
| static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2910 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, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().
Referenced by handle_request().
02911 { 02912 /* ************************* 02913 * I hope this works. 02914 * Copied out of chan_zap 02915 * Cross your fingers 02916 * *************************/ 02917 02918 /* In order to transfer, we need at least one of the channels to 02919 actually be in a call bridge. We can't conference two applications 02920 together (but then, why would we want to?) */ 02921 if (ast_bridged_channel(p->sub->owner)) { 02922 /* The three-way person we're about to transfer to could still be in MOH, so 02923 stop if now if appropriate */ 02924 if (ast_bridged_channel(p->sub->next->owner)) 02925 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 02926 if (p->sub->owner->_state == AST_STATE_RINGING) { 02927 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 02928 } 02929 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 02930 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 02931 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); 02932 return -1; 02933 } 02934 /* Orphan the channel */ 02935 unalloc_sub(p->sub->next); 02936 } else if (ast_bridged_channel(p->sub->next->owner)) { 02937 if (p->sub->owner->_state == AST_STATE_RINGING) { 02938 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 02939 } 02940 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 02941 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 02942 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 02943 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); 02944 return -1; 02945 } 02946 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 02947 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 02948 p->sub = p->sub->next; 02949 unalloc_sub(p->sub->next); 02950 /* Tell the caller not to hangup */ 02951 return 1; 02952 } else { 02953 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 02954 p->sub->owner->name, p->sub->next->owner->name); 02955 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02956 if (p->sub->next->owner) { 02957 p->sub->next->alreadygone = 1; 02958 mgcp_queue_hangup(p->sub->next); 02959 } 02960 } 02961 return 0; 02962 }
| static struct mgcp_gateway* build_gateway | ( | char * | cat, | |
| struct ast_variable * | v | |||
| ) | [static, read] |
build_gateway: parse mgcp.conf and create gateway/endpoint structures
Definition at line 3578 of file chan_mgcp.c.
References __ourip, mgcp_endpoint::accountcode, mgcp_gateway::addr, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_free, ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_strdupa, ast_strlen_zero(), ast_true(), ast_verb, mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::canreinvite, CANREINVITE, mgcp_endpoint::capability, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, gateways, mgcp_gateway::ha, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, INADDR_NONE, mgcp_gateway::isnamedottedip, mgcp_endpoint::language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, MAX_SUBS, mbox(), MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::msgs_lock, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, mwi_event_cb(), mgcp_endpoint::mwi_event_sub, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, mgcp_endpoint::needaudit, ast_variable::next, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_gateway::ourip, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::parkinglot, mgcp_endpoint::pickupgroup, mgcp_gateway::retransid, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, mgcp_endpoint::slowsequence, strsep(), mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and mgcp_gateway::wcardep.
Referenced by reload_config().
03579 { 03580 struct mgcp_gateway *gw; 03581 struct mgcp_endpoint *e; 03582 struct mgcp_subchannel *sub; 03583 /*char txident[80];*/ 03584 int i=0, y=0; 03585 int gw_reload = 0; 03586 int ep_reload = 0; 03587 canreinvite = CANREINVITE; 03588 03589 /* locate existing gateway */ 03590 gw = gateways; 03591 while (gw) { 03592 if (!strcasecmp(cat, gw->name)) { 03593 /* gateway already exists */ 03594 gw->delme = 0; 03595 gw_reload = 1; 03596 break; 03597 } 03598 gw = gw->next; 03599 } 03600 03601 if (!gw) 03602 gw = ast_calloc(1, sizeof(*gw)); 03603 03604 if (gw) { 03605 if (!gw_reload) { 03606 gw->expire = -1; 03607 gw->retransid = -1; /* SC */ 03608 ast_mutex_init(&gw->msgs_lock); 03609 ast_copy_string(gw->name, cat, sizeof(gw->name)); 03610 /* check if the name is numeric ip */ 03611 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 03612 gw->isnamedottedip = 1; 03613 } 03614 while(v) { 03615 if (!strcasecmp(v->name, "host")) { 03616 if (!strcasecmp(v->value, "dynamic")) { 03617 /* They'll register with us */ 03618 gw->dynamic = 1; 03619 memset(&gw->addr.sin_addr, 0, 4); 03620 if (gw->addr.sin_port) { 03621 /* If we've already got a port, make it the default rather than absolute */ 03622 gw->defaddr.sin_port = gw->addr.sin_port; 03623 gw->addr.sin_port = 0; 03624 } 03625 } else { 03626 /* Non-dynamic. Make sure we become that way if we're not */ 03627 AST_SCHED_DEL(sched, gw->expire); 03628 gw->dynamic = 0; 03629 if (ast_get_ip(&gw->addr, v->value)) { 03630 if (!gw_reload) { 03631 ast_mutex_destroy(&gw->msgs_lock); 03632 ast_free(gw); 03633 } 03634 return NULL; 03635 } 03636 } 03637 } else if (!strcasecmp(v->name, "defaultip")) { 03638 if (ast_get_ip(&gw->defaddr, v->value)) { 03639 if (!gw_reload) { 03640 ast_mutex_destroy(&gw->msgs_lock); 03641 ast_free(gw); 03642 } 03643 return NULL; 03644 } 03645 } else if (!strcasecmp(v->name, "permit") || 03646 !strcasecmp(v->name, "deny")) { 03647 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 03648 } else if (!strcasecmp(v->name, "port")) { 03649 gw->addr.sin_port = htons(atoi(v->value)); 03650 } else if (!strcasecmp(v->name, "context")) { 03651 ast_copy_string(context, v->value, sizeof(context)); 03652 } else if (!strcasecmp(v->name, "dtmfmode")) { 03653 if (!strcasecmp(v->value, "inband")) 03654 dtmfmode = MGCP_DTMF_INBAND; 03655 else if (!strcasecmp(v->value, "rfc2833")) 03656 dtmfmode = MGCP_DTMF_RFC2833; 03657 else if (!strcasecmp(v->value, "hybrid")) 03658 dtmfmode = MGCP_DTMF_HYBRID; 03659 else if (!strcasecmp(v->value, "none")) 03660 dtmfmode = 0; 03661 else 03662 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 03663 } else if (!strcasecmp(v->name, "nat")) { 03664 nat = ast_true(v->value); 03665 } else if (!strcasecmp(v->name, "callerid")) { 03666 if (!strcasecmp(v->value, "asreceived")) { 03667 cid_num[0] = '\0'; 03668 cid_name[0] = '\0'; 03669 } else { 03670 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 03671 } 03672 } else if (!strcasecmp(v->name, "language")) { 03673 ast_copy_string(language, v->value, sizeof(language)); 03674 } else if (!strcasecmp(v->name, "accountcode")) { 03675 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 03676 } else if (!strcasecmp(v->name, "amaflags")) { 03677 y = ast_cdr_amaflags2int(v->value); 03678 if (y < 0) { 03679 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 03680 } else { 03681 amaflags = y; 03682 } 03683 } else if (!strcasecmp(v->name, "musiconhold")) { 03684 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 03685 } else if (!strcasecmp(v->name, "parkinglot")) { 03686 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 03687 } else if (!strcasecmp(v->name, "callgroup")) { 03688 cur_callergroup = ast_get_group(v->value); 03689 } else if (!strcasecmp(v->name, "pickupgroup")) { 03690 cur_pickupgroup = ast_get_group(v->value); 03691 } else if (!strcasecmp(v->name, "immediate")) { 03692 immediate = ast_true(v->value); 03693 } else if (!strcasecmp(v->name, "cancallforward")) { 03694 cancallforward = ast_true(v->value); 03695 } else if (!strcasecmp(v->name, "singlepath")) { 03696 singlepath = ast_true(v->value); 03697 } else if (!strcasecmp(v->name, "canreinvite")) { 03698 canreinvite = ast_true(v->value); 03699 } else if (!strcasecmp(v->name, "mailbox")) { 03700 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 03701 } else if (!strcasecmp(v->name, "hasvoicemail")) { 03702 if (ast_true(v->value) && ast_strlen_zero(mailbox)) { 03703 ast_copy_string(mailbox, gw->name, sizeof(mailbox)); 03704 } 03705 } else if (!strcasecmp(v->name, "adsi")) { 03706 adsi = ast_true(v->value); 03707 } else if (!strcasecmp(v->name, "callreturn")) { 03708 callreturn = ast_true(v->value); 03709 } else if (!strcasecmp(v->name, "callwaiting")) { 03710 callwaiting = ast_true(v->value); 03711 } else if (!strcasecmp(v->name, "slowsequence")) { 03712 slowsequence = ast_true(v->value); 03713 } else if (!strcasecmp(v->name, "transfer")) { 03714 transfer = ast_true(v->value); 03715 } else if (!strcasecmp(v->name, "threewaycalling")) { 03716 threewaycalling = ast_true(v->value); 03717 } else if (!strcasecmp(v->name, "wcardep")) { 03718 /* locate existing endpoint */ 03719 e = gw->endpoints; 03720 while (e) { 03721 if (!strcasecmp(v->value, e->name)) { 03722 /* endpoint already exists */ 03723 e->delme = 0; 03724 ep_reload = 1; 03725 break; 03726 } 03727 e = e->next; 03728 } 03729 03730 if (!e) { 03731 /* Allocate wildcard endpoint */ 03732 e = ast_calloc(1, sizeof(*e)); 03733 ep_reload = 0; 03734 } 03735 03736 if (e) { 03737 if (!ep_reload) { 03738 memset(e, 0, sizeof(struct mgcp_endpoint)); 03739 ast_mutex_init(&e->lock); 03740 ast_mutex_init(&e->rqnt_queue_lock); 03741 ast_mutex_init(&e->cmd_queue_lock); 03742 ast_copy_string(e->name, v->value, sizeof(e->name)); 03743 e->needaudit = 1; 03744 } 03745 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 03746 /* XXX Should we really check for uniqueness?? XXX */ 03747 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 03748 ast_copy_string(e->context, context, sizeof(e->context)); 03749 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 03750 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 03751 ast_copy_string(e->language, language, sizeof(e->language)); 03752 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 03753 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 03754 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 03755 if (!ast_strlen_zero(e->mailbox)) { 03756 char *mbox, *cntx; 03757 cntx = mbox = ast_strdupa(e->mailbox); 03758 strsep(&cntx, "@"); 03759 if (ast_strlen_zero(cntx)) 03760 cntx = "default"; 03761 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 03762 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 03763 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 03764 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 03765 AST_EVENT_IE_END); 03766 } 03767 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 03768 e->msgstate = -1; 03769 e->amaflags = amaflags; 03770 e->capability = capability; 03771 e->parent = gw; 03772 e->dtmfmode = dtmfmode; 03773 if (!ep_reload && e->sub && e->sub->rtp) 03774 e->dtmfmode |= MGCP_DTMF_INBAND; 03775 e->adsi = adsi; 03776 e->type = TYPE_LINE; 03777 e->immediate = immediate; 03778 e->callgroup=cur_callergroup; 03779 e->pickupgroup=cur_pickupgroup; 03780 e->callreturn = callreturn; 03781 e->cancallforward = cancallforward; 03782 e->singlepath = singlepath; 03783 e->canreinvite = canreinvite; 03784 e->callwaiting = callwaiting; 03785 e->hascallwaiting = callwaiting; 03786 e->slowsequence = slowsequence; 03787 e->transfer = transfer; 03788 e->threewaycalling = threewaycalling; 03789 e->onhooktime = time(NULL); 03790 /* ASSUME we're onhook */ 03791 e->hookstate = MGCP_ONHOOK; 03792 if (!ep_reload) { 03793 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 03794 for (i = 0; i < MAX_SUBS; i++) { 03795 sub = ast_calloc(1, sizeof(*sub)); 03796 if (sub) { 03797 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 03798 ast_mutex_init(&sub->lock); 03799 ast_mutex_init(&sub->cx_queue_lock); 03800 sub->parent = e; 03801 sub->id = i; 03802 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 03803 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 03804 sub->cxmode = MGCP_CX_INACTIVE; 03805 sub->nat = nat; 03806 sub->next = e->sub; 03807 e->sub = sub; 03808 } else { 03809 /* XXX Should find a way to clean up our memory */ 03810 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 03811 return NULL; 03812 } 03813 } 03814 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 03815 sub = e->sub; 03816 /* find the end of the list */ 03817 while(sub->next){ 03818 sub = sub->next; 03819 } 03820 /* set the last sub->next to the first sub */ 03821 sub->next = e->sub; 03822 03823 e->next = gw->endpoints; 03824 gw->endpoints = e; 03825 } 03826 } 03827 } else if (!strcasecmp(v->name, "trunk") || 03828 !strcasecmp(v->name, "line")) { 03829 03830 /* locate existing endpoint */ 03831 e = gw->endpoints; 03832 while (e) { 03833 if (!strcasecmp(v->value, e->name)) { 03834 /* endpoint already exists */ 03835 e->delme = 0; 03836 ep_reload = 1; 03837 break; 03838 } 03839 e = e->next; 03840 } 03841 03842 if (!e) { 03843 e = ast_calloc(1, sizeof(*e)); 03844 ep_reload = 0; 03845 } 03846 03847 if (e) { 03848 if (!ep_reload) { 03849 ast_mutex_init(&e->lock); 03850 ast_mutex_init(&e->rqnt_queue_lock); 03851 ast_mutex_init(&e->cmd_queue_lock); 03852 ast_copy_string(e->name, v->value, sizeof(e->name)); 03853 e->needaudit = 1; 03854 } 03855 /* XXX Should we really check for uniqueness?? XXX */ 03856 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 03857 ast_copy_string(e->context, context, sizeof(e->context)); 03858 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 03859 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 03860 ast_copy_string(e->language, language, sizeof(e->language)); 03861 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 03862 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 03863 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 03864 if (!ast_strlen_zero(mailbox)) { 03865 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 03866 } 03867 if (!ep_reload) { 03868 /* XXX potential issue due to reload */ 03869 e->msgstate = -1; 03870 e->parent = gw; 03871 } 03872 e->amaflags = amaflags; 03873 e->capability = capability; 03874 e->dtmfmode = dtmfmode; 03875 e->adsi = adsi; 03876 if (!strcasecmp(v->name, "trunk")) 03877 e->type = TYPE_TRUNK; 03878 else 03879 e->type = TYPE_LINE; 03880 03881 e->immediate = immediate; 03882 e->callgroup=cur_callergroup; 03883 e->pickupgroup=cur_pickupgroup; 03884 e->callreturn = callreturn; 03885 e->cancallforward = cancallforward; 03886 e->canreinvite = canreinvite; 03887 e->singlepath = singlepath; 03888 e->callwaiting = callwaiting; 03889 e->hascallwaiting = callwaiting; 03890 e->slowsequence = slowsequence; 03891 e->transfer = transfer; 03892 e->threewaycalling = threewaycalling; 03893 if (!ep_reload) { 03894 e->onhooktime = time(NULL); 03895 /* ASSUME we're onhook */ 03896 e->hookstate = MGCP_ONHOOK; 03897 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 03898 } 03899 03900 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 03901 if (!ep_reload) { 03902 sub = ast_calloc(1, sizeof(*sub)); 03903 } else { 03904 if (!sub) 03905 sub = e->sub; 03906 else 03907 sub = sub->next; 03908 } 03909 03910 if (sub) { 03911 if (!ep_reload) { 03912 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 03913 ast_mutex_init(&sub->lock); 03914 ast_mutex_init(&sub->cx_queue_lock); 03915 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 03916 sub->parent = e; 03917 sub->id = i; 03918 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 03919 sub->cxmode = MGCP_CX_INACTIVE; 03920 sub->next = e->sub; 03921 e->sub = sub; 03922 } 03923 sub->nat = nat; 03924 } else { 03925 /* XXX Should find a way to clean up our memory */ 03926 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 03927 return NULL; 03928 } 03929 } 03930 if (!ep_reload) { 03931 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 03932 sub = e->sub; 03933 /* find the end of the list */ 03934 while (sub->next) { 03935 sub = sub->next; 03936 } 03937 /* set the last sub->next to the first sub */ 03938 sub->next = e->sub; 03939 03940 e->next = gw->endpoints; 03941 gw->endpoints = e; 03942 } 03943 } 03944 } else 03945 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 03946 v = v->next; 03947 } 03948 } 03949 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 03950 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 03951 if (!gw_reload) { 03952 ast_mutex_destroy(&gw->msgs_lock); 03953 ast_free(gw); 03954 } 03955 return NULL; 03956 } 03957 gw->defaddr.sin_family = AF_INET; 03958 gw->addr.sin_family = AF_INET; 03959 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 03960 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 03961 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) 03962 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 03963 if (gw->addr.sin_addr.s_addr) 03964 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) 03965 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 03966 03967 return (gw_reload ? NULL : gw); 03968 }
| static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1420 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().
01420 { 01421 switch (ind) { 01422 case AST_CONTROL_HANGUP: 01423 return "Other end has hungup"; 01424 case AST_CONTROL_RING: 01425 return "Local ring"; 01426 case AST_CONTROL_RINGING: 01427 return "Remote end is ringing"; 01428 case AST_CONTROL_ANSWER: 01429 return "Remote end has answered"; 01430 case AST_CONTROL_BUSY: 01431 return "Remote end is busy"; 01432 case AST_CONTROL_TAKEOFFHOOK: 01433 return "Make it go off hook"; 01434 case AST_CONTROL_OFFHOOK: 01435 return "Line is off hook"; 01436 case AST_CONTROL_CONGESTION: 01437 return "Congestion (circuits busy)"; 01438 case AST_CONTROL_FLASH: 01439 return "Flash hook"; 01440 case AST_CONTROL_WINK: 01441 return "Wink"; 01442 case AST_CONTROL_OPTION: 01443 return "Set a low-level option"; 01444 case AST_CONTROL_RADIO_KEY: 01445 return "Key Radio"; 01446 case AST_CONTROL_RADIO_UNKEY: 01447 return "Un-Key Radio"; 01448 } 01449 return "UNKNOWN"; 01450 }
| static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 4003 of file chan_mgcp.c.
References ast_dsp_free(), ast_event_unsubscribe(), ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, dump_cmd_queues(), dump_queue(), mgcp_endpoint::lock, mgcp_subchannel::lock, mgcp_subchannel::magic, MAX_SUBS, mgcp_queue_hangup(), mgcp_endpoint::mwi_event_sub, mgcp_subchannel::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and transmit_connection_del().
Referenced by prune_gateways().
04004 { 04005 struct mgcp_subchannel *sub = e->sub->next, *s; 04006 int i; 04007 04008 for (i = 0; i < MAX_SUBS; i++) { 04009 ast_mutex_lock(&sub->lock); 04010 if (!ast_strlen_zero(sub->cxident)) { 04011 transmit_connection_del(sub); 04012 } 04013 if (sub->rtp) { 04014 ast_rtp_destroy(sub->rtp); 04015 sub->rtp = NULL; 04016 } 04017 memset(sub->magic, 0, sizeof(sub->magic)); 04018 mgcp_queue_hangup(sub); 04019 dump_cmd_queues(NULL, sub); 04020 ast_mutex_unlock(&sub->lock); 04021 sub = sub->next; 04022 } 04023 04024 if (e->dsp) { 04025 ast_dsp_free(e->dsp); 04026 } 04027 04028 dump_queue(e->parent, e); 04029 dump_cmd_queues(e, NULL); 04030 04031 sub = e->sub; 04032 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04033 s = sub; 04034 sub = sub->next; 04035 ast_mutex_destroy(&s->lock); 04036 ast_mutex_destroy(&s->cx_queue_lock); 04037 ast_free(s); 04038 } 04039 04040 if (e->mwi_event_sub) 04041 ast_event_unsubscribe(e->mwi_event_sub); 04042 04043 ast_mutex_destroy(&e->lock); 04044 ast_mutex_destroy(&e->rqnt_queue_lock); 04045 ast_mutex_destroy(&e->cmd_queue_lock); 04046 ast_free(e); 04047 }
| static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4049 of file chan_mgcp.c.
References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.
Referenced by prune_gateways().
04050 { 04051 if (g->ha) 04052 ast_free_ha(g->ha); 04053 04054 dump_queue(g, NULL); 04055 04056 ast_free(g); 04057 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3409 of file chan_mgcp.c.
References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, gateways, has_voicemail(), MGCP_ONHOOK, mgcp_reload_lock, mgcpsock_read(), monlock, netlock, reload_config(), transmit_notify_request(), and TYPE_LINE.
Referenced by restart_monitor().
03410 { 03411 int res; 03412 int reloading; 03413 /*struct mgcp_gateway *g;*/ 03414 /*struct mgcp_endpoint *e;*/ 03415 /*time_t thispass = 0, lastpass = 0;*/ 03416 03417 /* Add an I/O event to our UDP socket */ 03418 if (mgcpsock > -1) 03419 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03420 03421 /* This thread monitors all the frame relay interfaces which are not yet in use 03422 (and thus do not have a separate thread) indefinitely */ 03423 /* From here on out, we die whenever asked */ 03424 for(;;) { 03425 /* Check for a reload request */ 03426 ast_mutex_lock(&mgcp_reload_lock); 03427 reloading = mgcp_reloading; 03428 mgcp_reloading = 0; 03429 ast_mutex_unlock(&mgcp_reload_lock); 03430 if (reloading) { 03431 ast_verb(1, "Reloading MGCP\n"); 03432 reload_config(1); 03433 /* Add an I/O event to our UDP socket */ 03434 if (mgcpsock > -1 && !mgcpsock_read_id) { 03435 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03436 } 03437 } 03438 03439 /* Check for interfaces needing to be killed */ 03440 /* Don't let anybody kill us right away. Nobody should lock the interface list 03441 and wait for the monitor list, but the other way around is okay. */ 03442 ast_mutex_lock(&monlock); 03443 /* Lock the network interface */ 03444 ast_mutex_lock(&netlock); 03445 03446 #if 0 03447 /* XXX THIS IS COMPLETELY HOSED */ 03448 /* The gateway goes into a state of panic */ 03449 /* If the vmwi indicator is sent while it is reseting interfaces */ 03450 lastpass = thispass; 03451 thispass = time(NULL); 03452 g = gateways; 03453 while(g) { 03454 if (thispass != lastpass) { 03455 e = g->endpoints; 03456 while(e) { 03457 if (e->type == TYPE_LINE) { 03458 res = has_voicemail(e); 03459 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03460 if (res) { 03461 transmit_notify_request(e, "L/vmwi(+)"); 03462 } else { 03463 transmit_notify_request(e, "L/vmwi(-)"); 03464 } 03465 e->msgstate = res; 03466 e->onhooktime = thispass; 03467 } 03468 } 03469 e = e->next; 03470 } 03471 } 03472 g = g->next; 03473 } 03474 #endif 03475 /* Okay, now that we know what to do, release the network lock */ 03476 ast_mutex_unlock(&netlock); 03477 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03478 ast_mutex_unlock(&monlock); 03479 pthread_testcancel(); 03480 /* Wait for sched or io */ 03481 res = ast_sched_wait(sched); 03482 /* copied from chan_sip.c */ 03483 if ((res < 0) || (res > 1000)) 03484 res = 1000; 03485 res = ast_io_wait(io, res); 03486 ast_mutex_lock(&monlock); 03487 if (res >= 0) 03488 ast_sched_runq(sched); 03489 ast_mutex_unlock(&monlock); 03490 } 03491 /* Never reached */ 03492 return NULL; 03493 }
| static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub | |||
| ) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2414 of file chan_mgcp.c.
References ast_free, ast_mutex_lock(), ast_mutex_unlock(), mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::next, mgcp_request::next, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::sub.
Referenced by destroy_endpoint(), handle_request(), handle_response(), and unalloc_sub().
02415 { 02416 struct mgcp_request *t, *q; 02417 02418 if (p) { 02419 ast_mutex_lock(&p->rqnt_queue_lock); 02420 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); 02421 p->rqnt_queue = NULL; 02422 ast_mutex_unlock(&p->rqnt_queue_lock); 02423 02424 ast_mutex_lock(&p->cmd_queue_lock); 02425 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); 02426 p->cmd_queue = NULL; 02427 ast_mutex_unlock(&p->cmd_queue_lock); 02428 02429 ast_mutex_lock(&p->sub->cx_queue_lock); 02430 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02431 p->sub->cx_queue = NULL; 02432 ast_mutex_unlock(&p->sub->cx_queue_lock); 02433 02434 ast_mutex_lock(&p->sub->next->cx_queue_lock); 02435 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); 02436 p->sub->next->cx_queue = NULL; 02437 ast_mutex_unlock(&p->sub->next->cx_queue_lock); 02438 } else if (sub) { 02439 ast_mutex_lock(&sub->cx_queue_lock); 02440 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02441 sub->cx_queue = NULL; 02442 ast_mutex_unlock(&sub->cx_queue_lock); 02443 } 02444 }
| static void dump_queue | ( | struct mgcp_gateway * | gw, | |
| struct mgcp_endpoint * | p | |||
| ) | [static] |
Definition at line 555 of file chan_mgcp.c.
References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_NOTICE, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, and mgcp_message::next.
Referenced by destroy_endpoint(), destroy_gateway(), and handle_request().
00556 { 00557 struct mgcp_message *cur, *q = NULL, *w, *prev; 00558 00559 ast_mutex_lock(&gw->msgs_lock); 00560 prev = NULL, cur = gw->msgs; 00561 while (cur) { 00562 if (!p || cur->owner_ep == p) { 00563 if (prev) 00564 prev->next = cur->next; 00565 else 00566 gw->msgs = cur->next; 00567 00568 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 00569 gw->name, cur->seqno); 00570 00571 w = cur; 00572 cur = cur->next; 00573 if (q) { 00574 w->next = q; 00575 } else { 00576 w->next = NULL; 00577 } 00578 q = w; 00579 } else { 00580 prev = cur, cur=cur->next; 00581 } 00582 } 00583 ast_mutex_unlock(&gw->msgs_lock); 00584 00585 while (q) { 00586 cur = q; 00587 q = q->next; 00588 ast_free(cur); 00589 } 00590 }
| static int find_and_retrans | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 3288 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().
03289 { 03290 int seqno=0; 03291 time_t now; 03292 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL; 03293 time(&now); 03294 if (sscanf(req->identifier, "%30d", &seqno) != 1) 03295 seqno = 0; 03296 cur = sub->parent->parent->responses; 03297 while(cur) { 03298 next = cur->next; 03299 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03300 /* Delete this entry */ 03301 if (prev) 03302 prev->next = next; 03303 else 03304 sub->parent->parent->responses = next; 03305 ast_free(cur); 03306 } else { 03307 if (seqno == cur->seqno) 03308 answer = cur; 03309 prev = cur; 03310 } 03311 cur = next; 03312 } 03313 if (answer) { 03314 resend_response(sub, answer); 03315 return 1; 03316 } 03317 return 0; 03318 }
| static struct mgcp_request* find_command | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub, | |||
| struct mgcp_request ** | queue, | |||
| ast_mutex_t * | l, | |||
| int | ident | |||
| ) | [static, read] |
find_command: (SC:) remove command transaction from queue
Definition at line 2448 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, mgcp_postrequest(), mgcp_request::next, and mgcp_endpoint::parent.
Referenced by handle_response().
02450 { 02451 struct mgcp_request *prev, *req; 02452 02453 ast_mutex_lock(l); 02454 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02455 if (req->trid == ident) { 02456 /* remove from queue */ 02457 if (!prev) 02458 *queue = req->next; 02459 else 02460 prev->next = req->next; 02461 02462 /* send next pending command */ 02463 if (*queue) { 02464 if (mgcpdebug) { 02465 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02466 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02467 } 02468 02469 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02470 } 02471 break; 02472 } 02473 } 02474 ast_mutex_unlock(l); 02475 return req; 02476 }
| static struct mgcp_subchannel* find_subchannel_and_lock | ( | char * | name, | |
| int | msgid, | |||
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 1651 of file chan_mgcp.c.
References __ourip, mgcp_gateway::addr, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_ouraddrfor(), ast_verb, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_subchannel::next, mgcp_gateway::next, mgcp_gateway::ourip, and mgcp_endpoint::sub.
Referenced by mgcp_request(), and mgcpsock_read().
01652 { 01653 struct mgcp_endpoint *p = NULL; 01654 struct mgcp_subchannel *sub = NULL; 01655 struct mgcp_gateway *g; 01656 char tmp[256] = ""; 01657 char *at = NULL, *c; 01658 int found = 0; 01659 if (name) { 01660 ast_copy_string(tmp, name, sizeof(tmp)); 01661 at = strchr(tmp, '@'); 01662 if (!at) { 01663 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); 01664 return NULL; 01665 } 01666 *at++ = '\0'; 01667 } 01668 ast_mutex_lock(&gatelock); 01669 if (at && (at[0] == '[')) { 01670 at++; 01671 c = strrchr(at, ']'); 01672 if (c) 01673 *c = '\0'; 01674 } 01675 g = gateways; 01676 while(g) { 01677 if ((!name || !strcasecmp(g->name, at)) && 01678 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { 01679 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ 01680 if (sin && g->dynamic && name) { 01681 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01682 (g->addr.sin_port != sin->sin_port)) { 01683 memcpy(&g->addr, sin, sizeof(g->addr)); 01684 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip)) 01685 memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 01686 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)); 01687 } 01688 } 01689 /* not dynamic, check if the name matches */ 01690 else if (name) { 01691 if (strcasecmp(g->name, at)) { 01692 g = g->next; 01693 continue; 01694 } 01695 } 01696 /* not dynamic, no name, check if the addr matches */ 01697 else if (!name && sin) { 01698 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01699 (g->addr.sin_port != sin->sin_port)) { 01700 g = g->next; 01701 continue; 01702 } 01703 } else { 01704 g = g->next; 01705 continue; 01706 } 01707 /* SC */ 01708 p = g->endpoints; 01709 while(p) { 01710 ast_debug(1, "Searching on %s@%s for subchannel\n", 01711 p->name, g->name); 01712 if (msgid) { 01713 #if 0 /* new transport mech */ 01714 sub = p->sub; 01715 do { 01716 ast_debug(1, "Searching on %s@%s-%d for subchannel with lastout: %d\n", 01717 p->name, g->name, sub->id, msgid); 01718 if (sub->lastout == msgid) { 01719 ast_debug(1, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", 01720 sub->id, msgid, sub->lastout); 01721 found = 1; 01722 break; 01723 } 01724 sub = sub->next; 01725 } while (sub != p->sub); 01726 if (found) { 01727 break; 01728 } 01729 #endif 01730 /* SC */ 01731 sub = p->sub; 01732 found = 1; 01733 /* SC */ 01734 break; 01735 } else if (name && !strcasecmp(p->name, tmp)) { 01736 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 01737 p->name, g->name, p->sub->id); 01738 sub = p->sub; 01739 found = 1; 01740 break; 01741 } 01742 p = p->next; 01743 } 01744 if (sub && found) { 01745 ast_mutex_lock(&sub->lock); 01746 break; 01747 } 01748 } 01749 g = g->next; 01750 } 01751 ast_mutex_unlock(&gatelock); 01752 if (!sub) { 01753 if (name) { 01754 if (g) 01755 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); 01756 else 01757 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); 01758 } 01759 } 01760 return sub; 01761 }
| static char* get_csv | ( | char * | c, | |
| int * | len, | |||
| char ** | next | |||
| ) | [static] |
get_csv: (SC:) get comma separated value
Definition at line 1630 of file chan_mgcp.c.
References s.
Referenced by handle_response().
01631 { 01632 char *s; 01633 01634 *next = NULL, *len = 0; 01635 if (!c) return NULL; 01636 01637 while (*c && (*c < 33 || *c == ',')) 01638 c++; 01639 01640 s = c; 01641 while (*c && (*c >= 33 && *c != ',')) 01642 c++, (*len)++; 01643 *next = c; 01644 01645 if (*len == 0) 01646 s = NULL, *next = NULL; 01647 01648 return s; 01649 }
| static char* get_header | ( | struct mgcp_request * | req, | |
| char * | name | |||
| ) | [static] |
Definition at line 1623 of file chan_mgcp.c.
References __get_header().
Referenced by handle_request(), and handle_response().
01624 { 01625 int start = 0; 01626 return __get_header(req, name, &start); 01627 }
| static char* get_sdp | ( | struct mgcp_request * | req, | |
| char * | name | |||
| ) | [static] |
Definition at line 1575 of file chan_mgcp.c.
References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.
Referenced by process_sdp().
| static char* get_sdp_by_line | ( | char * | line, | |
| char * | name, | |||
| int | nameLen | |||
| ) | [static] |
Definition at line 1565 of file chan_mgcp.c.
Referenced by get_sdp(), and get_sdp_iterate().
01566 { 01567 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { 01568 char* r = line + nameLen + 1; 01569 while (*r && (*r < 33)) ++r; 01570 return r; 01571 } 01572 return ""; 01573 }
| static char* get_sdp_iterate | ( | int * | iterator, | |
| struct mgcp_request * | req, | |||
| char * | name | |||
| ) | [static] |
Definition at line 1593 of file chan_mgcp.c.
References get_sdp_by_line(), len(), and mgcp_request::line.
Referenced by process_sdp().
01594 { 01595 int len = strlen(name); 01596 char *r; 01597 while (*iterator < req->lines) { 01598 r = get_sdp_by_line(req->line[(*iterator)++], name, len); 01599 if (r[0] != '\0') return r; 01600 } 01601 return ""; 01602 }
| static void handle_hd_hf | ( | struct mgcp_subchannel * | sub, | |
| char * | ev | |||
| ) | [static] |
Definition at line 2964 of file chan_mgcp.c.
References ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_UNHOLD, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), AST_STATE_DOWN, AST_STATE_RING, mgcp_subchannel::cxmode, errno, has_voicemail(), mgcp_endpoint::hookstate, mgcp_endpoint::immediate, LOG_WARNING, MGCP_CX_SENDRECV, mgcp_new(), MGCP_OFFHOOK, mgcp_queue_control(), mgcp_ss(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), transmit_modify_request(), and transmit_notify_request().
Referenced by handle_request().
02965 { 02966 struct mgcp_endpoint *p = sub->parent; 02967 struct ast_channel *c; 02968 pthread_t t; 02969 02970 /* Off hook / answer */ 02971 if (sub->outgoing) { 02972 /* Answered */ 02973 if (sub->owner) { 02974 if (ast_bridged_channel(sub->owner)) 02975 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 02976 sub->cxmode = MGCP_CX_SENDRECV; 02977 if (!sub->rtp) { 02978 start_rtp(sub); 02979 } else { 02980 transmit_modify_request(sub); 02981 } 02982 /*transmit_notify_request(sub, "aw");*/ 02983 transmit_notify_request(sub, ""); 02984 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 02985 } 02986 } else { 02987 /* Start switch */ 02988 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 02989 if (!sub->owner) { 02990 if (!sub->rtp) { 02991 start_rtp(sub); 02992 } else { 02993 transmit_modify_request(sub); 02994 } 02995 if (p->immediate) { 02996 /* The channel is immediately up. Start right away */ 02997 #ifdef DLINK_BUGGY_FIRMWARE 02998 transmit_notify_request(sub, "rt"); 02999 #else 03000 transmit_notify_request(sub, "G/rt"); 03001 #endif 03002 c = mgcp_new(sub, AST_STATE_RING); 03003 if (!c) { 03004 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 03005 transmit_notify_request(sub, "G/cg"); 03006 ast_hangup(c); 03007 } 03008 } else { 03009 if (has_voicemail(p)) { 03010 transmit_notify_request(sub, "L/sl"); 03011 } else { 03012 transmit_notify_request(sub, "L/dl"); 03013 } 03014 c = mgcp_new(sub, AST_STATE_DOWN); 03015 if (c) { 03016 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { 03017 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 03018 ast_hangup(c); 03019 } 03020 } else { 03021 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 03022 } 03023 } 03024 } else { 03025 if (p->hookstate == MGCP_OFFHOOK) { 03026 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03027 } else { 03028 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03029 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 03030 } 03031 if (ast_bridged_channel(sub->owner)) 03032 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03033 sub->cxmode = MGCP_CX_SENDRECV; 03034 if (!sub->rtp) { 03035 start_rtp(sub); 03036 } else { 03037 transmit_modify_request(sub); 03038 } 03039 /*transmit_notify_request(sub, "aw");*/ 03040 transmit_notify_request(sub, ""); 03041 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03042 } 03043 } 03044 }
| static char* handle_mgcp_audit_endpoint | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1077 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, transmit_audit_endpoint(), and ast_cli_entry::usage.
01078 { 01079 struct mgcp_gateway *mg; 01080 struct mgcp_endpoint *me; 01081 int found = 0; 01082 char *ename,*gname, *c; 01083 01084 switch (cmd) { 01085 case CLI_INIT: 01086 e->command = "mgcp audit endpoint"; 01087 e->usage = 01088 "Usage: mgcp audit endpoint <endpointid>\n" 01089 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n" 01090 " mgcp debug MUST be on to see the results of this command.\n"; 01091 return NULL; 01092 case CLI_GENERATE: 01093 return NULL; 01094 } 01095 01096 if (!mgcpdebug) { 01097 return CLI_SHOWUSAGE; 01098 } 01099 if (a->argc != 4) 01100 return CLI_SHOWUSAGE; 01101 /* split the name into parts by null */ 01102 ename = a->argv[3]; 01103 gname = ename; 01104 while (*gname) { 01105 if (*gname == '@') { 01106 *gname = 0; 01107 gname++; 01108 break; 01109 } 01110 gname++; 01111 } 01112 if (gname[0] == '[') 01113 gname++; 01114 if ((c = strrchr(gname, ']'))) 01115 *c = '\0'; 01116 ast_mutex_lock(&gatelock); 01117 mg = gateways; 01118 while(mg) { 01119 if (!strcasecmp(mg->name, gname)) { 01120 me = mg->endpoints; 01121 while(me) { 01122 if (!strcasecmp(me->name, ename)) { 01123 found = 1; 01124 transmit_audit_endpoint(me); 01125 break; 01126 } 01127 me = me->next; 01128 } 01129 if (found) { 01130 break; 01131 } 01132 } 01133 mg = mg->next; 01134 } 01135 if (!found) { 01136 ast_cli(a->fd, " << Could not find endpoint >> "); 01137 } 01138 ast_mutex_unlock(&gatelock); 01139 return CLI_SUCCESS; 01140 }
| static char* handle_mgcp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1167 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
01168 { 01169 switch (cmd) { 01170 case CLI_INIT: 01171 e->command = "mgcp set debug {on|off}"; 01172 e->usage = 01173 "Usage: mgcp set debug {on|off}\n" 01174 " Enables/Disables dumping of MGCP packets for debugging purposes\n"; 01175 return NULL; 01176 case CLI_GENERATE: 01177 return NULL; 01178 } 01179 01180 if (a->argc != e->args) 01181 return CLI_SHOWUSAGE; 01182 01183 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 01184 mgcpdebug = 1; 01185 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01186 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01187 mgcpdebug = 0; 01188 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01189 } else { 01190 return CLI_SHOWUSAGE; 01191 } 01192 return CLI_SUCCESS; 01193 }
| static char* handle_mgcp_set_debug_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1142 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
01143 { 01144 switch (cmd) { 01145 case CLI_INIT: 01146 e->command = "mgcp set debug [off]"; 01147 e->usage = 01148 "Usage: mgcp set debug [off]\n" 01149 " Enables/Disables dumping of MGCP packets for debugging purposes\n"; 01150 return NULL; 01151 case CLI_GENERATE: 01152 return NULL; 01153 } 01154 01155 if (a->argc < 3 || a->argc > 4) 01156 return CLI_SHOWUSAGE; 01157 if (a->argc == 3) { 01158 mgcpdebug = 1; 01159 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01160 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01161 mgcpdebug = 0; 01162 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01163 } 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 1037 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_endpoint::context, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, mgcp_subchannel::owner, mgcp_endpoint::sub, ast_cli_entry::usage, and mgcp_gateway::wcardep.
01038 { 01039 struct mgcp_gateway *mg; 01040 struct mgcp_endpoint *me; 01041 int hasendpoints = 0; 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 ast_mutex_lock(&gatelock); 01057 mg = gateways; 01058 while(mg) { 01059 me = mg->endpoints; 01060 ast_cli(a->fd, "Gateway '%s' at %s (%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->dynamic ? "Dynamic" : "Static"); 01061 while(me) { 01062 /* Don't show wilcard endpoint */ 01063 if (strcmp(me->name, mg->wcardep) != 0) 01064 ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle"); 01065 hasendpoints = 1; 01066 me = me->next; 01067 } 01068 if (!hasendpoints) { 01069 ast_cli(a->fd, " << No Endpoints Defined >> "); 01070 } 01071 mg = mg->next; 01072 } 01073 ast_mutex_unlock(&gatelock); 01074 return CLI_SUCCESS; 01075 }
| static int handle_request | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req, | |||
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 3046 of file chan_mgcp.c.
References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_DOWN, AST_STATE_UP, ast_verb, ast_verbose, attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::dtmf_buf, dump_cmd_queues(), dump_queue(), mgcp_gateway::endpoints, ast_frame::frametype, 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::next, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, ast_frame::src, mgcp_endpoint::sub, ast_frame::subclass, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, transmit_audit_endpoint(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_response(), mgcp_request::verb, and mgcp_gateway::wcardep.
Referenced by mgcpsock_read().
03047 { 03048 char *ev, *s; 03049 struct ast_frame f = { 0, }; 03050 struct mgcp_endpoint *p = sub->parent; 03051 struct mgcp_gateway *g = NULL; 03052 int res; 03053 03054 if (mgcpdebug) { 03055 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03056 } 03057 /* Clear out potential response */ 03058 if (!strcasecmp(req->verb, "RSIP")) { 03059 /* Test if this RSIP request is just a keepalive */ 03060 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03061 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03062 transmit_response(sub, "200", req, "OK"); 03063 } else { 03064 dump_queue(p->parent, p); 03065 dump_cmd_queues(p, NULL); 03066 03067 if ((strcmp(p->name, p->parent->wcardep) != 0)) { 03068 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); 03069 } 03070 /* For RSIP on wildcard we reset all endpoints */ 03071 if (!strcmp(p->name, p->parent->wcardep)) { 03072 /* Reset all endpoints */ 03073 struct mgcp_endpoint *tmp_ep; 03074 03075 g = p->parent; 03076 tmp_ep = g->endpoints; 03077 while (tmp_ep) { 03078 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03079 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03080 struct mgcp_subchannel *tmp_sub, *first_sub; 03081 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03082 03083 first_sub = tmp_ep->sub; 03084 tmp_sub = tmp_ep->sub; 03085 while (tmp_sub) { 03086 mgcp_queue_hangup(tmp_sub); 03087 tmp_sub = tmp_sub->next; 03088 if (tmp_sub == first_sub) 03089 break; 03090 } 03091 } 03092 tmp_ep = tmp_ep->next; 03093 } 03094 } else if (sub->owner) { 03095 mgcp_queue_hangup(sub); 03096 } 03097 transmit_response(sub, "200", req, "OK"); 03098 /* We dont send NTFY or AUEP to wildcard ep */ 03099 if (strcmp(p->name, p->parent->wcardep) != 0) { 03100 transmit_notify_request(sub, ""); 03101 /* Audit endpoint. 03102 Idea is to prevent lost lines due to race conditions 03103 */ 03104 transmit_audit_endpoint(p); 03105 } 03106 } 03107 } else if (!strcasecmp(req->verb, "NTFY")) { 03108 /* Acknowledge and be sure we keep looking for the same things */ 03109 transmit_response(sub, "200", req, "OK"); 03110 /* Notified of an event */ 03111 ev = get_header(req, "O"); 03112 s = strchr(ev, '/'); 03113 if (s) ev = s + 1; 03114 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03115 /* Keep looking for events unless this was a hangup */ 03116 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03117 transmit_notify_request(sub, p->curtone); 03118 } 03119 if (!strcasecmp(ev, "hd")) { 03120 p->hookstate = MGCP_OFFHOOK; 03121 sub->cxmode = MGCP_CX_SENDRECV; 03122 handle_hd_hf(sub, ev); 03123 } else if (!strcasecmp(ev, "hf")) { 03124 /* We can assume we are offhook if we received a hookflash */ 03125 /* First let's just do call wait and ignore threeway */ 03126 /* We're currently in charge */ 03127 if (p->hookstate != MGCP_OFFHOOK) { 03128 /* Cisco c7940 sends hf even if the phone is onhook */ 03129 /* Thanks to point on IRC for pointing this out */ 03130 return -1; 03131 } 03132 /* do not let * conference two down channels */ 03133 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) 03134 return -1; 03135 03136 if (p->callwaiting || p->transfer || p->threewaycalling) { 03137 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03138 p->sub = p->sub->next; 03139 03140 /* transfer control to our next subchannel */ 03141 if (!sub->next->owner) { 03142 /* plave the first call on hold and start up a new call */ 03143 sub->cxmode = MGCP_CX_MUTE; 03144 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03145 transmit_modify_request(sub); 03146 if (sub->owner && ast_bridged_channel(sub->owner)) 03147 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03148 sub->next->cxmode = MGCP_CX_RECVONLY; 03149 handle_hd_hf(sub->next, ev); 03150 } else if (sub->owner && sub->next->owner) { 03151 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03152 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03153 /* We made both calls lets conferenct */ 03154 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", 03155 sub->id, sub->next->id, p->name, p->parent->name); 03156 sub->cxmode = MGCP_CX_CONF; 03157 sub->next->cxmode = MGCP_CX_CONF; 03158 if (ast_bridged_channel(sub->next->owner)) 03159 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03160 transmit_modify_request(sub); 03161 transmit_modify_request(sub->next); 03162 } else { 03163 /* Let's flipflop between calls */ 03164 /* XXX Need to check for state up ??? */ 03165 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03166 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03167 sub->id, sub->next->id, p->name, p->parent->name); 03168 sub->cxmode = MGCP_CX_MUTE; 03169 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03170 transmit_modify_request(sub); 03171 if (ast_bridged_channel(sub->owner)) 03172 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03173 03174 if (ast_bridged_channel(sub->next->owner)) 03175 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03176 03177 handle_hd_hf(sub->next, ev); 03178 } 03179 } else { 03180 /* We've most likely lost one of our calls find an active call and bring it up */ 03181 if (sub->owner) { 03182 p->sub = sub; 03183 } else if (sub->next->owner) { 03184 p->sub = sub->next; 03185 } else { 03186 /* We seem to have lost both our calls */ 03187 /* XXX - What do we do now? */ 03188 return -1; 03189 } 03190 if (ast_bridged_channel(p->sub->owner)) 03191 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03192 p->sub->cxmode = MGCP_CX_SENDRECV; 03193 transmit_modify_request(p->sub); 03194 } 03195 } else { 03196 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03197 p->name, p->parent->name); 03198 } 03199 } else if (!strcasecmp(ev, "hu")) { 03200 p->hookstate = MGCP_ONHOOK; 03201 sub->cxmode = MGCP_CX_RECVONLY; 03202 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03203 /* Do we need to send MDCX before a DLCX ? 03204 if (sub->rtp) { 03205 transmit_modify_request(sub); 03206 } 03207 */ 03208 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03209 /* We're allowed to transfer, we have two avtive calls and */ 03210 /* we made at least one of the calls. Let's try and transfer */ 03211 ast_mutex_lock(&p->sub->next->lock); 03212 res = attempt_transfer(p); 03213 if (res < 0) { 03214 if (p->sub->next->owner) { 03215 sub->next->alreadygone = 1; 03216 mgcp_queue_hangup(sub->next); 03217 } 03218 } else if (res) { 03219 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03220 ast_mutex_unlock(&p->sub->next->lock); 03221 return -1; 03222 } 03223 ast_mutex_unlock(&p->sub->next->lock); 03224 } else { 03225 /* Hangup the current call */ 03226 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03227 if (sub->owner) { 03228 sub->alreadygone = 1; 03229 mgcp_queue_hangup(sub); 03230 } else { 03231 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03232 p->name, p->parent->name, sub->id); 03233 /* Instruct the other side to remove the connection since it apparently * 03234 * still thinks the channel is active. * 03235 * For Cisco IAD2421 /BAK/ */ 03236 transmit_connection_del(sub); 03237 } 03238 } 03239 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03240 p->hidecallerid = 0; 03241 if (p->hascallwaiting && !p->callwaiting) { 03242 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03243 p->callwaiting = -1; 03244 } 03245 if (has_voicemail(p)) { 03246 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03247 transmit_notify_request(sub, "L/vmwi(+)"); 03248 } else { 03249 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03250 transmit_notify_request(sub, "L/vmwi(-)"); 03251 } 03252 } 03253 } else if ((strlen(ev) == 1) && 03254 (((ev[0] >= '0') && (ev[0] <= '9')) || 03255 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03256 (ev[0] == '*') || (ev[0] == '#'))) { 03257 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) { 03258 f.frametype = AST_FRAME_DTMF; 03259 f.subclass = ev[0]; 03260 f.src = "mgcp"; 03261 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03262 mgcp_queue_frame(sub, &f); 03263 ast_mutex_lock(&sub->next->lock); 03264 if (sub->next->owner) 03265 mgcp_queue_frame(sub->next, &f); 03266 ast_mutex_unlock(&sub->next->lock); 03267 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) { 03268 memset(p->curtone, 0, sizeof(p->curtone)); 03269 } 03270 } else { 03271 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; 03272 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; 03273 } 03274 } else if (!strcasecmp(ev, "T")) { 03275 /* Digit timeout -- unimportant */ 03276 } else if (!strcasecmp(ev, "ping")) { 03277 /* ping -- unimportant */ 03278 } else { 03279 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03280 } 03281 } else { 03282 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03283 transmit_response(sub, "510", req, "Unknown verb"); 03284 } 03285 return 0; 03286 }
| 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 2479 of file chan_mgcp.c.
References ast_copy_string(), ast_free, ast_log(), ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, dump_cmd_queues(), find_command(), get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, len(), mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), and transmit_notify_request().
Referenced by mgcpsock_read(), and retrans_pkt().
02481 { 02482 char *c; 02483 struct mgcp_request *req; 02484 struct mgcp_gateway *gw = p->parent; 02485 02486 if (result < 200) { 02487 /* provisional response */ 02488 return; 02489 } 02490 02491 if (p->slowsequence) 02492 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02493 else if (sub) 02494 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02495 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02496 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02497 02498 if (!req) { 02499 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", 02500 gw->name, ident); 02501 return; 02502 } 02503 02504 if (p && (result >= 400) && (result <= 599)) { 02505 switch (result) { 02506 case 401: 02507 p->hookstate = MGCP_OFFHOOK; 02508 break; 02509 case 402: 02510 p->hookstate = MGCP_ONHOOK; 02511 break; 02512 case 406: 02513 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02514 break; 02515 case 407: 02516 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02517 break; 02518 } 02519 if (sub) { 02520 if (sub->owner) { 02521 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02522 result, p->name, p->parent->name, sub ? sub->id:-1); 02523 mgcp_queue_hangup(sub); 02524 } 02525 } else { 02526 if (p->sub->next->owner) { 02527 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02528 result, p->name, p->parent->name, sub ? sub->id:-1); 02529 mgcp_queue_hangup(p->sub); 02530 } 02531 02532 if (p->sub->owner) { 02533 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02534 result, p->name, p->parent->name, sub ? sub->id:-1); 02535 mgcp_queue_hangup(p->sub); 02536 } 02537 02538 dump_cmd_queues(p, NULL); 02539 } 02540 } 02541 02542 if (resp) { 02543 if (req->cmd == MGCP_CMD_CRCX) { 02544 if ((c = get_header(resp, "I"))) { 02545 if (!ast_strlen_zero(c) && sub) { 02546 /* if we are hanging up do not process this conn. */ 02547 if (sub->owner) { 02548 if (!ast_strlen_zero(sub->cxident)) { 02549 if (strcasecmp(c, sub->cxident)) { 02550 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02551 } 02552 } 02553 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02554 if (sub->tmpdest.sin_addr.s_addr) { 02555 transmit_modify_with_sdp(sub, NULL, 0); 02556 } 02557 } else { 02558 /* XXX delete this one 02559 callid and conn id may already be lost. 02560 so the following del conn may have a side effect of 02561 cleaning up the next subchannel */ 02562 transmit_connection_del(sub); 02563 } 02564 } 02565 } 02566 } 02567 02568 if (req->cmd == MGCP_CMD_AUEP) { 02569 /* check stale connection ids */ 02570 if ((c = get_header(resp, "I"))) { 02571 char *v, *n; 02572 int len; 02573 while ((v = get_csv(c, &len, &n))) { 02574 if (len) { 02575 if (strncasecmp(v, p->sub->cxident, len) && 02576 strncasecmp(v, p->sub->next->cxident, len)) { 02577 /* connection id not found. delete it */ 02578 char cxident[80] = ""; 02579 02580 if (len > (sizeof(cxident) - 1)) 02581 len = sizeof(cxident) - 1; 02582 ast_copy_string(cxident, v, len); 02583 ast_verb(3, "Non existing connection id %s on %s@%s \n", 02584 cxident, p->name, gw->name); 02585 transmit_connection_del_w_params(p, NULL, cxident); 02586 } 02587 } 02588 c = n; 02589 } 02590 } 02591 02592 /* Try to determine the hookstate returned from an audit endpoint command */ 02593 if ((c = get_header(resp, "ES"))) { 02594 if (!ast_strlen_zero(c)) { 02595 if (strstr(c, "hu")) { 02596 if (p->hookstate != MGCP_ONHOOK) { 02597 /* XXX cleanup if we think we are offhook XXX */ 02598 if ((p->sub->owner || p->sub->next->owner ) && 02599 p->hookstate == MGCP_OFFHOOK) 02600 mgcp_queue_hangup(sub); 02601 p->hookstate = MGCP_ONHOOK; 02602 02603 /* update the requested events according to the new hookstate */ 02604 transmit_notify_request(p->sub, ""); 02605 02606 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02607 } 02608 } else if (strstr(c, "hd")) { 02609 if (p->hookstate != MGCP_OFFHOOK) { 02610 p->hookstate = MGCP_OFFHOOK; 02611 02612 /* update the requested events according to the new hookstate */ 02613 transmit_notify_request(p->sub, ""); 02614 02615 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02616 } 02617 } 02618 } 02619 } 02620 } 02621 02622 if (resp && resp->lines) { 02623 /* do not process sdp if we are hanging up. this may be a late response */ 02624 if (sub && sub->owner) { 02625 if (!sub->rtp) 02626 start_rtp(sub); 02627 if (sub->rtp) 02628 process_sdp(sub, resp); 02629 } 02630 } 02631 } 02632 02633 ast_free(req); 02634 }
| static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 462 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().
Referenced by do_monitor(), handle_hd_hf(), handle_request(), mgcp_hangup(), and mgcp_request().
00463 { 00464 int new_msgs; 00465 struct ast_event *event; 00466 char *mbox, *cntx; 00467 00468 cntx = mbox = ast_strdupa(p->mailbox); 00469 strsep(&cntx, "@"); 00470 if (ast_strlen_zero(cntx)) 00471 cntx = "default"; 00472 00473 event = ast_event_get_cached(AST_EVENT_MWI, 00474 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 00475 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 00476 AST_EVENT_IE_END); 00477 00478 if (event) { 00479 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 00480 ast_event_destroy(event); 00481 } else 00482 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 00483 00484 return new_msgs; 00485 }
| static int init_req | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_request * | req, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2012 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, and mgcp_endpoint::parent.
Referenced by reqprep().
02013 { 02014 /* Initialize a response */ 02015 if (req->headers || req->len) { 02016 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02017 return -1; 02018 } 02019 req->header[req->headers] = req->data + req->len; 02020 /* check if we need brackets around the gw name */ 02021 if (p->parent->isnamedottedip) 02022 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name); 02023 else 02024 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name); 02025 req->len += strlen(req->header[req->headers]); 02026 if (req->headers < MGCP_MAX_HEADERS) 02027 req->headers++; 02028 else 02029 ast_log(LOG_WARNING, "Out of header space\n"); 02030 return 0; 02031 }
| static int init_resp | ( | struct mgcp_request * | req, | |
| char * | resp, | |||
| struct mgcp_request * | orig, | |||
| char * | resprest | |||
| ) | [static] |
Definition at line 1995 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().
01996 { 01997 /* Initialize a response */ 01998 if (req->headers || req->len) { 01999 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02000 return -1; 02001 } 02002 req->header[req->headers] = req->data + req->len; 02003 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 02004 req->len += strlen(req->header[req->headers]); 02005 if (req->headers < MGCP_MAX_HEADERS) 02006 req->headers++; 02007 else 02008 ast_log(LOG_WARNING, "Out of header space\n"); 02009 return 0; 02010 }
| static int load_module | ( | void | ) | [static] |
load_module: PBX load module - initialization ---
Definition at line 4278 of file chan_mgcp.c.
References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().
04279 { 04280 if (!(sched = sched_context_create())) { 04281 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 04282 return AST_MODULE_LOAD_FAILURE; 04283 } 04284 04285 if (!(io = io_context_create())) { 04286 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 04287 sched_context_destroy(sched); 04288 return AST_MODULE_LOAD_FAILURE; 04289 } 04290 04291 if (reload_config(0)) 04292 return AST_MODULE_LOAD_DECLINE; 04293 04294 /* Make sure we can register our mgcp channel type */ 04295 if (ast_channel_register(&mgcp_tech)) { 04296 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); 04297 io_context_destroy(io); 04298 sched_context_destroy(sched); 04299 return AST_MODULE_LOAD_FAILURE; 04300 } 04301 04302 ast_rtp_proto_register(&mgcp_rtp); 04303 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04304 04305 /* And start the monitor for the first time */ 04306 restart_monitor(); 04307 04308 return AST_MODULE_LOAD_SUCCESS; 04309 }
| static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1203 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, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01204 { 01205 int res = 0; 01206 struct mgcp_subchannel *sub = ast->tech_pvt; 01207 struct mgcp_endpoint *p = sub->parent; 01208 01209 ast_mutex_lock(&sub->lock); 01210 sub->cxmode = MGCP_CX_SENDRECV; 01211 if (!sub->rtp) { 01212 start_rtp(sub); 01213 } else { 01214 transmit_modify_request(sub); 01215 } 01216 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", 01217 ast->name, p->name, p->parent->name, sub->id); 01218 if (ast->_state != AST_STATE_UP) { 01219 ast_setstate(ast, AST_STATE_UP); 01220 ast_debug(1, "mgcp_answer(%s)\n", ast->name); 01221 transmit_notify_request(sub, ""); 01222 transmit_modify_request(sub); 01223 } 01224 ast_mutex_unlock(&sub->lock); 01225 return res; 01226 }
| static int mgcp_call | ( | struct ast_channel * | ast, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 843 of file chan_mgcp.c.
References ast_channel::_state, AST_CONTROL_RINGING, ast_copy_string(), AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_verb, mgcp_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, and ast_channel::varshead.
00844 { 00845 int res; 00846 struct mgcp_endpoint *p; 00847 struct mgcp_subchannel *sub; 00848 char tone[50] = ""; 00849 const char *distinctive_ring = NULL; 00850 struct varshead *headp; 00851 struct ast_var_t *current; 00852 00853 if (mgcpdebug) { 00854 ast_verb(3, "MGCP mgcp_call(%s)\n", ast->name); 00855 } 00856 sub = ast->tech_pvt; 00857 p = sub->parent; 00858 headp = &ast->varshead; 00859 AST_LIST_TRAVERSE(headp,current,entries) { 00860 /* Check whether there is an ALERT_INFO variable */ 00861 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { 00862 distinctive_ring = ast_var_value(current); 00863 } 00864 } 00865 00866 ast_mutex_lock(&sub->lock); 00867 switch (p->hookstate) { 00868 case MGCP_OFFHOOK: 00869 if (!ast_strlen_zero(distinctive_ring)) { 00870 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); 00871 if (mgcpdebug) { 00872 ast_verb(3, "MGCP distinctive callwait %s\n", tone); 00873 } 00874 } else { 00875 ast_copy_string(tone, "L/wt", sizeof(tone)); 00876 if (mgcpdebug) { 00877 ast_verb(3, "MGCP normal callwait %s\n", tone); 00878 } 00879 } 00880 break; 00881 case MGCP_ONHOOK: 00882 default: 00883 if (!ast_strlen_zero(distinctive_ring)) { 00884 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); 00885 if (mgcpdebug) { 00886 ast_verb(3, "MGCP distinctive ring %s\n", tone); 00887 } 00888 } else { 00889 ast_copy_string(tone, "L/rg", sizeof(tone)); 00890 if (mgcpdebug) { 00891 ast_verb(3, "MGCP default ring\n"); 00892 } 00893 } 00894 break; 00895 } 00896 00897 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00898 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name); 00899 ast_mutex_unlock(&sub->lock); 00900 return -1; 00901 } 00902 00903 res = 0; 00904 sub->outgoing = 1; 00905 sub->cxmode = MGCP_CX_RECVONLY; 00906 if (p->type == TYPE_LINE) { 00907 if (!sub->rtp) { 00908 start_rtp(sub); 00909 } else { 00910 transmit_modify_request(sub); 00911 } 00912 00913 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00914 /* try to prevent a callwait from disturbing the other connection */ 00915 sub->next->cxmode = MGCP_CX_RECVONLY; 00916 transmit_modify_request(sub->next); 00917 } 00918 00919 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name); 00920 ast_setstate(ast, AST_STATE_RINGING); 00921 00922 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00923 /* Put the connection back in sendrecv */ 00924 sub->next->cxmode = MGCP_CX_SENDRECV; 00925 transmit_modify_request(sub->next); 00926 } 00927 } else { 00928 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); 00929 res = -1; 00930 } 00931 ast_mutex_unlock(&sub->lock); 00932 ast_queue_control(ast, AST_CONTROL_RINGING); 00933 return res; 00934 }
| static int mgcp_devicestate | ( | void * | data | ) | [static] |
mgcp_devicestate: channel callback for device status monitoring
| data | tech/resource name of MGCP device to query |
Callback for device state management in channel subsystem to obtain device status (up/down) of a specific MGCP endpoint
Definition at line 1372 of file chan_mgcp.c.
References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, and mgcp_gateway::next.
01373 { 01374 struct mgcp_gateway *g; 01375 struct mgcp_endpoint *e = NULL; 01376 char *tmp, *endpt, *gw; 01377 int ret = AST_DEVICE_INVALID; 01378 01379 endpt = ast_strdupa(data); 01380 if ((tmp = strchr(endpt, '@'))) { 01381 *tmp++ = '\0'; 01382 gw = tmp; 01383 } else 01384 goto error; 01385 01386 ast_mutex_lock(&gatelock); 01387 g = gateways; 01388 while (g) { 01389 if (strcasecmp(g->name, gw) == 0) { 01390 e = g->endpoints; 01391 break; 01392 } 01393 g = g->next; 01394 } 01395 01396 if (!e) 01397 goto error; 01398 01399 while (e) { 01400 if (strcasecmp(e->name, endpt) == 0) 01401 break; 01402 e = e->next; 01403 } 01404 01405 if (!e) 01406 goto error; 01407 01408 /* 01409 * As long as the gateway/endpoint is valid, we'll 01410 * assume that the device is available and its state 01411 * can be tracked. 01412 */ 01413 ret = AST_DEVICE_UNKNOWN; 01414 01415 error: 01416 ast_mutex_unlock(&gatelock); 01417 return ret; 01418 }
| static int mgcp_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 1299 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_subchannel::owner, and ast_channel::tech_pvt.
01300 { 01301 struct mgcp_subchannel *sub = newchan->tech_pvt; 01302 01303 ast_mutex_lock(&sub->lock); 01304 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name); 01305 if (sub->owner != oldchan) { 01306 ast_mutex_unlock(&sub->lock); 01307 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01308 return -1; 01309 } 01310 sub->owner = newchan; 01311 ast_mutex_unlock(&sub->lock); 01312 return 0; 01313 }
| static enum ast_rtp_get_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp ** | rtp | |||
| ) | [static] |
Definition at line 3970 of file chan_mgcp.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, mgcp_endpoint::canreinvite, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
03971 { 03972 struct mgcp_subchannel *sub = NULL; 03973 03974 if (!(sub = chan->tech_pvt) || !(sub->rtp)) 03975 return AST_RTP_GET_FAILED; 03976 03977 *rtp = sub->rtp; 03978 03979 if (sub->parent->canreinvite) 03980 return AST_RTP_TRY_NATIVE; 03981 else 03982 return AST_RTP_TRY_PARTIAL; 03983 }
| static int mgcp_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 936 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_debug, ast_dsp_free(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
00937 { 00938 struct mgcp_subchannel *sub = ast->tech_pvt; 00939 struct mgcp_endpoint *p = sub->parent; 00940 00941 ast_debug(1, "mgcp_hangup(%s)\n", ast->name); 00942 if (!ast->tech_pvt) { 00943 ast_debug(1, "Asked to hangup channel not connected\n"); 00944 return 0; 00945 } 00946 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) { 00947 ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n"); 00948 return 0; 00949 } 00950 ast_mutex_lock(&sub->lock); 00951 if (mgcpdebug) { 00952 ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name); 00953 } 00954 00955 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) { 00956 /* check whether other channel is active. */ 00957 if (!sub->next->owner) { 00958 if (p->dtmfmode & MGCP_DTMF_HYBRID) 00959 p->dtmfmode &= ~MGCP_DTMF_INBAND; 00960 if (mgcpdebug) { 00961 ast_verb(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name); 00962 } 00963 ast_dsp_free(p->dsp); 00964 p->dsp = NULL; 00965 } 00966 } 00967 00968 sub->owner = NULL; 00969 if (!ast_strlen_zero(sub->cxident)) { 00970 transmit_connection_del(sub); 00971 } 00972 sub->cxident[0] = '\0'; 00973 if ((sub == p->sub) && sub->next->owner) { 00974 if (p->hookstate == MGCP_OFFHOOK) { 00975 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00976 transmit_notify_request_with_callerid(p->sub, "L/wt", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name); 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 transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name); 00985 } 00986 } 00987 00988 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) { 00989 transmit_notify_request(sub, "L/v"); 00990 } else if (p->hookstate == MGCP_OFFHOOK) { 00991 transmit_notify_request(sub, "L/ro"); 00992 } else { 00993 transmit_notify_request(sub, ""); 00994 } 00995 00996 ast->tech_pvt = NULL; 00997 sub->alreadygone = 0; 00998 sub->outgoing = 0; 00999 sub->cxmode = MGCP_CX_INACTIVE; 01000 sub->callid[0] = '\0'; 01001 if (p) { 01002 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 01003 } 01004 /* Reset temporary destination */ 01005 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 01006 if (sub->rtp) { 01007 ast_rtp_destroy(sub->rtp); 01008 sub->rtp = NULL; 01009 } 01010 01011 ast_module_unref(ast_module_info->self); 01012 01013 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) { 01014 p->hidecallerid = 0; 01015 if (p->hascallwaiting && !p->callwaiting) { 01016 ast_verb(3, "Enabling call waiting on %s\n", ast->name); 01017 p->callwaiting = -1; 01018 } 01019 if (has_voicemail(p)) { 01020 if (mgcpdebug) { 01021 ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 01022 ast->name, p->name, p->parent->name); 01023 } 01024 transmit_notify_request(sub, "L/vmwi(+)"); 01025 } else { 01026 if (mgcpdebug) { 01027 ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 01028 ast->name, p->name, p->parent->name); 01029 } 01030 transmit_notify_request(sub, "L/vmwi(-)"); 01031 } 01032 } 01033 ast_mutex_unlock(&sub->lock); 01034 return 0; 01035 }
| static int mgcp_indicate | ( | struct ast_channel * | ast, | |
| int | ind, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 1452 of file chan_mgcp.c.
References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_new_source(), ast_verb, control2str(), mgcp_subchannel::lock, LOG_WARNING, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_notify_request().
01453 { 01454 struct mgcp_subchannel *sub = ast->tech_pvt; 01455 int res = 0; 01456 01457 if (mgcpdebug) { 01458 ast_verb(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", 01459 ind, control2str(ind), ast->name); 01460 } 01461 ast_mutex_lock(&sub->lock); 01462 switch(ind) { 01463 case AST_CONTROL_RINGING: 01464 #ifdef DLINK_BUGGY_FIRMWARE 01465 transmit_notify_request(sub, "rt"); 01466 #else 01467 transmit_notify_request(sub, "G/rt"); 01468 #endif 01469 break; 01470 case AST_CONTROL_BUSY: 01471 transmit_notify_request(sub, "L/bz"); 01472 break; 01473 case AST_CONTROL_CONGESTION: 01474 transmit_notify_request(sub, "G/cg"); 01475 break; 01476 case AST_CONTROL_HOLD: 01477 ast_moh_start(ast, data, NULL); 01478 break; 01479 case AST_CONTROL_UNHOLD: 01480 ast_moh_stop(ast); 01481 break; 01482 case AST_CONTROL_SRCUPDATE: 01483 ast_rtp_new_source(sub->rtp); 01484 break; 01485 case -1: 01486 transmit_notify_request(sub, ""); 01487 break; 01488 default: 01489 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); 01490 res = -1; 01491 } 01492 ast_mutex_unlock(&sub->lock); 01493 return res; 01494 }
| static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, | |
| int | state | |||
| ) | [static, read] |
Definition at line 1496 of file chan_mgcp.c.
References mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, ast_channel::exten, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by handle_hd_hf(), and mgcp_request().
01497 { 01498 struct ast_channel *tmp; 01499 struct mgcp_endpoint *i = sub->parent; 01500 int fmt; 01501 01502 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); 01503 if (tmp) { 01504 tmp->tech = &mgcp_tech; 01505 tmp->nativeformats = i->capability; 01506 if (!tmp->nativeformats) 01507 tmp->nativeformats = capability; 01508 fmt = ast_best_codec(tmp->nativeformats); 01509 ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); 01510 if (sub->rtp) 01511 ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp)); 01512 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { 01513 i->dsp = ast_dsp_new(); 01514 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); 01515 /* this is to prevent clipping of dtmf tones during dsp processing */ 01516 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); 01517 } else { 01518 i->dsp = NULL; 01519 } 01520 if (state == AST_STATE_RING) 01521 tmp->rings = 1; 01522 tmp->writeformat = fmt; 01523 tmp->rawwriteformat = fmt; 01524 tmp->readformat = fmt; 01525 tmp->rawreadformat = fmt; 01526 tmp->tech_pvt = sub; 01527 if (!ast_strlen_zero(i->language)) 01528 ast_string_field_set(tmp, language, i->language); 01529 if (!ast_strlen_zero(i->accountcode)) 01530 ast_string_field_set(tmp, accountcode, i->accountcode); 01531 if (i->amaflags) 01532 tmp->amaflags = i->amaflags; 01533 sub->owner = tmp; 01534 ast_module_ref(ast_module_info->self); 01535 tmp->callgroup = i->callgroup; 01536 tmp->pickupgroup = i->pickupgroup; 01537 ast_string_field_set(tmp, call_forward, i->call_forward); 01538 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 01539 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 01540 01541 /* Don't use ast_set_callerid() here because it will 01542 * generate a needless NewCallerID event */ 01543 tmp->cid.cid_ani = ast_strdup(i->cid_num); 01544 01545 if (!i->adsi) 01546 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01547 tmp->priority = 1; 01548 if (sub->rtp) 01549 ast_jb_configure(tmp, &global_jbconf); 01550 if (state != AST_STATE_DOWN) { 01551 if (ast_pbx_start(tmp)) { 01552 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 01553 ast_hangup(tmp); 01554 tmp = NULL; 01555 } 01556 } 01557 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", 01558 tmp->name, ast_state2str(state)); 01559 } else { 01560 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01561 } 01562 return tmp; 01563 }
| static int mgcp_postrequest | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub, | |||
| char * | data, | |||
| int | len, | |||
| unsigned int | seqno | |||
| ) | [static] |
Definition at line 693 of file chan_mgcp.c.
References __mgcp_xmit(), ast_free, ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_tvnow(), DEFAULT_RETRANS, msg, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, mgcp_endpoint::next, mgcp_endpoint::parent, retrans_pkt(), and mgcp_gateway::retransid.
Referenced by find_command(), and send_request().
00695 { 00696 struct mgcp_message *msg; 00697 struct mgcp_message *cur; 00698 struct mgcp_gateway *gw; 00699 struct timeval now; 00700 00701 msg = ast_malloc(sizeof(*msg) + len); 00702 if (!msg) { 00703 return -1; 00704 } 00705 gw = ((p && p->parent) ? p->parent : NULL); 00706 if (!gw) { 00707 ast_free(msg); 00708 return -1; 00709 } 00710 /* SC 00711 time(&t); 00712 if (gw->messagepending && (gw->lastouttime + 20 < t)) { 00713 ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d, lastouttime: %ld, now: %ld. Dumping pending queue\n", 00714 gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t); 00715 dump_queue(sub->parent); 00716 } 00717 */ 00718 msg->owner_sub = sub; 00719 msg->owner_ep = p; 00720 msg->seqno = seqno; 00721 msg->next = NULL; 00722 msg->len = len; 00723 msg->retrans = 0; 00724 memcpy(msg->buf, data, msg->len); 00725 00726 ast_mutex_lock(&gw->msgs_lock); 00727 cur = gw->msgs; 00728 if (cur) { 00729 while(cur->next) 00730 cur = cur->next; 00731 cur->next = msg; 00732 } else { 00733 gw->msgs = msg; 00734 } 00735 00736 now = ast_tvnow(); 00737 msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS; 00738 00739 if (gw->retransid == -1) 00740 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw); 00741 ast_mutex_unlock(&gw->msgs_lock); 00742 /* SC 00743 if (!gw->messagepending) { 00744 gw->messagepending = 1; 00745 gw->lastout = seqno; 00746 gw->lastouttime = t; 00747 */ 00748 __mgcp_xmit(gw, msg->buf, msg->len); 00749 /* XXX Should schedule retransmission XXX */ 00750 /* SC 00751 } else 00752 ast_debug(1, "Deferring transmission of transaction %d\n", seqno); 00753 */ 00754 return 0; 00755 }
| static void mgcp_queue_control | ( | struct mgcp_subchannel * | sub, | |
| int | control | |||
| ) | [static] |
Definition at line 624 of file chan_mgcp.c.
References AST_FRAME_CONTROL, mgcp_queue_frame(), and ast_frame::subclass.
Referenced by handle_hd_hf().
00625 { 00626 struct ast_frame f = { AST_FRAME_CONTROL, }; 00627 f.subclass = control; 00628 return mgcp_queue_frame(sub, &f); 00629 }
| static void mgcp_queue_frame | ( | struct mgcp_subchannel * | sub, | |
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 592 of file chan_mgcp.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.
Referenced by handle_request(), and mgcp_queue_control().
00593 { 00594 for(;;) { 00595 if (sub->owner) { 00596 if (!ast_channel_trylock(sub->owner)) { 00597 ast_queue_frame(sub->owner, f); 00598 ast_channel_unlock(sub->owner); 00599 break; 00600 } else { 00601 DEADLOCK_AVOIDANCE(&sub->lock); 00602 } 00603 } else 00604 break; 00605 } 00606 }
| static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 608 of file chan_mgcp.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.
Referenced by attempt_transfer(), destroy_endpoint(), handle_request(), and handle_response().
00609 { 00610 for(;;) { 00611 if (sub->owner) { 00612 if (!ast_channel_trylock(sub->owner)) { 00613 ast_queue_hangup(sub->owner); 00614 ast_channel_unlock(sub->owner); 00615 break; 00616 } else { 00617 DEADLOCK_AVOIDANCE(&sub->lock); 00618 } 00619 } else 00620 break; 00621 } 00622 }
| static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1259 of file chan_mgcp.c.
References ast_mutex_lock(), ast_mutex_unlock(), f, mgcp_subchannel::lock, mgcp_rtp_read(), and ast_channel::tech_pvt.
01260 { 01261 struct ast_frame *f; 01262 struct mgcp_subchannel *sub = ast->tech_pvt; 01263 ast_mutex_lock(&sub->lock); 01264 f = mgcp_rtp_read(sub); 01265 ast_mutex_unlock(&sub->lock); 01266 return f; 01267 }
| static char * mgcp_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4311 of file chan_mgcp.c.
References ast_cli_args::argc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, LOG_WARNING, mgcp_reload_lock, restart_monitor(), and ast_cli_entry::usage.
Referenced by reload(), and unload_module().
04312 { 04313 static int deprecated = 0; 04314 04315 if (e) { 04316 switch (cmd) { 04317 case CLI_INIT: 04318 e->command = "mgcp reload"; 04319 e->usage = 04320 "Usage: mgcp reload\n" 04321 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; 04322 return NULL; 04323 case CLI_GENERATE: 04324 return NULL; 04325 } 04326 } 04327 04328 if (!deprecated && a && a->argc > 0) { 04329 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); 04330 deprecated = 1; 04331 } 04332 04333 ast_mutex_lock(&mgcp_reload_lock); 04334 if (mgcp_reloading) { 04335 ast_verbose("Previous mgcp reload not yet done\n"); 04336 } else 04337 mgcp_reloading = 1; 04338 ast_mutex_unlock(&mgcp_reload_lock); 04339 restart_monitor(); 04340 return CLI_SUCCESS; 04341 }
| static struct ast_channel * mgcp_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 3524 of file chan_mgcp.c.
References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, mgcp_endpoint::dnd, find_subchannel_and_lock(), has_voicemail(), mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), MGCP_ONHOOK, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), and transmit_notify_request().
03525 { 03526 int oldformat; 03527 struct mgcp_subchannel *sub; 03528 struct ast_channel *tmpc = NULL; 03529 char tmp[256]; 03530 char *dest = data; 03531 03532 oldformat = format; 03533 format &= capability; 03534 if (!format) { 03535 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); 03536 return NULL; 03537 } 03538 ast_copy_string(tmp, dest, sizeof(tmp)); 03539 if (ast_strlen_zero(tmp)) { 03540 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); 03541 return NULL; 03542 } 03543 sub = find_subchannel_and_lock(tmp, 0, NULL); 03544 if (!sub) { 03545 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); 03546 *cause = AST_CAUSE_UNREGISTERED; 03547 return NULL; 03548 } 03549 03550 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); 03551 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 03552 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); 03553 /* Must be busy */ 03554 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || 03555 ((!sub->parent->callwaiting) && (sub->owner)) || 03556 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { 03557 if (sub->parent->hookstate == MGCP_ONHOOK) { 03558 if (has_voicemail(sub->parent)) { 03559 transmit_notify_request(sub,"L/vmwi(+)"); 03560 } else { 03561 transmit_notify_request(sub,"L/vmwi(-)"); 03562 } 03563 } 03564 *cause = AST_CAUSE_BUSY; 03565 ast_mutex_unlock(&sub->lock); 03566 return NULL; 03567 } 03568 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN); 03569 ast_mutex_unlock(&sub->lock); 03570 if (!tmpc) 03571 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); 03572 restart_monitor(); 03573 return tmpc; 03574 }
| static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static, read] |
Definition at line 1228 of file chan_mgcp.c.
References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, f, ast_frame::frametype, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, ast_frame::subclass, and ast_channel::writeformat.
Referenced by mgcp_read().
01229 { 01230 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ 01231 struct ast_frame *f; 01232 01233 f = ast_rtp_read(sub->rtp); 01234 /* Don't send RFC2833 if we're not supposed to */ 01235 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) 01236 return &ast_null_frame; 01237 if (sub->owner) { 01238 /* We already hold the channel lock */ 01239 if (f->frametype == AST_FRAME_VOICE) { 01240 if (f->subclass != sub->owner->nativeformats) { 01241 ast_debug(1, "Oooh, format changed to %d\n", f->subclass); 01242 sub->owner->nativeformats = f->subclass; 01243 ast_set_read_format(sub->owner, sub->owner->readformat); 01244 ast_set_write_format(sub->owner, sub->owner->writeformat); 01245 } 01246 /* Courtesy fearnor aka alex@pilosoft.com */ 01247 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { 01248 #if 0 01249 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); 01250 #endif 01251 f = ast_dsp_process(sub->owner, sub->parent->dsp, f); 01252 } 01253 } 01254 } 01255 return f; 01256 }
| static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1315 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
01316 { 01317 struct mgcp_subchannel *sub = ast->tech_pvt; 01318 struct mgcp_endpoint *p = sub->parent; 01319 int res = 0; 01320 01321 ast_mutex_lock(&sub->lock); 01322 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01323 ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n"); 01324 res = -1; /* Let asterisk play inband indications */ 01325 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01326 ast_log(LOG_DEBUG, "Sending DTMF using RFC2833"); 01327 ast_rtp_senddigit_begin(sub->rtp, digit); 01328 } else { 01329 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01330 } 01331 ast_mutex_unlock(&sub->lock); 01332 01333 return res; 01334 }
| static int mgcp_senddigit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1336 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_end(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_notify_request().
01337 { 01338 struct mgcp_subchannel *sub = ast->tech_pvt; 01339 struct mgcp_endpoint *p = sub->parent; 01340 int res = 0; 01341 char tmp[4]; 01342 01343 ast_mutex_lock(&sub->lock); 01344 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01345 ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n"); 01346 res = -1; /* Tell Asterisk to stop inband indications */ 01347 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01348 ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n"); 01349 tmp[0] = 'D'; 01350 tmp[1] = '/'; 01351 tmp[2] = digit; 01352 tmp[3] = '\0'; 01353 transmit_notify_request(sub, tmp); 01354 ast_rtp_senddigit_end(sub->rtp, digit); 01355 } else { 01356 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01357 } 01358 ast_mutex_unlock(&sub->lock); 01359 01360 return res; 01361 }
| static int mgcp_set_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp * | rtp, | |||
| struct ast_rtp * | vrtp, | |||
| struct ast_rtp * | trtp, | |||
| int | codecs, | |||
| int | nat_active | |||
| ) | [static] |
Definition at line 3985 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_channel::tech_pvt, and transmit_modify_with_sdp().
03986 { 03987 /* XXX Is there such thing as video support with MGCP? XXX */ 03988 struct mgcp_subchannel *sub; 03989 sub = chan->tech_pvt; 03990 if (sub && !sub->alreadygone) { 03991 transmit_modify_with_sdp(sub, rtp, codecs); 03992 return 0; 03993 } 03994 return -1; 03995 }
| static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2663 of file chan_mgcp.c.
References ast_bridged_channel(), ast_canmatch_extension(), ast_copy_string(), ast_db_put(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strlen_zero(), ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, chan, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, ast_callerid::cid_num, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), ast_channel::tech_pvt, and transmit_notify_request().
Referenced by handle_hd_hf().
02664 { 02665 struct ast_channel *chan = data; 02666 struct mgcp_subchannel *sub = chan->tech_pvt; 02667 struct mgcp_endpoint *p = sub->parent; 02668 /* char exten[AST_MAX_EXTENSION] = ""; */ 02669 int len = 0; 02670 int timeout = firstdigittimeout; 02671 int res= 0; 02672 int getforward = 0; 02673 int loop_pause = 100; 02674 02675 len = strlen(p->dtmf_buf); 02676 02677 while(len < AST_MAX_EXTENSION-1) { 02678 res = 1; /* Assume that we will get a digit */ 02679 while (strlen(p->dtmf_buf) == len){ 02680 ast_safe_sleep(chan, loop_pause); 02681 timeout -= loop_pause; 02682 if (timeout <= 0){ 02683 res = 0; 02684 break; 02685 } 02686 res = 1; 02687 } 02688 02689 timeout = 0; 02690 len = strlen(p->dtmf_buf); 02691 02692 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) { 02693 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02694 ast_indicate(chan, -1); 02695 } else { 02696 /* XXX Redundant? We should already be playing dialtone */ 02697 /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02698 transmit_notify_request(sub, "L/dl"); 02699 } 02700 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02701 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02702 if (getforward) { 02703 /* Record this as the forwarding extension */ 02704 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 02705 ast_verb(3, "Setting call forward to '%s' on channel %s\n", 02706 p->call_forward, chan->name); 02707 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02708 transmit_notify_request(sub, "L/sl"); 02709 if (res) 02710 break; 02711 usleep(500000); 02712 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02713 ast_indicate(chan, -1); 02714 sleep(1); 02715 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02716 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02717 transmit_notify_request(sub, "L/dl"); 02718 len = 0; 02719 getforward = 0; 02720 } else { 02721 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02722 ast_indicate(chan, -1); 02723 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten)); 02724 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02725 ast_set_callerid(chan, 02726 p->hidecallerid ? "" : p->cid_num, 02727 p->hidecallerid ? "" : p->cid_name, 02728 chan->cid.cid_ani ? NULL : p->cid_num); 02729 ast_setstate(chan, AST_STATE_RING); 02730 /*dahdi_enable_ec(p);*/ 02731 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 02732 p->dtmfmode |= MGCP_DTMF_INBAND; 02733 ast_indicate(chan, -1); 02734 } 02735 res = ast_pbx_run(chan); 02736 if (res) { 02737 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 02738 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 02739 /*transmit_notify_request(p, "nbz", 1);*/ 02740 transmit_notify_request(sub, "G/cg"); 02741 } 02742 return NULL; 02743 } 02744 } else { 02745 /* It's a match, but they just typed a digit, and there is an ambiguous match, 02746 so just set the timeout to matchdigittimeout and wait some more */ 02747 timeout = matchdigittimeout; 02748 } 02749 } else if (res == 0) { 02750 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 02751 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 02752 transmit_notify_request(sub, "G/cg"); 02753 /*dahdi_wait_event(p->subs[index].zfd);*/ 02754 ast_hangup(chan); 02755 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02756 return NULL; 02757 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { 02758 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 02759 /* Disable call waiting if enabled */ 02760 p->callwaiting = 0; 02761 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02762 transmit_notify_request(sub, "L/sl"); 02763 len = 0; 02764 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02765 timeout = firstdigittimeout; 02766 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { 02767 /* Scan all channels and see if any there 02768 * ringing channqels with that have call groups 02769 * that equal this channels pickup group 02770 */ 02771 if (ast_pickup_call(chan)) { 02772 ast_log(LOG_WARNING, "No call pickup possible...\n"); 02773 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 02774 transmit_notify_request(sub, "G/cg"); 02775 } 02776 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02777 ast_hangup(chan); 02778 return NULL; 02779 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { 02780 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 02781 /* Disable Caller*ID if enabled */ 02782 p->hidecallerid = 1; 02783 ast_set_callerid(chan, "", "", NULL); 02784 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02785 transmit_notify_request(sub, "L/sl"); 02786 len = 0; 02787 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02788 timeout = firstdigittimeout; 02789 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { 02790 res = 0; 02791 if (!ast_strlen_zero(p->lastcallerid)) { 02792 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language); 02793 } 02794 if (!res) 02795 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02796 transmit_notify_request(sub, "L/sl"); 02797 break; 02798 } else if (!strcmp(p->dtmf_buf, "*78")) { 02799 /* Do not disturb */ 02800 ast_verb(3, "Enabled DND on channel %s\n", chan->name); 02801 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02802 transmit_notify_request(sub, "L/sl"); 02803 p->dnd = 1; 02804 getforward = 0; 02805 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02806 len = 0; 02807 } else if (!strcmp(p->dtmf_buf, "*79")) { 02808 /* Do not disturb */ 02809 ast_verb(3, "Disabled DND on channel %s\n", chan->name); 02810 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02811 transmit_notify_request(sub, "L/sl"); 02812 p->dnd = 0; 02813 getforward = 0; 02814 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02815 len = 0; 02816 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { 02817 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02818 transmit_notify_request(sub, "L/sl"); 02819 getforward = 1; 02820 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02821 len = 0; 02822 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { 02823 ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name); 02824 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02825 transmit_notify_request(sub, "L/sl"); 02826 memset(p->call_forward, 0, sizeof(p->call_forward)); 02827 getforward = 0; 02828 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02829 len = 0; 02830 } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) && 02831 sub->next->owner && ast_bridged_channel(sub->next->owner)) { 02832 /* This is a three way call, the main call being a real channel, 02833 and we're parking the first call. */ 02834 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL); 02835 ast_verb(3, "Parking call to '%s'\n", chan->name); 02836 break; 02837 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { 02838 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); 02839 res = ast_db_put("blacklist", p->lastcallerid, "1"); 02840 if (!res) { 02841 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02842 transmit_notify_request(sub, "L/sl"); 02843 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02844 len = 0; 02845 } 02846 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { 02847 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 02848 /* Enable Caller*ID if enabled */ 02849 p->hidecallerid = 0; 02850 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 02851 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02852 transmit_notify_request(sub, "L/sl"); 02853 len = 0; 02854 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02855 timeout = firstdigittimeout; 02856 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) && 02857 ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 02858 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context); 02859 break; 02860 } 02861 if (!timeout) 02862 timeout = gendigittimeout; 02863 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf)) 02864 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02865 ast_indicate(chan, -1); 02866 } 02867 #if 0 02868 for (;;) { 02869 res = ast_waitfordigit(chan, to); 02870 if (!res) { 02871 ast_debug(1, "Timeout...\n"); 02872 break; 02873 } 02874 if (res < 0) { 02875 ast_debug(1, "Got hangup...\n"); 02876 ast_hangup(chan); 02877 break; 02878 } 02879 exten[pos++] = res; 02880 if (!ast_ignore_pattern(chan->context, exten)) 02881 ast_indicate(chan, -1); 02882 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { 02883 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 02884 to = 3000; 02885 else 02886 to = 8000; 02887 } else 02888 break; 02889 } 02890 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { 02891 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); 02892 if (!p->rtp) { 02893 start_rtp(p); 02894 } 02895 ast_setstate(chan, AST_STATE_RING); 02896 chan->rings = 1; 02897 if (ast_pbx_run(chan)) { 02898 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); 02899 } else { 02900 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02901 return NULL; 02902 } 02903 } 02904 #endif 02905 ast_hangup(chan); 02906 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02907 return NULL; 02908 }
| static int mgcp_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 1269 of file chan_mgcp.c.
References AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.
01270 { 01271 struct mgcp_subchannel *sub = ast->tech_pvt; 01272 int res = 0; 01273 if (frame->frametype != AST_FRAME_VOICE) { 01274 if (frame->frametype == AST_FRAME_IMAGE) 01275 return 0; 01276 else { 01277 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); 01278 return 0; 01279 } 01280 } else { 01281 if (!(frame->subclass & ast->nativeformats)) { 01282 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 01283 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat); 01284 return -1; 01285 } 01286 } 01287 if (sub) { 01288 ast_mutex_lock(&sub->lock); 01289 if ((sub->parent->sub == sub) || !sub->parent->singlepath) { 01290 if (sub->rtp) { 01291 res = ast_rtp_write(sub->rtp, frame); 01292 } 01293 } 01294 ast_mutex_unlock(&sub->lock); 01295 } 01296 return res; 01297 }
| static int mgcpsock_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | ignore | |||
| ) | [static] |
Definition at line 3320 of file chan_mgcp.c.
References ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL, ast_strlen_zero(), ast_verbose, mgcp_request::data, mgcp_request::endpoint, errno, find_and_retrans(), find_subchannel_and_lock(), handle_request(), handle_response(), mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, len(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_subchannel::parent, parse(), mgcp_gateway::retransid, mgcp_message::seqno, mgcp_request::verb, and mgcp_request::version.
Referenced by do_monitor().
03321 { 03322 struct mgcp_request req; 03323 struct sockaddr_in sin; 03324 struct mgcp_subchannel *sub; 03325 int res; 03326 socklen_t len; 03327 int result; 03328 int ident; 03329 len = sizeof(sin); 03330 memset(&req, 0, sizeof(req)); 03331 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 03332 if (res < 0) { 03333 if (errno != ECONNREFUSED) 03334 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 03335 return 1; 03336 } 03337 req.data[res] = '\0'; 03338 req.len = res; 03339 if (mgcpdebug) { 03340 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 03341 } 03342 parse(&req); 03343 if (req.headers < 1) { 03344 /* Must have at least one header */ 03345 return 1; 03346 } 03347 if (ast_strlen_zero(req.identifier)) { 03348 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); 03349 return 1; 03350 } 03351 03352 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { 03353 /* Try to find who this message is for, if it's important */ 03354 sub = find_subchannel_and_lock(NULL, ident, &sin); 03355 if (sub) { 03356 struct mgcp_gateway *gw = sub->parent->parent; 03357 struct mgcp_message *cur, *prev; 03358 03359 ast_mutex_unlock(&sub->lock); 03360 ast_mutex_lock(&gw->msgs_lock); 03361 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 03362 if (cur->seqno == ident) { 03363 ast_debug(1, "Got response back on transaction %d\n", ident); 03364 if (prev) 03365 prev->next = cur->next; 03366 else 03367 gw->msgs = cur->next; 03368 break; 03369 } 03370 } 03371 03372 /* stop retrans timer if the queue is empty */ 03373 if (!gw->msgs) { 03374 AST_SCHED_DEL(sched, gw->retransid); 03375 } 03376 03377 ast_mutex_unlock(&gw->msgs_lock); 03378 if (cur) { 03379 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); 03380 ast_free(cur); 03381 return 1; 03382 } 03383 03384 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 03385 gw->name, ident); 03386 } 03387 } else { 03388 if (ast_strlen_zero(req.endpoint) || 03389 ast_strlen_zero(req.version) || 03390 ast_strlen_zero(req.verb)) { 03391 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); 03392 return 1; 03393 } 03394 /* Process request, with iflock held */ 03395 sub = find_subchannel_and_lock(req.endpoint, 0, &sin); 03396 if (sub) { 03397 /* look first to find a matching response in the queue */ 03398 if (!find_and_retrans(sub, &req)) 03399 /* pass the request off to the currently mastering subchannel */ 03400 handle_request(sub, &req, &sin); 03401 ast_mutex_unlock(&sub->lock); 03402 } 03403 } 03404 return 1; 03405 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 454 of file chan_mgcp.c.
Referenced by build_gateway().
00455 { 00456 /* This module does not handle MWI in an event-based manner. However, it 00457 * subscribes to MWI for each mailbox that is configured so that the core 00458 * knows that we care about it. Then, chan_mgcp will get the MWI from the 00459 * event cache instead of checking the mailbox directly. */ 00460 }
| static void parse | ( | struct mgcp_request * | req | ) | [static] |
Definition at line 1763 of file chan_mgcp.c.
References ast_log(), ast_strlen_zero(), ast_verbose, mgcp_request::data, mgcp_request::endpoint, f, mgcp_request::header, mgcp_request::headers, mgcp_request::identifier, mgcp_request::line, mgcp_request::lines, LOG_WARNING, MGCP_MAX_HEADERS, MGCP_MAX_LINES, mgcp_request::verb, and mgcp_request::version.
Referenced by acf_channel_read(), acf_meetme_info(), add_agent(), app_exec(), aqm_exec(), ast_parse_allow_disallow(), astman_get_variables(), conf_exec(), conf_run(), config_function_read(), cut_internal(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), find_conf(), function_agent(), get_in_brackets(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), mgcpsock_read(), misdn_check_l2l1(), misdn_facility_exec(), misdn_set_opt_exec(), mixmonitor_exec(), oss_call(), oss_request(), park_call_exec(), pbx_builtin_background(), pbx_builtin_waitexten(), play_moh_exec(), pqm_exec(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), rcvfax_exec(), record_exec(), reload_agents(), reload_queues(), retrydial_exec(), rqm_exec(), sayunixtime_exec(), sendtext_exec(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), start_moh_exec(), start_monitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), and zapateller_exec().
01764 { 01765 /* Divide fields by NULL's */ 01766 char *c; 01767 int f = 0; 01768 c = req->data; 01769 01770 /* First header starts immediately */ 01771 req->header[f] = c; 01772 while(*c) { 01773 if (*c == '\n') { 01774 /* We've got a new header */ 01775 *c = 0; 01776 #if 0 01777 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f])); 01778 #endif 01779 if (ast_strlen_zero(req->header[f])) { 01780 /* Line by itself means we're now in content */ 01781 c++; 01782 break; 01783 } 01784 if (f >= MGCP_MAX_HEADERS - 1) { 01785 ast_log(LOG_WARNING, "Too many MGCP headers...\n"); 01786 } else 01787 f++; 01788 req->header[f] = c + 1; 01789 } else if (*c == '\r') { 01790 /* Ignore but eliminate \r's */ 01791 *c = 0; 01792 } 01793 c++; 01794 } 01795 /* Check for last header */ 01796 if (!ast_strlen_zero(req->header[f])) 01797 f++; 01798 req->headers = f; 01799 /* Now we process any mime content */ 01800 f = 0; 01801 req->line[f] = c; 01802 while(*c) { 01803 if (*c == '\n') { 01804 /* We've got a new line */ 01805 *c = 0; 01806 #if 0 01807 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f])); 01808 #endif 01809 if (f >= MGCP_MAX_LINES - 1) { 01810 ast_log(LOG_WARNING, "Too many SDP lines...\n"); 01811 } else 01812 f++; 01813 req->line[f] = c + 1; 01814 } else if (*c == '\r') { 01815 /* Ignore and eliminate \r's */ 01816 *c = 0; 01817 } 01818 c++; 01819 } 01820 /* Check for last line */ 01821 if (!ast_strlen_zero(req->line[f])) 01822 f++; 01823 req->lines = f; 01824 /* Parse up the initial header */ 01825 c = req->header[0]; 01826 while(*c && *c < 33) c++; 01827 /* First the verb */ 01828 req->verb = c; 01829 while(*c && (*c > 32)) c++; 01830 if (*c) { 01831 *c = '\0'; 01832 c++; 01833 while(*c && (*c < 33)) c++; 01834 req->identifier = c; 01835 while(*c && (*c > 32)) c++; 01836 if (*c) { 01837 *c = '\0'; 01838 c++; 01839 while(*c && (*c < 33)) c++; 01840 req->endpoint = c; 01841 while(*c && (*c > 32)) c++; 01842 if (*c) { 01843 *c = '\0'; 01844 c++; 01845 while(*c && (*c < 33)) c++; 01846 req->version = c; 01847 while(*c && (*c > 32)) c++; 01848 while(*c && (*c < 33)) c++; 01849 while(*c && (*c > 32)) c++; 01850 *c = '\0'; 01851 } 01852 } 01853 } 01854 01855 if (mgcpdebug) { 01856 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", 01857 req->verb, req->identifier, req->endpoint, req->version); 01858 ast_verbose("%d headers, %d lines\n", req->headers, req->lines); 01859 } 01860 if (*c) 01861 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); 01862 }
| static int process_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 1864 of file chan_mgcp.c.
References ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_get_current_formats(), ast_rtp_pt_clear(), ast_rtp_set_m_type(), ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_strdupa, ast_strlen_zero(), ast_verbose, mgcp_endpoint::capability, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sdpLineNum_iterator_init().
Referenced by handle_response().
01865 { 01866 char *m; 01867 char *c; 01868 char *a; 01869 char host[258]; 01870 int len; 01871 int portno; 01872 int peercapability, peerNonCodecCapability; 01873 struct sockaddr_in sin; 01874 char *codecs; 01875 struct ast_hostent ahp; struct hostent *hp; 01876 int codec, codec_count=0; 01877 int iterator; 01878 struct mgcp_endpoint *p = sub->parent; 01879 01880 /* Get codec and RTP info from SDP */ 01881 m = get_sdp(req, "m"); 01882 c = get_sdp(req, "c"); 01883 if (ast_strlen_zero(m) || ast_strlen_zero(c)) { 01884 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); 01885 return -1; 01886 } 01887 if (sscanf(c, "IN IP4 %256s", host) != 1) { 01888 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 01889 return -1; 01890 } 01891 /* XXX This could block for a long time, and block the main thread! XXX */ 01892 hp = ast_gethostbyname(host, &ahp); 01893 if (!hp) { 01894 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); 01895 return -1; 01896 } 01897 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) { 01898 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 01899 return -1; 01900 } 01901 sin.sin_family = AF_INET; 01902 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01903 sin.sin_port = htons(portno); 01904 ast_rtp_set_peer(sub->rtp, &sin); 01905 #if 0 01906 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 01907 #endif 01908 /* Scan through the RTP payload types specified in a "m=" line: */ 01909 ast_rtp_pt_clear(sub->rtp); 01910 codecs = ast_strdupa(m + len); 01911 while (!ast_strlen_zero(codecs)) { 01912 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) { 01913 if (codec_count) 01914 break; 01915 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs); 01916 return -1; 01917 } 01918 ast_rtp_set_m_type(sub->rtp, codec); 01919 codec_count++; 01920 codecs += len; 01921 } 01922 01923 /* Next, scan through each "a=rtpmap:" line, noting each */ 01924 /* specified RTP payload type (with corresponding MIME subtype): */ 01925 sdpLineNum_iterator_init(&iterator); 01926 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 01927 char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */ 01928 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2) 01929 continue; 01930 /* Note: should really look at the 'freq' and '#chans' params too */ 01931 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0); 01932 } 01933 01934 /* Now gather all of the codecs that were asked for: */ 01935 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability); 01936 p->capability = capability & peercapability; 01937 if (mgcpdebug) { 01938 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n", 01939 capability, peercapability, p->capability); 01940 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n", 01941 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); 01942 } 01943 if (!p->capability) { 01944 ast_log(LOG_WARNING, "No compatible codecs!\n"); 01945 return -1; 01946 } 01947 return 0; 01948 }
| static void prune_gateways | ( | void | ) | [static] |
Definition at line 4059 of file chan_mgcp.c.
References ast_mutex_lock(), ast_mutex_unlock(), mgcp_gateway::delme, mgcp_endpoint::delme, destroy_endpoint(), destroy_gateway(), mgcp_gateway::endpoints, gatelock, gateways, mgcp_gateway::next, and mgcp_endpoint::next.
Referenced by reload_config(), and unload_module().
04060 { 04061 struct mgcp_gateway *g, *z, *r; 04062 struct mgcp_endpoint *e, *p, *t; 04063 04064 ast_mutex_lock(&gatelock); 04065 04066 /* prune gateways */ 04067 for (z = NULL, g = gateways; g;) { 04068 /* prune endpoints */ 04069 for (p = NULL, e = g->endpoints; e; ) { 04070 if (e->delme || g->delme) { 04071 t = e; 04072 e = e->next; 04073 if (!p) 04074 g->endpoints = e; 04075 else 04076 p->next = e; 04077 destroy_endpoint(t); 04078 } else { 04079 p = e; 04080 e = e->next; 04081 } 04082 } 04083 04084 if (g->delme) { 04085 r = g; 04086 g = g->next; 04087 if (!z) 04088 gateways = g; 04089 else 04090 z->next = g; 04091 04092 destroy_gateway(r); 04093 } else { 04094 z = g; 04095 g = g->next; 04096 } 04097 } 04098 04099 ast_mutex_unlock(&gatelock); 04100 }
| static int reload | ( | void | ) | [static] |
Definition at line 4343 of file chan_mgcp.c.
References mgcp_reload().
04344 { 04345 mgcp_reload(NULL, 0, NULL); 04346 return 0; 04347 }
| static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4102 of file chan_mgcp.c.
References __ourip, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_jb_read_conf(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_set_qos(), ast_sched_runq(), ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_gateway(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, errno, format, gatelock, gateways, global_jbconf, hp, ast_variable::lineno, LOG_NOTICE, LOG_WARNING, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, netlock, mgcp_gateway::next, mgcp_endpoint::next, ast_variable::next, prune_gateways(), qos, transmit_audit_endpoint(), and ast_variable::value.
Referenced by do_monitor(), and load_module().
04103 { 04104 struct ast_config *cfg; 04105 struct ast_variable *v; 04106 struct mgcp_gateway *g; 04107 struct mgcp_endpoint *e; 04108 char *cat; 04109 struct ast_hostent ahp; 04110 struct hostent *hp; 04111 int format; 04112 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04113 04114 if (gethostname(ourhost, sizeof(ourhost)-1)) { 04115 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); 04116 return 0; 04117 } 04118 cfg = ast_config_load(config, config_flags); 04119 04120 /* We *must* have a config file otherwise stop immediately */ 04121 if (!cfg) { 04122 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); 04123 return 0; 04124 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) 04125 return 0; 04126 04127 memset(&bindaddr, 0, sizeof(bindaddr)); 04128 dtmfmode = 0; 04129 04130 /* Copy the default jb config over global_jbconf */ 04131 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 04132 04133 v = ast_variable_browse(cfg, "general"); 04134 while (v) { 04135 /* handle jb conf */ 04136 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { 04137 v = v->next; 04138 continue; 04139 } 04140 04141 /* Create the interface list */ 04142 if (!strcasecmp(v->name, "bindaddr")) { 04143 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 04144 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 04145 } else { 04146 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 04147 } 04148 } else if (!strcasecmp(v->name, "allow")) { 04149 format = ast_getformatbyname(v->value); 04150 if (format < 1) 04151 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04152 else 04153 capability |= format; 04154 } else if (!strcasecmp(v->name, "disallow")) { 04155 format = ast_getformatbyname(v->value); 04156 if (format < 1) 04157 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value); 04158 else 04159 capability &= ~format; 04160 } else if (!strcasecmp(v->name, "tos")) { 04161 if (ast_str2tos(v->value, &qos.tos)) 04162 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04163 } else if (!strcasecmp(v->name, "tos_audio")) { 04164 if (ast_str2tos(v->value, &qos.tos_audio)) 04165 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04166 } else if (!strcasecmp(v->name, "cos")) { 04167 if (ast_str2cos(v->value, &qos.cos)) 04168 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 04169 } else if (!strcasecmp(v->name, "cos_audio")) { 04170 if (ast_str2cos(v->value, &qos.cos_audio)) 04171 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04172 } else if (!strcasecmp(v->name, "port")) { 04173 if (sscanf(v->value, "%5d", &ourport) == 1) { 04174 bindaddr.sin_port = htons(ourport); 04175 } else { 04176 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 04177 } 04178 } 04179 v = v->next; 04180 } 04181 04182 /* mark existing entries for deletion */ 04183 ast_mutex_lock(&gatelock); 04184 g = gateways; 04185 while (g) { 04186 g->delme = 1; 04187 e = g->endpoints; 04188 while (e) { 04189 e->delme = 1; 04190 e = e->next; 04191 } 04192 g = g->next; 04193 } 04194 ast_mutex_unlock(&gatelock); 04195 04196 cat = ast_category_browse(cfg, NULL); 04197 while(cat) { 04198 if (strcasecmp(cat, "general")) { 04199 ast_mutex_lock(&gatelock); 04200 g = build_gateway(cat, ast_variable_browse(cfg, cat)); 04201 if (g) { 04202 ast_verb(3, "Added gateway '%s'\n", g->name); 04203 g->next = gateways; 04204 gateways = g; 04205 } 04206 ast_mutex_unlock(&gatelock); 04207 04208 /* FS: process queue and IO */ 04209 if (monitor_thread == pthread_self()) { 04210 if (sched) ast_sched_runq(sched); 04211 if (io) ast_io_wait(io, 10); 04212 } 04213 } 04214 cat = ast_category_browse(cfg, cat); 04215 } 04216 04217 /* prune deleted entries etc. */ 04218 prune_gateways(); 04219 04220 if (ntohl(bindaddr.sin_addr.s_addr)) { 04221 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); 04222 } else { 04223 hp = ast_gethostbyname(ourhost, &ahp); 04224 if (!hp) { 04225 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); 04226 ast_config_destroy(cfg); 04227 return 0; 04228 } 04229 memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); 04230 } 04231 if (!ntohs(bindaddr.sin_port)) 04232 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT); 04233 bindaddr.sin_family = AF_INET; 04234 ast_mutex_lock(&netlock); 04235 if (mgcpsock > -1) 04236 close(mgcpsock); 04237 04238 if (mgcpsock_read_id != NULL) 04239 ast_io_remove(io, mgcpsock_read_id); 04240 mgcpsock_read_id = NULL; 04241 04242 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); 04243 if (mgcpsock < 0) { 04244 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); 04245 } else { 04246 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 04247 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 04248 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 04249 strerror(errno)); 04250 close(mgcpsock); 04251 mgcpsock = -1; 04252 } else { 04253 ast_verb(2, "MGCP Listening on %s:%d\n", 04254 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 04255 ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); 04256 } 04257 } 04258 ast_mutex_unlock(&netlock); 04259 ast_config_destroy(cfg); 04260 04261 /* send audit only to the new endpoints */ 04262 g = gateways; 04263 while (g) { 04264 e = g->endpoints; 04265 while (e && e->needaudit) { 04266 e->needaudit = 0; 04267 transmit_audit_endpoint(e); 04268 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); 04269 e = e->next; 04270 } 04271 g = g->next; 04272 } 04273 04274 return 0; 04275 }
| static int reqprep | ( | struct mgcp_request * | req, | |
| struct mgcp_endpoint * | p, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2041 of file chan_mgcp.c.
References init_req().
Referenced by transmit_audit_endpoint(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
| static int resend_response | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_response * | resp | |||
| ) | [static] |
Definition at line 528 of file chan_mgcp.c.
References __mgcp_xmit(), mgcp_gateway::addr, ast_inet_ntoa(), ast_verbose, mgcp_response::buf, mgcp_response::len, mgcp_endpoint::parent, and mgcp_subchannel::parent.
Referenced by find_and_retrans().
00529 { 00530 struct mgcp_endpoint *p = sub->parent; 00531 int res; 00532 if (mgcpdebug) { 00533 ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00534 } 00535 res = __mgcp_xmit(p->parent, resp->buf, resp->len); 00536 if (res > 0) 00537 res = 0; 00538 return res; 00539 }
| static int respprep | ( | struct mgcp_request * | resp, | |
| struct mgcp_endpoint * | p, | |||
| char * | msg, | |||
| struct mgcp_request * | req, | |||
| char * | msgrest | |||
| ) | [static] |
Definition at line 2034 of file chan_mgcp.c.
References init_resp().
Referenced by transmit_response().
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 3495 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, and monlock.
Referenced by load_module(), mgcp_reload(), and mgcp_request().
03496 { 03497 /* If we're supposed to be stopped -- stay stopped */ 03498 if (monitor_thread == AST_PTHREADT_STOP) 03499 return 0; 03500 if (ast_mutex_lock(&monlock)) { 03501 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 03502 return -1; 03503 } 03504 if (monitor_thread == pthread_self()) { 03505 ast_mutex_unlock(&monlock); 03506 ast_log(LOG_WARNING, "Cannot kill myself\n"); 03507 return -1; 03508 } 03509 if (monitor_thread != AST_PTHREADT_NULL) { 03510 /* Wake up the thread */ 03511 pthread_kill(monitor_thread, SIGURG); 03512 } else { 03513 /* Start a new monitor */ 03514 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 03515 ast_mutex_unlock(&monlock); 03516 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 03517 return -1; 03518 } 03519 } 03520 ast_mutex_unlock(&monlock); 03521 return 0; 03522 }
| static int retrans_pkt | ( | const void * | data | ) | [static] |
Definition at line 631 of file chan_mgcp.c.
References __mgcp_xmit(), ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, handle_response(), LOG_WARNING, MAX_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::retrans, and mgcp_gateway::retransid.
Referenced by mgcp_postrequest().
00632 { 00633 struct mgcp_gateway *gw = (struct mgcp_gateway *)data; 00634 struct mgcp_message *cur, *exq = NULL, *w, *prev; 00635 int res = 0; 00636 00637 /* find out expired msgs */ 00638 ast_mutex_lock(&gw->msgs_lock); 00639 00640 prev = NULL, cur = gw->msgs; 00641 while (cur) { 00642 if (cur->retrans < MAX_RETRANS) { 00643 cur->retrans++; 00644 if (mgcpdebug) { 00645 ast_verbose("Retransmitting #%d transaction %u on [%s]\n", 00646 cur->retrans, cur->seqno, gw->name); 00647 } 00648 __mgcp_xmit(gw, cur->buf, cur->len); 00649 00650 prev = cur; 00651 cur = cur->next; 00652 } else { 00653 if (prev) 00654 prev->next = cur->next; 00655 else 00656 gw->msgs = cur->next; 00657 00658 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", 00659 cur->seqno, gw->name); 00660 00661 w = cur; 00662 cur = cur->next; 00663 00664 if (exq) { 00665 w->next = exq; 00666 } else { 00667 w->next = NULL; 00668 } 00669 exq = w; 00670 } 00671 } 00672 00673 if (!gw->msgs) { 00674 gw->retransid = -1; 00675 res = 0; 00676 } else { 00677 res = 1; 00678 } 00679 ast_mutex_unlock(&gw->msgs_lock); 00680 00681 while (exq) { 00682 cur = exq; 00683 /* time-out transaction */ 00684 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 00685 exq = exq->next; 00686 ast_free(cur); 00687 } 00688 00689 return res; 00690 }
| static void sdpLineNum_iterator_init | ( | int * | iterator | ) | [static] |
Definition at line 1588 of file chan_mgcp.c.
Referenced by process_sdp().
| static int send_request | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub, | |||
| struct mgcp_request * | req, | |||
| unsigned int | seqno | |||
| ) | [static] |
Definition at line 758 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_request::data, mgcp_request::len, LOG_WARNING, MGCP_CMD_CRCX, MGCP_CMD_DLCX, MGCP_CMD_MDCX, MGCP_CMD_RQNT, mgcp_postrequest(), mgcp_request::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.
Referenced by transmit_audit_endpoint(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
00760 { 00761 int res = 0; 00762 struct mgcp_request **queue, *q, *r, *t; 00763 ast_mutex_t *l; 00764 00765 ast_debug(1, "Slow sequence is %d\n", p->slowsequence); 00766 if (p->slowsequence) { 00767 queue = &p->cmd_queue; 00768 l = &p->cmd_queue_lock; 00769 ast_mutex_lock(l); 00770 } else { 00771 switch (req->cmd) { 00772 case MGCP_CMD_DLCX: 00773 queue = &sub->cx_queue; 00774 l = &sub->cx_queue_lock; 00775 ast_mutex_lock(l); 00776 q = sub->cx_queue; 00777 /* delete pending cx cmds */ 00778 while (q) { 00779 r = q->next; 00780 ast_free(q); 00781 q = r; 00782 } 00783 *queue = NULL; 00784 break; 00785 00786 case MGCP_CMD_CRCX: 00787 case MGCP_CMD_MDCX: 00788 queue = &sub->cx_queue; 00789 l = &sub->cx_queue_lock; 00790 ast_mutex_lock(l); 00791 break; 00792 00793 case MGCP_CMD_RQNT: 00794 queue = &p->rqnt_queue; 00795 l = &p->rqnt_queue_lock; 00796 ast_mutex_lock(l); 00797 break; 00798 00799 default: 00800 queue = &p->cmd_queue; 00801 l = &p->cmd_queue_lock; 00802 ast_mutex_lock(l); 00803 break; 00804 } 00805 } 00806 00807 r = ast_malloc(sizeof(*r)); 00808 if (!r) { 00809 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n"); 00810 ast_mutex_unlock(l); 00811 return -1; 00812 } 00813 memcpy(r, req, sizeof(*r)); 00814 00815 if (!(*queue)) { 00816 if (mgcpdebug) { 00817 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 00818 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00819 } 00820 00821 res = mgcp_postrequest(p, sub, req->data, req->len, seqno); 00822 } else { 00823 if (mgcpdebug) { 00824 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 00825 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00826 } 00827 } 00828 00829 /* XXX find tail. We could also keep tail in the data struct for faster access */ 00830 for (t = *queue; t && t->next; t = t->next); 00831 00832 r->next = NULL; 00833 if (t) 00834 t->next = r; 00835 else 00836 *queue = r; 00837 00838 ast_mutex_unlock(l); 00839 00840 return res; 00841 }
| static int send_response | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 541 of file chan_mgcp.c.
References __mgcp_xmit(), mgcp_gateway::addr, ast_inet_ntoa(), ast_verbose, mgcp_request::data, mgcp_request::len, mgcp_endpoint::parent, and mgcp_subchannel::parent.
Referenced by transmit_response().
00542 { 00543 struct mgcp_endpoint *p = sub->parent; 00544 int res; 00545 if (mgcpdebug) { 00546 ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00547 } 00548 res = __mgcp_xmit(p->parent, req->data, req->len); 00549 if (res > 0) 00550 res = 0; 00551 return res; 00552 }
| static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2636 of file chan_mgcp.c.
References ast_channel_set_fd(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_destroy(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_callback(), ast_rtp_set_data(), ast_rtp_setnat(), ast_rtp_setqos(), bindaddr, mgcp_subchannel::callid, mgcp_subchannel::lock, mgcp_subchannel::nat, mgcp_subchannel::owner, qos, mgcp_subchannel::rtp, transmit_connect_with_sdp(), and mgcp_subchannel::txident.
Referenced by handle_hd_hf(), handle_response(), mgcp_answer(), mgcp_call(), and mgcp_ss().
02637 { 02638 ast_mutex_lock(&sub->lock); 02639 /* check again to be on the safe side */ 02640 if (sub->rtp) { 02641 ast_rtp_destroy(sub->rtp); 02642 sub->rtp = NULL; 02643 } 02644 /* Allocate the RTP now */ 02645 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 02646 if (sub->rtp && sub->owner) 02647 ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp)); 02648 if (sub->rtp) { 02649 ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); 02650 ast_rtp_setnat(sub->rtp, sub->nat); 02651 } 02652 #if 0 02653 ast_rtp_set_callback(p->rtp, rtpready); 02654 ast_rtp_set_data(p->rtp, p); 02655 #endif 02656 /* Make a call*ID */ 02657 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); 02658 /* Transmit the connection create */ 02659 transmit_connect_with_sdp(sub, NULL); 02660 ast_mutex_unlock(&sub->lock); 02661 }
| static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2355 of file chan_mgcp.c.
References add_header(), mgcp_request::cmd, MGCP_CMD_AUEP, reqprep(), send_request(), and mgcp_request::trid.
Referenced by handle_mgcp_audit_endpoint(), handle_request(), and reload_config().
02356 { 02357 struct mgcp_request resp; 02358 reqprep(&resp, p, "AUEP"); 02359 /* removed unknown param VS */ 02360 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ 02361 add_header(&resp, "F", "A"); 02362 /* fill in new fields */ 02363 resp.cmd = MGCP_CMD_AUEP; 02364 resp.trid = oseq; 02365 return send_request(p, NULL, &resp, oseq); /* SC */ 02366 }
| static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp * | rtp | |||
| ) | [static] |
Definition at line 2202 of file chan_mgcp.c.
References add_header(), add_sdp(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype(), ast_verb, mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by start_rtp().
02203 { 02204 struct mgcp_request resp; 02205 char local[256]; 02206 char tmp[80]; 02207 int x; 02208 struct mgcp_endpoint *p = sub->parent; 02209 02210 ast_copy_string(local, "p:20", sizeof(local)); 02211 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02212 if (p->capability & x) { 02213 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0)); 02214 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02215 } 02216 } 02217 if (mgcpdebug) { 02218 ast_verb(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02219 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02220 } 02221 reqprep(&resp, p, "CRCX"); 02222 add_header(&resp, "C", sub->callid); 02223 add_header(&resp, "L", local); 02224 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02225 /* X header should not be sent. kept for compatibility */ 02226 add_header(&resp, "X", sub->txident); 02227 /*add_header(&resp, "S", "");*/ 02228 add_sdp(&resp, sub, rtp); 02229 /* fill in new fields */ 02230 resp.cmd = MGCP_CMD_CRCX; 02231 resp.trid = oseq; 02232 return send_request(p, sub, &resp, oseq); /* SC */ 02233 }
| static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2368 of file chan_mgcp.c.
References add_header(), ast_verb, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by destroy_endpoint(), handle_request(), handle_response(), mgcp_hangup(), and unalloc_sub().
02369 { 02370 struct mgcp_endpoint *p = sub->parent; 02371 struct mgcp_request resp; 02372 02373 if (mgcpdebug) { 02374 ast_verb(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 02375 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02376 } 02377 reqprep(&resp, p, "DLCX"); 02378 /* check if call id is avail */ 02379 if (sub->callid[0]) 02380 add_header(&resp, "C", sub->callid); 02381 /* X header should not be sent. kept for compatibility */ 02382 add_header(&resp, "X", sub->txident); 02383 /* check if cxident is avail */ 02384 if (sub->cxident[0]) 02385 add_header(&resp, "I", sub->cxident); 02386 /* fill in new fields */ 02387 resp.cmd = MGCP_CMD_DLCX; 02388 resp.trid = oseq; 02389 return send_request(p, sub, &resp, oseq); /* SC */ 02390 }
| static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, | |
| char * | callid, | |||
| char * | cxident | |||
| ) | [static] |
Definition at line 2392 of file chan_mgcp.c.
References add_header(), ast_verb, mgcp_request::cmd, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, reqprep(), send_request(), mgcp_endpoint::sub, and mgcp_request::trid.
Referenced by handle_response().
02393 { 02394 struct mgcp_request resp; 02395 02396 if (mgcpdebug) { 02397 ast_verb(3, "Delete connection %s %s@%s on callid: %s\n", 02398 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); 02399 } 02400 reqprep(&resp, p, "DLCX"); 02401 /* check if call id is avail */ 02402 if (callid && *callid) 02403 add_header(&resp, "C", callid); 02404 /* check if cxident is avail */ 02405 if (cxident && *cxident) 02406 add_header(&resp, "I", cxident); 02407 /* fill in new fields */ 02408 resp.cmd = MGCP_CMD_DLCX; 02409 resp.trid = oseq; 02410 return send_request(p, p->sub, &resp, oseq); 02411 }
| static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2310 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), mgcp_call(), and mgcp_hangup().
02311 { 02312 struct mgcp_request resp; 02313 struct mgcp_endpoint *p = sub->parent; 02314 02315 if (ast_strlen_zero(sub->cxident)) { 02316 /* We don't have a CXident yet, store the destination and 02317 wait a bit */ 02318 return 0; 02319 } 02320 if (mgcpdebug) { 02321 ast_verb(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", 02322 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02323 } 02324 reqprep(&resp, p, "MDCX"); 02325 add_header(&resp, "C", sub->callid); 02326 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02327 /* X header should not be sent. kept for compatibility */ 02328 add_header(&resp, "X", sub->txident); 02329 add_header(&resp, "I", sub->cxident); 02330 switch (sub->parent->hookstate) { 02331 case MGCP_ONHOOK: 02332 add_header(&resp, "R", "L/hd(N)"); 02333 break; 02334 case MGCP_OFFHOOK: 02335 add_header_offhook(sub, &resp); 02336 break; 02337 } 02338 /* fill in new fields */ 02339 resp.cmd = MGCP_CMD_MDCX; 02340 resp.trid = oseq; 02341 return send_request(p, sub, &resp, oseq); /* SC */ 02342 }
| static int transmit_modify_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp * | rtp, | |||
| int | codecs | |||
| ) | [static] |
Definition at line 2166 of file chan_mgcp.c.
References add_header(), add_sdp(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_get_peer(), ast_rtp_lookup_mime_subtype(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, MGCP_CMD_MDCX, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_subchannel::tmpdest, mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by handle_response(), and mgcp_set_rtp_peer().
02167 { 02168 struct mgcp_request resp; 02169 char local[256]; 02170 char tmp[80]; 02171 int x; 02172 struct mgcp_endpoint *p = sub->parent; 02173 02174 if (ast_strlen_zero(sub->cxident) && rtp) { 02175 /* We don't have a CXident yet, store the destination and 02176 wait a bit */ 02177 ast_rtp_get_peer(rtp, &sub->tmpdest); 02178 return 0; 02179 } 02180 ast_copy_string(local, "p:20", sizeof(local)); 02181 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02182 if (p->capability & x) { 02183 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0)); 02184 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02185 } 02186 } 02187 reqprep(&resp, p, "MDCX"); 02188 add_header(&resp, "C", sub->callid); 02189 add_header(&resp, "L", local); 02190 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02191 /* X header should not be sent. kept for compatibility */ 02192 add_header(&resp, "X", sub->txident); 02193 add_header(&resp, "I", sub->cxident); 02194 /*add_header(&resp, "S", "");*/ 02195 add_sdp(&resp, sub, rtp); 02196 /* fill in new fields */ 02197 resp.cmd = MGCP_CMD_MDCX; 02198 resp.trid = oseq; 02199 return send_request(p, sub, &resp, oseq); /* SC */ 02200 }
| static int transmit_notify_request | ( | struct mgcp_subchannel * | sub, | |
| char * | tone | |||
| ) | [static] |
Definition at line 2235 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_copy_string(), ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_RQNT, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), 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().
02236 { 02237 struct mgcp_request resp; 02238 struct mgcp_endpoint *p = sub->parent; 02239 02240 if (mgcpdebug) { 02241 ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02242 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02243 } 02244 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02245 reqprep(&resp, p, "RQNT"); 02246 add_header(&resp, "X", p->rqnt_ident); /* SC */ 02247 switch (p->hookstate) { 02248 case MGCP_ONHOOK: 02249 add_header(&resp, "R", "L/hd(N)"); 02250 break; 02251 case MGCP_OFFHOOK: 02252 add_header_offhook(sub, &resp); 02253 break; 02254 } 02255 if (!ast_strlen_zero(tone)) { 02256 add_header(&resp, "S", tone); 02257 } 02258 /* fill in new fields */ 02259 resp.cmd = MGCP_CMD_RQNT; 02260 resp.trid = oseq; 02261 return send_request(p, NULL, &resp, oseq); /* SC */ 02262 }
| static int transmit_notify_request_with_callerid | ( | struct mgcp_subchannel * | sub, | |
| char * | tone, | |||
| char * | callernum, | |||
| char * | callername | |||
| ) | [static] |
Definition at line 2264 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_copy_string(), ast_localtime(), ast_strlen_zero(), ast_tvnow(), ast_verb, mgcp_request::cmd, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::lastcallerid, MGCP_CMD_RQNT, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), 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().
02265 { 02266 struct mgcp_request resp; 02267 char tone2[256]; 02268 char *l, *n; 02269 struct timeval t = ast_tvnow(); 02270 struct ast_tm tm; 02271 struct mgcp_endpoint *p = sub->parent; 02272 02273 ast_localtime(&t, &tm, NULL); 02274 n = callername; 02275 l = callernum; 02276 if (!n) 02277 n = ""; 02278 if (!l) 02279 l = ""; 02280 02281 /* Keep track of last callerid for blacklist and callreturn */ 02282 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid)); 02283 02284 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 02285 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n); 02286 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02287 reqprep(&resp, p, "RQNT"); 02288 add_header(&resp, "X", p->rqnt_ident); /* SC */ 02289 switch (p->hookstate) { 02290 case MGCP_ONHOOK: 02291 add_header(&resp, "R", "L/hd(N)"); 02292 break; 02293 case MGCP_OFFHOOK: 02294 add_header_offhook(sub, &resp); 02295 break; 02296 } 02297 if (!ast_strlen_zero(tone2)) { 02298 add_header(&resp, "S", tone2); 02299 } 02300 if (mgcpdebug) { 02301 ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02302 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02303 } 02304 /* fill in new fields */ 02305 resp.cmd = MGCP_CMD_RQNT; 02306 resp.trid = oseq; 02307 return send_request(p, NULL, &resp, oseq); /* SC */ 02308 }
| static int transmit_response | ( | struct mgcp_subchannel * | sub, | |
| char * | msg, | |||
| struct mgcp_request * | req, | |||
| char * | msgrest | |||
| ) | [static] |
Definition at line 2051 of file chan_mgcp.c.
References ast_calloc, mgcp_response::buf, mgcp_request::data, mgcp_request::identifier, mgcp_response::len, mgcp_request::len, mgcp_response::next, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_gateway::responses, respprep(), send_response(), mgcp_response::seqno, and mgcp_response::whensent.
Referenced by handle_request().
02052 { 02053 struct mgcp_request resp; 02054 struct mgcp_endpoint *p = sub->parent; 02055 struct mgcp_response *mgr; 02056 02057 respprep(&resp, p, msg, req, msgrest); 02058 mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1); 02059 if (mgr) { 02060 /* Store MGCP response in case we have to retransmit */ 02061 sscanf(req->identifier, "%30d", &mgr->seqno); 02062 time(&mgr->whensent); 02063 mgr->len = resp.len; 02064 memcpy(mgr->buf, resp.data, resp.len); 02065 mgr->buf[resp.len] = '\0'; 02066 mgr->next = p->parent->responses; 02067 p->parent->responses = mgr; 02068 } 02069 return send_response(sub, &resp); 02070 }
| static int unalloc_sub | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 487 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_WARNING, MGCP_CX_INACTIVE, mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_subchannel::tmpdest, and transmit_connection_del().
Referenced by attempt_transfer().
00488 { 00489 struct mgcp_endpoint *p = sub->parent; 00490 if (p->sub == sub) { 00491 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name); 00492 return -1; 00493 } 00494 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name); 00495 00496 sub->owner = NULL; 00497 if (!ast_strlen_zero(sub->cxident)) { 00498 transmit_connection_del(sub); 00499 } 00500 sub->cxident[0] = '\0'; 00501 sub->callid[0] = '\0'; 00502 sub->cxmode = MGCP_CX_INACTIVE; 00503 sub->outgoing = 0; 00504 sub->alreadygone = 0; 00505 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 00506 if (sub->rtp) { 00507 ast_rtp_destroy(sub->rtp); 00508 sub->rtp = NULL; 00509 } 00510 dump_cmd_queues(NULL, sub); /* SC */ 00511 return 0; 00512 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 4349 of file chan_mgcp.c.
References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, LOG_WARNING, mgcp_reload(), mgcp_reload_lock, monlock, mgcp_endpoint::next, mgcp_gateway::next, prune_gateways(), and sched_context_destroy().
04350 { 04351 struct mgcp_endpoint *e; 04352 struct mgcp_gateway *g; 04353 04354 /* Check to see if we're reloading */ 04355 if (ast_mutex_trylock(&mgcp_reload_lock)) { 04356 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n"); 04357 return -1; 04358 } else { 04359 mgcp_reloading = 1; 04360 ast_mutex_unlock(&mgcp_reload_lock); 04361 } 04362 04363 /* First, take us out of the channel loop */ 04364 ast_channel_unregister(&mgcp_tech); 04365 04366 /* Shut down the monitoring thread */ 04367 if (!ast_mutex_lock(&monlock)) { 04368 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { 04369 pthread_cancel(monitor_thread); 04370 pthread_kill(monitor_thread, SIGURG); 04371 pthread_join(monitor_thread, NULL); 04372 } 04373 monitor_thread = AST_PTHREADT_STOP; 04374 ast_mutex_unlock(&monlock); 04375 } else { 04376 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 04377 /* We always want to leave this in a consistent state */ 04378 ast_channel_register(&mgcp_tech); 04379 mgcp_reloading = 0; 04380 mgcp_reload(NULL, 0, NULL); 04381 return -1; 04382 } 04383 04384 if (!ast_mutex_lock(&gatelock)) { 04385 for (g = gateways; g; g = g->next) { 04386 g->delme = 1; 04387 for (e = g->endpoints; e; e = e->next) 04388 e->delme = 1; 04389 } 04390 04391 prune_gateways(); 04392 ast_mutex_unlock(&gatelock); 04393 } else { 04394 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n"); 04395 /* We always want to leave this in a consistent state */ 04396 ast_channel_register(&mgcp_tech); 04397 /* Allow the monitor to restart */ 04398 monitor_thread = AST_PTHREADT_NULL; 04399 mgcp_reloading = 0; 04400 mgcp_reload(NULL, 0, NULL); 04401 return -1; 04402 } 04403 04404 close(mgcpsock); 04405 ast_rtp_proto_unregister(&mgcp_rtp); 04406 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04407 sched_context_destroy(sched); 04408 04409 return 0; 04410 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 4416 of file chan_mgcp.c.
struct in_addr __ourip [static] |
Definition at line 218 of file chan_mgcp.c.
Referenced by build_gateway(), find_subchannel_and_lock(), and reload_config().
char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static] |
Definition at line 183 of file chan_mgcp.c.
int adsi = 0 [static] |
Definition at line 189 of file chan_mgcp.c.
int amaflags = 0 [static] |
Definition at line 187 of file chan_mgcp.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4416 of file chan_mgcp.c.
struct sockaddr_in bindaddr [static] |
Definition at line 405 of file chan_mgcp.c.
Referenced by reload_config(), and start_rtp().
int callreturn = 0 [static] |
Definition at line 168 of file chan_mgcp.c.
int callwaiting = 0 [static] |
Definition at line 166 of file chan_mgcp.c.
int cancallforward = 0 [static] |
Definition at line 177 of file chan_mgcp.c.
int canreinvite = CANREINVITE [static] |
Definition at line 181 of file chan_mgcp.c.
int capability = AST_FORMAT_ULAW [static] |
Definition at line 214 of file chan_mgcp.c.
Referenced by build_setup(), iax2_call(), parse_setup(), set_config(), and set_local_capabilities().
char cid_name[AST_MAX_EXTENSION] = "" [static] |
Definition at line 149 of file chan_mgcp.c.
Referenced by __oh323_new(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_pvt_defaults(), sip_call(), sla_ring_station(), and store_callerid().
char cid_num[AST_MAX_EXTENSION] = "" [static] |
Definition at line 148 of file chan_mgcp.c.
Referenced by __oh323_new(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_pvt_defaults(), sla_ring_station(), socket_process(), and store_callerid().
struct ast_cli_entry cli_mgcp[] [static] |
Definition at line 1196 of file chan_mgcp.c.
struct ast_cli_entry cli_mgcp_set_debug_deprecated = AST_CLI_DEFINE(handle_mgcp_set_debug_deprecated, "Enable/Disable MGCP debugging") [static] |
Definition at line 1195 of file chan_mgcp.c.
const char config[] = "mgcp.conf" [static] |
Definition at line 101 of file chan_mgcp.c.
char context[AST_MAX_EXTENSION] = "default" [static] |
Definition at line 143 of file chan_mgcp.c.
| unsigned int cos |
Definition at line 160 of file chan_mgcp.c.
| unsigned int cos_audio |
Definition at line 161 of file chan_mgcp.c.
ast_group_t cur_callergroup = 0 [static] |
Definition at line 154 of file chan_mgcp.c.
ast_group_t cur_pickupgroup = 0 [static] |
Definition at line 155 of file chan_mgcp.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 90 of file chan_mgcp.c.
int dtmfmode = 0 [static] |
Definition at line 151 of file chan_mgcp.c.
Referenced by set_local_capabilities().
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic)
Definition at line 194 of file chan_mgcp.c.
ast_mutex_t gatelock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
gatelock: mutex for gateway/endpoint lists
Definition at line 401 of file chan_mgcp.c.
Referenced by find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), reload_config(), and unload_module().
struct mgcp_gateway * gateways [static] |
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic)
Definition at line 197 of file chan_mgcp.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 98 of file chan_mgcp.c.
Referenced by mgcp_new(), and reload_config().
int immediate = 0 [static] |
Definition at line 164 of file chan_mgcp.c.
struct io_context* io [static] |
Definition at line 224 of file chan_mgcp.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 145 of file chan_mgcp.c.
char mailbox[AST_MAX_EXTENSION] [static] |
Definition at line 185 of file chan_mgcp.c.
Referenced by action_mailboxcount(), action_mailboxstatus(), add_peer_mailboxes(), add_peer_mwi_subs(), append_mailbox_mapping(), ast_event_hash_mwi(), build_peer(), chanspy_exec(), clear_peer_mailboxes(), disa_exec(), extenspy_exec(), get_cached_mwi(), has_voicemail(), mkintf(), notify_message(), peer_mailboxes_to_str(), realtime_directory(), unistim_send_mwi_to_peer(), and update_registry().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match
Definition at line 200 of file chan_mgcp.c.
char* mgcp_cxmodes[] [static] |
}
Definition at line 123 of file chan_mgcp.c.
ast_mutex_t mgcp_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 397 of file chan_mgcp.c.
Referenced by do_monitor(), mgcp_reload(), and unload_module().
int mgcp_reloading = 0 [static] |
Definition at line 398 of file chan_mgcp.c.
struct ast_rtp_protocol mgcp_rtp [static] |
{
.type = "MGCP",
.get_rtp_info = mgcp_get_rtp_peer,
.set_rtp_peer = mgcp_set_rtp_peer,
}
Definition at line 3997 of file chan_mgcp.c.
struct ast_channel_tech mgcp_tech [static] |
Definition at line 435 of file chan_mgcp.c.
int mgcpdebug = 0 [static] |
Definition at line 221 of file chan_mgcp.c.
int mgcpsock = -1 [static] |
Definition at line 403 of file chan_mgcp.c.
int* mgcpsock_read_id = NULL [static] |
Definition at line 3407 of file chan_mgcp.c.
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 210 of file chan_mgcp.c.
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 206 of file chan_mgcp.c.
Referenced by do_monitor(), restart_monitor(), and unload_module().
char musicclass[MAX_MUSICCLASS] = "" [static] |
Definition at line 146 of file chan_mgcp.c.
Referenced by ast_do_masquerade(), begin_dial_channel(), dial_exec_full(), findmeexec(), func_channel_write(), gtalk_new(), jingle_new(), local_call(), moh_handle_digit(), monitor_dial(), and set_moh_exec().
int nat = 0 [static] |
Definition at line 152 of file chan_mgcp.c.
ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 204 of file chan_mgcp.c.
Referenced by do_monitor(), and reload_config().
int nonCodecCapability = AST_RTP_DTMF [static] |
Definition at line 215 of file chan_mgcp.c.
unsigned int oseq [static] |
Definition at line 191 of file chan_mgcp.c.
char ourhost[MAXHOSTNAMELEN] [static] |
Definition at line 217 of file chan_mgcp.c.
Referenced by ast_find_ourip().
int ourport [static] |
Definition at line 219 of file chan_mgcp.c.
Referenced by build_contact(), initreqprep(), and transmit_notify_with_mwi().
char parkinglot[AST_MAX_CONTEXT] [static] |
Definition at line 147 of file chan_mgcp.c.
struct { ... } qos [static] |
Referenced by reload_config(), and start_rtp().
struct sched_context* sched [static] |
Definition at line 223 of file chan_mgcp.c.
int singlepath = 0 [static] |
Definition at line 179 of file chan_mgcp.c.
int slowsequence = 0 [static] |
Definition at line 170 of file chan_mgcp.c.
const char tdesc[] = "Media Gateway Control Protocol (MGCP)" [static] |
Definition at line 100 of file chan_mgcp.c.
int threewaycalling = 0 [static] |
Definition at line 172 of file chan_mgcp.c.
| unsigned int tos |
Definition at line 158 of file chan_mgcp.c.
| unsigned int tos_audio |
Definition at line 159 of file chan_mgcp.c.
int transfer = 0 [static] |
This is for flashhook transfers
Definition at line 175 of file chan_mgcp.c.
Referenced by leave_voicemail(), and send_packet().
1.6.1