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 | DEFAULT_EXPIRY 120 |
| #define | DEFAULT_MGCP_CA_PORT 2727 |
| #define | DEFAULT_MGCP_GW_PORT 2427 |
| #define | DEFAULT_RETRANS 1000 |
| #define | DIRECTMEDIA 1 |
| #define | INADDR_NONE (in_addr_t)(-1) |
| #define | MAX_EXPIRY 3600 |
| #define | MAX_RETRANS 5 |
| #define | MAX_SUBS 2 |
| #define | MGCP_CX_CONF 3 |
| #define | MGCP_CX_CONFERENCE 3 |
| #define | MGCP_CX_INACTIVE 4 |
| #define | MGCP_CX_MUTE 4 |
| #define | MGCP_CX_RECVONLY 1 |
| #define | MGCP_CX_SENDONLY 0 |
| #define | MGCP_CX_SENDRECV 2 |
| #define | MGCP_DTMF_HYBRID (1 << 2) |
| #define | MGCP_DTMF_INBAND (1 << 1) |
| #define | MGCP_DTMF_RFC2833 (1 << 0) |
| #define | MGCP_MAX_HEADERS 64 |
| #define | MGCP_MAX_LINES 64 |
| #define | MGCP_MAX_PACKET 1500 |
| #define | MGCP_OFFHOOK 2 |
| #define | MGCP_ONHOOK 1 |
| #define | MGCP_SUBCHANNEL_MAGIC "!978!" |
| #define | MGCPDUMPER |
| #define | RESPONSE_TIMEOUT 30 |
| #define | SUB_ALT 1 |
| #define | SUB_REAL 0 |
| #define | TYPE_LINE 2 |
| #define | TYPE_TRUNK 1 |
Enumerations | |
| enum | { MGCP_CMD_EPCF, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_CMD_DLCX, MGCP_CMD_RQNT, MGCP_CMD_NTFY, MGCP_CMD_AUEP, MGCP_CMD_AUCX, MGCP_CMD_RSIP } |
Functions | |
| static char * | __get_header (struct mgcp_request *req, char *name, int *start) |
| 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_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 = "0901e4e500243c855563a2d78b0c03e4" , .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 | capability = AST_FORMAT_ULAW |
| static char | cid_name [AST_MAX_EXTENSION] = "" |
| static char | cid_num [AST_MAX_EXTENSION] = "" |
| static struct ast_cli_entry | cli_mgcp [] |
| static const char | config [] = "mgcp.conf" |
| static char | context [AST_MAX_EXTENSION] = "default" |
| static ast_group_t | cur_callergroup = 0 |
| static ast_group_t | cur_pickupgroup = 0 |
| static struct ast_jb_conf | default_jbconf |
| static int | directmedia = DIRECTMEDIA |
| static int | dtmfmode = 0 |
| static int | firstdigittimeout = 16000 |
| static ast_mutex_t | gatelock = ((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 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 DIRECTMEDIA 1 |
Definition at line 83 of file chan_mgcp.c.
Referenced by build_gateway().
| #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_gateway(), config_line(), config_parse_variables(), do_monitor(), and mgcp_call().
| #define TYPE_TRUNK 1 |
Definition at line 305 of file chan_mgcp.c.
Referenced by 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 1578 of file chan_mgcp.c.
References mgcp_request::header, mgcp_request::headers, and len().
Referenced by get_header().
01579 { 01580 int x; 01581 int len = strlen(name); 01582 char *r; 01583 for (x=*start;x<req->headers;x++) { 01584 if (!strncasecmp(req->header[x], name, len) && 01585 (req->header[x][len] == ':')) { 01586 r = req->header[x] + len + 1; 01587 while(*r && (*r < 33)) 01588 r++; 01589 *start = x+1; 01590 return r; 01591 } 01592 } 01593 /* Don't return NULL, so get_header is always a valid pointer */ 01594 return ""; 01595 }
| 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 4394 of file chan_mgcp.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4394 of file chan_mgcp.c.
| static int add_header | ( | struct mgcp_request * | req, | |
| char * | var, | |||
| char * | value | |||
| ) | [static] |
Definition at line 1924 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().
01925 { 01926 if (req->len >= sizeof(req->data) - 4) { 01927 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 01928 return -1; 01929 } 01930 if (req->lines) { 01931 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 01932 return -1; 01933 } 01934 req->header[req->headers] = req->data + req->len; 01935 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); 01936 req->len += strlen(req->header[req->headers]); 01937 if (req->headers < MGCP_MAX_HEADERS) 01938 req->headers++; 01939 else { 01940 ast_log(LOG_WARNING, "Out of header space\n"); 01941 return -1; 01942 } 01943 return 0; 01944 }
| static void add_header_offhook | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | resp | |||
| ) | [static] |
Definition at line 2319 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().
02320 { 02321 struct mgcp_endpoint *p = sub->parent; 02322 02323 if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) 02324 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02325 else 02326 add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)"); 02327 }
| static int add_line | ( | struct mgcp_request * | req, | |
| char * | line | |||
| ) | [static] |
Definition at line 1946 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().
01947 { 01948 if (req->len >= sizeof(req->data) - 4) { 01949 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 01950 return -1; 01951 } 01952 if (!req->lines) { 01953 /* Add extra empty return */ 01954 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); 01955 req->len += strlen(req->data + req->len); 01956 } 01957 req->line[req->lines] = req->data + req->len; 01958 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 01959 req->len += strlen(req->line[req->lines]); 01960 if (req->lines < MGCP_MAX_LINES) 01961 req->lines++; 01962 else { 01963 ast_log(LOG_WARNING, "Out of line space\n"); 01964 return -1; 01965 } 01966 return 0; 01967 }
| static int add_sdp | ( | struct mgcp_request * | resp, | |
| struct mgcp_subchannel * | sub, | |||
| struct ast_rtp * | rtp | |||
| ) | [static] |
Definition at line 2047 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().
02048 { 02049 int len; 02050 int codec; 02051 char costr[80]; 02052 struct sockaddr_in sin; 02053 char v[256]; 02054 char s[256]; 02055 char o[256]; 02056 char c[256]; 02057 char t[256]; 02058 char m[256] = ""; 02059 char a[1024] = ""; 02060 int x; 02061 struct sockaddr_in dest; 02062 struct mgcp_endpoint *p = sub->parent; 02063 /* XXX We break with the "recommendation" and send our IP, in order that our 02064 peer doesn't have to ast_gethostbyname() us XXX */ 02065 len = 0; 02066 if (!sub->rtp) { 02067 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02068 return -1; 02069 } 02070 ast_rtp_get_us(sub->rtp, &sin); 02071 if (rtp) { 02072 ast_rtp_get_peer(rtp, &dest); 02073 } else { 02074 if (sub->tmpdest.sin_addr.s_addr) { 02075 dest.sin_addr = sub->tmpdest.sin_addr; 02076 dest.sin_port = sub->tmpdest.sin_port; 02077 /* Reset temporary destination */ 02078 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02079 } else { 02080 dest.sin_addr = p->parent->ourip; 02081 dest.sin_port = sin.sin_port; 02082 } 02083 } 02084 if (mgcpdebug) { 02085 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02086 } 02087 ast_copy_string(v, "v=0\r\n", sizeof(v)); 02088 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); 02089 ast_copy_string(s, "s=session\r\n", sizeof(s)); 02090 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02091 ast_copy_string(t, "t=0 0\r\n", sizeof(t)); 02092 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02093 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02094 if (p->capability & x) { 02095 if (mgcpdebug) { 02096 ast_verbose("Answering with capability %d\n", x); 02097 } 02098 codec = ast_rtp_lookup_code(sub->rtp, 1, x); 02099 if (codec > -1) { 02100 snprintf(costr, sizeof(costr), " %d", codec); 02101 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02102 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0)); 02103 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02104 } 02105 } 02106 } 02107 for (x = 1; x <= AST_RTP_MAX; x <<= 1) { 02108 if (p->nonCodecCapability & x) { 02109 if (mgcpdebug) { 02110 ast_verbose("Answering with non-codec capability %d\n", x); 02111 } 02112 codec = ast_rtp_lookup_code(sub->rtp, 0, x); 02113 if (codec > -1) { 02114 snprintf(costr, sizeof(costr), " %d", codec); 02115 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02116 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0)); 02117 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02118 if (x == AST_RTP_DTMF) { 02119 /* Indicate we support DTMF... Not sure about 16, 02120 but MSN supports it so dang it, we will too... */ 02121 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02122 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02123 } 02124 } 02125 } 02126 } 02127 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02128 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02129 snprintf(costr, sizeof(costr), "%d", len); 02130 add_line(resp, v); 02131 add_line(resp, o); 02132 add_line(resp, s); 02133 add_line(resp, c); 02134 add_line(resp, t); 02135 add_line(resp, m); 02136 add_line(resp, a); 02137 return 0; 02138 }
| static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2884 of file chan_mgcp.c.
References ast_channel::_softhangup, ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verb, mgcp_subchannel::id, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().
Referenced by handle_request().
02885 { 02886 /* ************************* 02887 * I hope this works. 02888 * Copied out of chan_zap 02889 * Cross your fingers 02890 * *************************/ 02891 02892 /* In order to transfer, we need at least one of the channels to 02893 actually be in a call bridge. We can't conference two applications 02894 together (but then, why would we want to?) */ 02895 if (ast_bridged_channel(p->sub->owner)) { 02896 /* The three-way person we're about to transfer to could still be in MOH, so 02897 stop if now if appropriate */ 02898 if (ast_bridged_channel(p->sub->next->owner)) 02899 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 02900 if (p->sub->owner->_state == AST_STATE_RINGING) { 02901 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 02902 } 02903 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 02904 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 02905 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); 02906 return -1; 02907 } 02908 /* Orphan the channel */ 02909 unalloc_sub(p->sub->next); 02910 } else if (ast_bridged_channel(p->sub->next->owner)) { 02911 if (p->sub->owner->_state == AST_STATE_RINGING) { 02912 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 02913 } 02914 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 02915 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 02916 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 02917 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); 02918 return -1; 02919 } 02920 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 02921 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 02922 p->sub = p->sub->next; 02923 unalloc_sub(p->sub->next); 02924 /* Tell the caller not to hangup */ 02925 return 1; 02926 } else { 02927 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 02928 p->sub->owner->name, p->sub->next->owner->name); 02929 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02930 if (p->sub->next->owner) { 02931 p->sub->next->alreadygone = 1; 02932 mgcp_queue_hangup(p->sub->next); 02933 } 02934 } 02935 return 0; 02936 }
| 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 3552 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_strlen_zero(), ast_true(), ast_verb, mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, 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::directmedia, DIRECTMEDIA, 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, 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().
03553 { 03554 struct mgcp_gateway *gw; 03555 struct mgcp_endpoint *e; 03556 struct mgcp_subchannel *sub; 03557 /*char txident[80];*/ 03558 int i=0, y=0; 03559 int gw_reload = 0; 03560 int ep_reload = 0; 03561 directmedia = DIRECTMEDIA; 03562 03563 /* locate existing gateway */ 03564 gw = gateways; 03565 while (gw) { 03566 if (!strcasecmp(cat, gw->name)) { 03567 /* gateway already exists */ 03568 gw->delme = 0; 03569 gw_reload = 1; 03570 break; 03571 } 03572 gw = gw->next; 03573 } 03574 03575 if (!gw) 03576 gw = ast_calloc(1, sizeof(*gw)); 03577 03578 if (gw) { 03579 if (!gw_reload) { 03580 gw->expire = -1; 03581 gw->retransid = -1; /* SC */ 03582 ast_mutex_init(&gw->msgs_lock); 03583 ast_copy_string(gw->name, cat, sizeof(gw->name)); 03584 /* check if the name is numeric ip */ 03585 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 03586 gw->isnamedottedip = 1; 03587 } 03588 while(v) { 03589 if (!strcasecmp(v->name, "host")) { 03590 if (!strcasecmp(v->value, "dynamic")) { 03591 /* They'll register with us */ 03592 gw->dynamic = 1; 03593 memset(&gw->addr.sin_addr, 0, 4); 03594 if (gw->addr.sin_port) { 03595 /* If we've already got a port, make it the default rather than absolute */ 03596 gw->defaddr.sin_port = gw->addr.sin_port; 03597 gw->addr.sin_port = 0; 03598 } 03599 } else { 03600 /* Non-dynamic. Make sure we become that way if we're not */ 03601 AST_SCHED_DEL(sched, gw->expire); 03602 gw->dynamic = 0; 03603 if (ast_get_ip(&gw->addr, v->value)) { 03604 if (!gw_reload) { 03605 ast_mutex_destroy(&gw->msgs_lock); 03606 ast_free(gw); 03607 } 03608 return NULL; 03609 } 03610 } 03611 } else if (!strcasecmp(v->name, "defaultip")) { 03612 if (ast_get_ip(&gw->defaddr, v->value)) { 03613 if (!gw_reload) { 03614 ast_mutex_destroy(&gw->msgs_lock); 03615 ast_free(gw); 03616 } 03617 return NULL; 03618 } 03619 } else if (!strcasecmp(v->name, "permit") || 03620 !strcasecmp(v->name, "deny")) { 03621 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 03622 } else if (!strcasecmp(v->name, "port")) { 03623 gw->addr.sin_port = htons(atoi(v->value)); 03624 } else if (!strcasecmp(v->name, "context")) { 03625 ast_copy_string(context, v->value, sizeof(context)); 03626 } else if (!strcasecmp(v->name, "dtmfmode")) { 03627 if (!strcasecmp(v->value, "inband")) 03628 dtmfmode = MGCP_DTMF_INBAND; 03629 else if (!strcasecmp(v->value, "rfc2833")) 03630 dtmfmode = MGCP_DTMF_RFC2833; 03631 else if (!strcasecmp(v->value, "hybrid")) 03632 dtmfmode = MGCP_DTMF_HYBRID; 03633 else if (!strcasecmp(v->value, "none")) 03634 dtmfmode = 0; 03635 else 03636 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 03637 } else if (!strcasecmp(v->name, "nat")) { 03638 nat = ast_true(v->value); 03639 } else if (!strcasecmp(v->name, "callerid")) { 03640 if (!strcasecmp(v->value, "asreceived")) { 03641 cid_num[0] = '\0'; 03642 cid_name[0] = '\0'; 03643 } else { 03644 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 03645 } 03646 } else if (!strcasecmp(v->name, "language")) { 03647 ast_copy_string(language, v->value, sizeof(language)); 03648 } else if (!strcasecmp(v->name, "accountcode")) { 03649 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 03650 } else if (!strcasecmp(v->name, "amaflags")) { 03651 y = ast_cdr_amaflags2int(v->value); 03652 if (y < 0) { 03653 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 03654 } else { 03655 amaflags = y; 03656 } 03657 } else if (!strcasecmp(v->name, "musiconhold")) { 03658 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 03659 } else if (!strcasecmp(v->name, "parkinglot")) { 03660 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 03661 } else if (!strcasecmp(v->name, "callgroup")) { 03662 cur_callergroup = ast_get_group(v->value); 03663 } else if (!strcasecmp(v->name, "pickupgroup")) { 03664 cur_pickupgroup = ast_get_group(v->value); 03665 } else if (!strcasecmp(v->name, "immediate")) { 03666 immediate = ast_true(v->value); 03667 } else if (!strcasecmp(v->name, "cancallforward")) { 03668 cancallforward = ast_true(v->value); 03669 } else if (!strcasecmp(v->name, "singlepath")) { 03670 singlepath = ast_true(v->value); 03671 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 03672 directmedia = ast_true(v->value); 03673 } else if (!strcasecmp(v->name, "mailbox")) { 03674 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 03675 } else if (!strcasecmp(v->name, "hasvoicemail")) { 03676 if (ast_true(v->value) && ast_strlen_zero(mailbox)) { 03677 ast_copy_string(mailbox, gw->name, sizeof(mailbox)); 03678 } 03679 } else if (!strcasecmp(v->name, "adsi")) { 03680 adsi = ast_true(v->value); 03681 } else if (!strcasecmp(v->name, "callreturn")) { 03682 callreturn = ast_true(v->value); 03683 } else if (!strcasecmp(v->name, "callwaiting")) { 03684 callwaiting = ast_true(v->value); 03685 } else if (!strcasecmp(v->name, "slowsequence")) { 03686 slowsequence = ast_true(v->value); 03687 } else if (!strcasecmp(v->name, "transfer")) { 03688 transfer = ast_true(v->value); 03689 } else if (!strcasecmp(v->name, "threewaycalling")) { 03690 threewaycalling = ast_true(v->value); 03691 } else if (!strcasecmp(v->name, "wcardep")) { 03692 /* locate existing endpoint */ 03693 e = gw->endpoints; 03694 while (e) { 03695 if (!strcasecmp(v->value, e->name)) { 03696 /* endpoint already exists */ 03697 e->delme = 0; 03698 ep_reload = 1; 03699 break; 03700 } 03701 e = e->next; 03702 } 03703 03704 if (!e) { 03705 /* Allocate wildcard endpoint */ 03706 e = ast_calloc(1, sizeof(*e)); 03707 ep_reload = 0; 03708 } 03709 03710 if (e) { 03711 if (!ep_reload) { 03712 memset(e, 0, sizeof(struct mgcp_endpoint)); 03713 ast_mutex_init(&e->lock); 03714 ast_mutex_init(&e->rqnt_queue_lock); 03715 ast_mutex_init(&e->cmd_queue_lock); 03716 ast_copy_string(e->name, v->value, sizeof(e->name)); 03717 e->needaudit = 1; 03718 } 03719 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 03720 /* XXX Should we really check for uniqueness?? XXX */ 03721 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 03722 ast_copy_string(e->context, context, sizeof(e->context)); 03723 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 03724 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 03725 ast_copy_string(e->language, language, sizeof(e->language)); 03726 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 03727 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 03728 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 03729 if (!ast_strlen_zero(e->mailbox)) { 03730 char *mbox, *cntx; 03731 cntx = mbox = ast_strdupa(e->mailbox); 03732 strsep(&cntx, "@"); 03733 if (ast_strlen_zero(cntx)) 03734 cntx = "default"; 03735 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 03736 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 03737 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 03738 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 03739 AST_EVENT_IE_END); 03740 } 03741 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 03742 e->msgstate = -1; 03743 e->amaflags = amaflags; 03744 e->capability = capability; 03745 e->parent = gw; 03746 e->dtmfmode = dtmfmode; 03747 if (!ep_reload && e->sub && e->sub->rtp) 03748 e->dtmfmode |= MGCP_DTMF_INBAND; 03749 e->adsi = adsi; 03750 e->type = TYPE_LINE; 03751 e->immediate = immediate; 03752 e->callgroup=cur_callergroup; 03753 e->pickupgroup=cur_pickupgroup; 03754 e->callreturn = callreturn; 03755 e->cancallforward = cancallforward; 03756 e->singlepath = singlepath; 03757 e->directmedia = directmedia; 03758 e->callwaiting = callwaiting; 03759 e->hascallwaiting = callwaiting; 03760 e->slowsequence = slowsequence; 03761 e->transfer = transfer; 03762 e->threewaycalling = threewaycalling; 03763 e->onhooktime = time(NULL); 03764 /* ASSUME we're onhook */ 03765 e->hookstate = MGCP_ONHOOK; 03766 if (!ep_reload) { 03767 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 03768 for (i = 0; i < MAX_SUBS; i++) { 03769 sub = ast_calloc(1, sizeof(*sub)); 03770 if (sub) { 03771 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 03772 ast_mutex_init(&sub->lock); 03773 ast_mutex_init(&sub->cx_queue_lock); 03774 sub->parent = e; 03775 sub->id = i; 03776 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 03777 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 03778 sub->cxmode = MGCP_CX_INACTIVE; 03779 sub->nat = nat; 03780 sub->next = e->sub; 03781 e->sub = sub; 03782 } else { 03783 /* XXX Should find a way to clean up our memory */ 03784 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 03785 return NULL; 03786 } 03787 } 03788 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 03789 sub = e->sub; 03790 /* find the end of the list */ 03791 while(sub->next){ 03792 sub = sub->next; 03793 } 03794 /* set the last sub->next to the first sub */ 03795 sub->next = e->sub; 03796 03797 e->next = gw->endpoints; 03798 gw->endpoints = e; 03799 } 03800 } 03801 } else if (!strcasecmp(v->name, "trunk") || 03802 !strcasecmp(v->name, "line")) { 03803 03804 /* locate existing endpoint */ 03805 e = gw->endpoints; 03806 while (e) { 03807 if (!strcasecmp(v->value, e->name)) { 03808 /* endpoint already exists */ 03809 e->delme = 0; 03810 ep_reload = 1; 03811 break; 03812 } 03813 e = e->next; 03814 } 03815 03816 if (!e) { 03817 e = ast_calloc(1, sizeof(*e)); 03818 ep_reload = 0; 03819 } 03820 03821 if (e) { 03822 if (!ep_reload) { 03823 ast_mutex_init(&e->lock); 03824 ast_mutex_init(&e->rqnt_queue_lock); 03825 ast_mutex_init(&e->cmd_queue_lock); 03826 ast_copy_string(e->name, v->value, sizeof(e->name)); 03827 e->needaudit = 1; 03828 } 03829 /* XXX Should we really check for uniqueness?? XXX */ 03830 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 03831 ast_copy_string(e->context, context, sizeof(e->context)); 03832 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 03833 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 03834 ast_copy_string(e->language, language, sizeof(e->language)); 03835 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 03836 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 03837 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 03838 if (!ast_strlen_zero(mailbox)) { 03839 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 03840 } 03841 if (!ep_reload) { 03842 /* XXX potential issue due to reload */ 03843 e->msgstate = -1; 03844 e->parent = gw; 03845 } 03846 e->amaflags = amaflags; 03847 e->capability = capability; 03848 e->dtmfmode = dtmfmode; 03849 e->adsi = adsi; 03850 if (!strcasecmp(v->name, "trunk")) 03851 e->type = TYPE_TRUNK; 03852 else 03853 e->type = TYPE_LINE; 03854 03855 e->immediate = immediate; 03856 e->callgroup=cur_callergroup; 03857 e->pickupgroup=cur_pickupgroup; 03858 e->callreturn = callreturn; 03859 e->cancallforward = cancallforward; 03860 e->directmedia = directmedia; 03861 e->singlepath = singlepath; 03862 e->callwaiting = callwaiting; 03863 e->hascallwaiting = callwaiting; 03864 e->slowsequence = slowsequence; 03865 e->transfer = transfer; 03866 e->threewaycalling = threewaycalling; 03867 if (!ep_reload) { 03868 e->onhooktime = time(NULL); 03869 /* ASSUME we're onhook */ 03870 e->hookstate = MGCP_ONHOOK; 03871 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 03872 } 03873 03874 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 03875 if (!ep_reload) { 03876 sub = ast_calloc(1, sizeof(*sub)); 03877 } else { 03878 if (!sub) 03879 sub = e->sub; 03880 else 03881 sub = sub->next; 03882 } 03883 03884 if (sub) { 03885 if (!ep_reload) { 03886 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 03887 ast_mutex_init(&sub->lock); 03888 ast_mutex_init(&sub->cx_queue_lock); 03889 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 03890 sub->parent = e; 03891 sub->id = i; 03892 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 03893 sub->cxmode = MGCP_CX_INACTIVE; 03894 sub->next = e->sub; 03895 e->sub = sub; 03896 } 03897 sub->nat = nat; 03898 } else { 03899 /* XXX Should find a way to clean up our memory */ 03900 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 03901 return NULL; 03902 } 03903 } 03904 if (!ep_reload) { 03905 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 03906 sub = e->sub; 03907 /* find the end of the list */ 03908 while (sub->next) { 03909 sub = sub->next; 03910 } 03911 /* set the last sub->next to the first sub */ 03912 sub->next = e->sub; 03913 03914 e->next = gw->endpoints; 03915 gw->endpoints = e; 03916 } 03917 } 03918 } else 03919 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 03920 v = v->next; 03921 } 03922 } 03923 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 03924 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 03925 if (!gw_reload) { 03926 ast_mutex_destroy(&gw->msgs_lock); 03927 ast_free(gw); 03928 } 03929 return NULL; 03930 } 03931 gw->defaddr.sin_family = AF_INET; 03932 gw->addr.sin_family = AF_INET; 03933 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 03934 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 03935 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) 03936 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 03937 if (gw->addr.sin_addr.s_addr) 03938 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) 03939 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 03940 03941 return (gw_reload ? NULL : gw); 03942 }
| static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1394 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().
01394 { 01395 switch (ind) { 01396 case AST_CONTROL_HANGUP: 01397 return "Other end has hungup"; 01398 case AST_CONTROL_RING: 01399 return "Local ring"; 01400 case AST_CONTROL_RINGING: 01401 return "Remote end is ringing"; 01402 case AST_CONTROL_ANSWER: 01403 return "Remote end has answered"; 01404 case AST_CONTROL_BUSY: 01405 return "Remote end is busy"; 01406 case AST_CONTROL_TAKEOFFHOOK: 01407 return "Make it go off hook"; 01408 case AST_CONTROL_OFFHOOK: 01409 return "Line is off hook"; 01410 case AST_CONTROL_CONGESTION: 01411 return "Congestion (circuits busy)"; 01412 case AST_CONTROL_FLASH: 01413 return "Flash hook"; 01414 case AST_CONTROL_WINK: 01415 return "Wink"; 01416 case AST_CONTROL_OPTION: 01417 return "Set a low-level option"; 01418 case AST_CONTROL_RADIO_KEY: 01419 return "Key Radio"; 01420 case AST_CONTROL_RADIO_UNKEY: 01421 return "Un-Key Radio"; 01422 } 01423 return "UNKNOWN"; 01424 }
| static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 3977 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().
03978 { 03979 struct mgcp_subchannel *sub = e->sub->next, *s; 03980 int i; 03981 03982 for (i = 0; i < MAX_SUBS; i++) { 03983 ast_mutex_lock(&sub->lock); 03984 if (!ast_strlen_zero(sub->cxident)) { 03985 transmit_connection_del(sub); 03986 } 03987 if (sub->rtp) { 03988 ast_rtp_destroy(sub->rtp); 03989 sub->rtp = NULL; 03990 } 03991 memset(sub->magic, 0, sizeof(sub->magic)); 03992 mgcp_queue_hangup(sub); 03993 dump_cmd_queues(NULL, sub); 03994 ast_mutex_unlock(&sub->lock); 03995 sub = sub->next; 03996 } 03997 03998 if (e->dsp) { 03999 ast_dsp_free(e->dsp); 04000 } 04001 04002 dump_queue(e->parent, e); 04003 dump_cmd_queues(e, NULL); 04004 04005 sub = e->sub; 04006 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04007 s = sub; 04008 sub = sub->next; 04009 ast_mutex_destroy(&s->lock); 04010 ast_mutex_destroy(&s->cx_queue_lock); 04011 ast_free(s); 04012 } 04013 04014 if (e->mwi_event_sub) 04015 ast_event_unsubscribe(e->mwi_event_sub); 04016 04017 ast_mutex_destroy(&e->lock); 04018 ast_mutex_destroy(&e->rqnt_queue_lock); 04019 ast_mutex_destroy(&e->cmd_queue_lock); 04020 ast_free(e); 04021 }
| static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4023 of file chan_mgcp.c.
References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.
Referenced by prune_gateways().
04024 { 04025 if (g->ha) 04026 ast_free_ha(g->ha); 04027 04028 dump_queue(g, NULL); 04029 04030 ast_free(g); 04031 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3383 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().
03384 { 03385 int res; 03386 int reloading; 03387 /*struct mgcp_gateway *g;*/ 03388 /*struct mgcp_endpoint *e;*/ 03389 /*time_t thispass = 0, lastpass = 0;*/ 03390 03391 /* Add an I/O event to our UDP socket */ 03392 if (mgcpsock > -1) 03393 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03394 03395 /* This thread monitors all the frame relay interfaces which are not yet in use 03396 (and thus do not have a separate thread) indefinitely */ 03397 /* From here on out, we die whenever asked */ 03398 for(;;) { 03399 /* Check for a reload request */ 03400 ast_mutex_lock(&mgcp_reload_lock); 03401 reloading = mgcp_reloading; 03402 mgcp_reloading = 0; 03403 ast_mutex_unlock(&mgcp_reload_lock); 03404 if (reloading) { 03405 ast_verb(1, "Reloading MGCP\n"); 03406 reload_config(1); 03407 /* Add an I/O event to our UDP socket */ 03408 if (mgcpsock > -1 && !mgcpsock_read_id) { 03409 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03410 } 03411 } 03412 03413 /* Check for interfaces needing to be killed */ 03414 /* Don't let anybody kill us right away. Nobody should lock the interface list 03415 and wait for the monitor list, but the other way around is okay. */ 03416 ast_mutex_lock(&monlock); 03417 /* Lock the network interface */ 03418 ast_mutex_lock(&netlock); 03419 03420 #if 0 03421 /* XXX THIS IS COMPLETELY HOSED */ 03422 /* The gateway goes into a state of panic */ 03423 /* If the vmwi indicator is sent while it is reseting interfaces */ 03424 lastpass = thispass; 03425 thispass = time(NULL); 03426 g = gateways; 03427 while(g) { 03428 if (thispass != lastpass) { 03429 e = g->endpoints; 03430 while(e) { 03431 if (e->type == TYPE_LINE) { 03432 res = has_voicemail(e); 03433 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03434 if (res) { 03435 transmit_notify_request(e, "L/vmwi(+)"); 03436 } else { 03437 transmit_notify_request(e, "L/vmwi(-)"); 03438 } 03439 e->msgstate = res; 03440 e->onhooktime = thispass; 03441 } 03442 } 03443 e = e->next; 03444 } 03445 } 03446 g = g->next; 03447 } 03448 #endif 03449 /* Okay, now that we know what to do, release the network lock */ 03450 ast_mutex_unlock(&netlock); 03451 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03452 ast_mutex_unlock(&monlock); 03453 pthread_testcancel(); 03454 /* Wait for sched or io */ 03455 res = ast_sched_wait(sched); 03456 /* copied from chan_sip.c */ 03457 if ((res < 0) || (res > 1000)) 03458 res = 1000; 03459 res = ast_io_wait(io, res); 03460 ast_mutex_lock(&monlock); 03461 if (res >= 0) 03462 ast_sched_runq(sched); 03463 ast_mutex_unlock(&monlock); 03464 } 03465 /* Never reached */ 03466 return NULL; 03467 }
| static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub | |||
| ) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2388 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().
02389 { 02390 struct mgcp_request *t, *q; 02391 02392 if (p) { 02393 ast_mutex_lock(&p->rqnt_queue_lock); 02394 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); 02395 p->rqnt_queue = NULL; 02396 ast_mutex_unlock(&p->rqnt_queue_lock); 02397 02398 ast_mutex_lock(&p->cmd_queue_lock); 02399 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); 02400 p->cmd_queue = NULL; 02401 ast_mutex_unlock(&p->cmd_queue_lock); 02402 02403 ast_mutex_lock(&p->sub->cx_queue_lock); 02404 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02405 p->sub->cx_queue = NULL; 02406 ast_mutex_unlock(&p->sub->cx_queue_lock); 02407 02408 ast_mutex_lock(&p->sub->next->cx_queue_lock); 02409 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); 02410 p->sub->next->cx_queue = NULL; 02411 ast_mutex_unlock(&p->sub->next->cx_queue_lock); 02412 } else if (sub) { 02413 ast_mutex_lock(&sub->cx_queue_lock); 02414 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02415 sub->cx_queue = NULL; 02416 ast_mutex_unlock(&sub->cx_queue_lock); 02417 } 02418 }
| 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 3262 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().
03263 { 03264 int seqno=0; 03265 time_t now; 03266 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL; 03267 time(&now); 03268 if (sscanf(req->identifier, "%30d", &seqno) != 1) 03269 seqno = 0; 03270 cur = sub->parent->parent->responses; 03271 while(cur) { 03272 next = cur->next; 03273 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03274 /* Delete this entry */ 03275 if (prev) 03276 prev->next = next; 03277 else 03278 sub->parent->parent->responses = next; 03279 ast_free(cur); 03280 } else { 03281 if (seqno == cur->seqno) 03282 answer = cur; 03283 prev = cur; 03284 } 03285 cur = next; 03286 } 03287 if (answer) { 03288 resend_response(sub, answer); 03289 return 1; 03290 } 03291 return 0; 03292 }
| 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 2422 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().
02424 { 02425 struct mgcp_request *prev, *req; 02426 02427 ast_mutex_lock(l); 02428 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02429 if (req->trid == ident) { 02430 /* remove from queue */ 02431 if (!prev) 02432 *queue = req->next; 02433 else 02434 prev->next = req->next; 02435 02436 /* send next pending command */ 02437 if (*queue) { 02438 if (mgcpdebug) { 02439 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02440 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02441 } 02442 02443 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02444 } 02445 break; 02446 } 02447 } 02448 ast_mutex_unlock(l); 02449 return req; 02450 }
| static struct mgcp_subchannel* find_subchannel_and_lock | ( | char * | name, | |
| int | msgid, | |||
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 1625 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().
01626 { 01627 struct mgcp_endpoint *p = NULL; 01628 struct mgcp_subchannel *sub = NULL; 01629 struct mgcp_gateway *g; 01630 char tmp[256] = ""; 01631 char *at = NULL, *c; 01632 int found = 0; 01633 if (name) { 01634 ast_copy_string(tmp, name, sizeof(tmp)); 01635 at = strchr(tmp, '@'); 01636 if (!at) { 01637 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); 01638 return NULL; 01639 } 01640 *at++ = '\0'; 01641 } 01642 ast_mutex_lock(&gatelock); 01643 if (at && (at[0] == '[')) { 01644 at++; 01645 c = strrchr(at, ']'); 01646 if (c) 01647 *c = '\0'; 01648 } 01649 g = gateways; 01650 while(g) { 01651 if ((!name || !strcasecmp(g->name, at)) && 01652 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { 01653 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ 01654 if (sin && g->dynamic && name) { 01655 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01656 (g->addr.sin_port != sin->sin_port)) { 01657 memcpy(&g->addr, sin, sizeof(g->addr)); 01658 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip)) 01659 memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 01660 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)); 01661 } 01662 } 01663 /* not dynamic, check if the name matches */ 01664 else if (name) { 01665 if (strcasecmp(g->name, at)) { 01666 g = g->next; 01667 continue; 01668 } 01669 } 01670 /* not dynamic, no name, check if the addr matches */ 01671 else if (!name && sin) { 01672 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01673 (g->addr.sin_port != sin->sin_port)) { 01674 g = g->next; 01675 continue; 01676 } 01677 } else { 01678 g = g->next; 01679 continue; 01680 } 01681 /* SC */ 01682 p = g->endpoints; 01683 while(p) { 01684 ast_debug(1, "Searching on %s@%s for subchannel\n", 01685 p->name, g->name); 01686 if (msgid) { 01687 #if 0 /* new transport mech */ 01688 sub = p->sub; 01689 do { 01690 ast_debug(1, "Searching on %s@%s-%d for subchannel with lastout: %d\n", 01691 p->name, g->name, sub->id, msgid); 01692 if (sub->lastout == msgid) { 01693 ast_debug(1, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", 01694 sub->id, msgid, sub->lastout); 01695 found = 1; 01696 break; 01697 } 01698 sub = sub->next; 01699 } while (sub != p->sub); 01700 if (found) { 01701 break; 01702 } 01703 #endif 01704 /* SC */ 01705 sub = p->sub; 01706 found = 1; 01707 /* SC */ 01708 break; 01709 } else if (name && !strcasecmp(p->name, tmp)) { 01710 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 01711 p->name, g->name, p->sub->id); 01712 sub = p->sub; 01713 found = 1; 01714 break; 01715 } 01716 p = p->next; 01717 } 01718 if (sub && found) { 01719 ast_mutex_lock(&sub->lock); 01720 break; 01721 } 01722 } 01723 g = g->next; 01724 } 01725 ast_mutex_unlock(&gatelock); 01726 if (!sub) { 01727 if (name) { 01728 if (g) 01729 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); 01730 else 01731 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); 01732 } 01733 } 01734 return sub; 01735 }
| static char* get_csv | ( | char * | c, | |
| int * | len, | |||
| char ** | next | |||
| ) | [static] |
get_csv: (SC:) get comma separated value
Definition at line 1604 of file chan_mgcp.c.
References s.
Referenced by handle_response().
01605 { 01606 char *s; 01607 01608 *next = NULL, *len = 0; 01609 if (!c) return NULL; 01610 01611 while (*c && (*c < 33 || *c == ',')) 01612 c++; 01613 01614 s = c; 01615 while (*c && (*c >= 33 && *c != ',')) 01616 c++, (*len)++; 01617 *next = c; 01618 01619 if (*len == 0) 01620 s = NULL, *next = NULL; 01621 01622 return s; 01623 }
| static char* get_header | ( | struct mgcp_request * | req, | |
| char * | name | |||
| ) | [static] |
Definition at line 1597 of file chan_mgcp.c.
References __get_header().
Referenced by handle_request(), and handle_response().
01598 { 01599 int start = 0; 01600 return __get_header(req, name, &start); 01601 }
| static char* get_sdp | ( | struct mgcp_request * | req, | |
| char * | name | |||
| ) | [static] |
Definition at line 1549 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 1539 of file chan_mgcp.c.
Referenced by get_sdp(), and get_sdp_iterate().
01540 { 01541 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { 01542 char* r = line + nameLen + 1; 01543 while (*r && (*r < 33)) ++r; 01544 return r; 01545 } 01546 return ""; 01547 }
| static char* get_sdp_iterate | ( | int * | iterator, | |
| struct mgcp_request * | req, | |||
| char * | name | |||
| ) | [static] |
Definition at line 1567 of file chan_mgcp.c.
References get_sdp_by_line(), len(), and mgcp_request::line.
Referenced by process_sdp().
| static void handle_hd_hf | ( | struct mgcp_subchannel * | sub, | |
| char * | ev | |||
| ) | [static] |
Definition at line 2938 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().
02939 { 02940 struct mgcp_endpoint *p = sub->parent; 02941 struct ast_channel *c; 02942 pthread_t t; 02943 02944 /* Off hook / answer */ 02945 if (sub->outgoing) { 02946 /* Answered */ 02947 if (sub->owner) { 02948 if (ast_bridged_channel(sub->owner)) 02949 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 02950 sub->cxmode = MGCP_CX_SENDRECV; 02951 if (!sub->rtp) { 02952 start_rtp(sub); 02953 } else { 02954 transmit_modify_request(sub); 02955 } 02956 /*transmit_notify_request(sub, "aw");*/ 02957 transmit_notify_request(sub, ""); 02958 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 02959 } 02960 } else { 02961 /* Start switch */ 02962 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 02963 if (!sub->owner) { 02964 if (!sub->rtp) { 02965 start_rtp(sub); 02966 } else { 02967 transmit_modify_request(sub); 02968 } 02969 if (p->immediate) { 02970 /* The channel is immediately up. Start right away */ 02971 #ifdef DLINK_BUGGY_FIRMWARE 02972 transmit_notify_request(sub, "rt"); 02973 #else 02974 transmit_notify_request(sub, "G/rt"); 02975 #endif 02976 c = mgcp_new(sub, AST_STATE_RING); 02977 if (!c) { 02978 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 02979 transmit_notify_request(sub, "G/cg"); 02980 ast_hangup(c); 02981 } 02982 } else { 02983 if (has_voicemail(p)) { 02984 transmit_notify_request(sub, "L/sl"); 02985 } else { 02986 transmit_notify_request(sub, "L/dl"); 02987 } 02988 c = mgcp_new(sub, AST_STATE_DOWN); 02989 if (c) { 02990 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { 02991 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 02992 ast_hangup(c); 02993 } 02994 } else { 02995 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 02996 } 02997 } 02998 } else { 02999 if (p->hookstate == MGCP_OFFHOOK) { 03000 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03001 } else { 03002 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03003 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 03004 } 03005 if (ast_bridged_channel(sub->owner)) 03006 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03007 sub->cxmode = MGCP_CX_SENDRECV; 03008 if (!sub->rtp) { 03009 start_rtp(sub); 03010 } else { 03011 transmit_modify_request(sub); 03012 } 03013 /*transmit_notify_request(sub, "aw");*/ 03014 transmit_notify_request(sub, ""); 03015 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03016 } 03017 } 03018 }
| 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 1142 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.
01143 { 01144 switch (cmd) { 01145 case CLI_INIT: 01146 e->command = "mgcp set debug {on|off}"; 01147 e->usage = 01148 "Usage: mgcp set debug {on|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 != e->args) 01156 return CLI_SHOWUSAGE; 01157 01158 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 01159 mgcpdebug = 1; 01160 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01161 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01162 mgcpdebug = 0; 01163 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01164 } else { 01165 return CLI_SHOWUSAGE; 01166 } 01167 return CLI_SUCCESS; 01168 }
| 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 3020 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().
03021 { 03022 char *ev, *s; 03023 struct ast_frame f = { 0, }; 03024 struct mgcp_endpoint *p = sub->parent; 03025 struct mgcp_gateway *g = NULL; 03026 int res; 03027 03028 if (mgcpdebug) { 03029 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03030 } 03031 /* Clear out potential response */ 03032 if (!strcasecmp(req->verb, "RSIP")) { 03033 /* Test if this RSIP request is just a keepalive */ 03034 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03035 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03036 transmit_response(sub, "200", req, "OK"); 03037 } else { 03038 dump_queue(p->parent, p); 03039 dump_cmd_queues(p, NULL); 03040 03041 if ((strcmp(p->name, p->parent->wcardep) != 0)) { 03042 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); 03043 } 03044 /* For RSIP on wildcard we reset all endpoints */ 03045 if (!strcmp(p->name, p->parent->wcardep)) { 03046 /* Reset all endpoints */ 03047 struct mgcp_endpoint *tmp_ep; 03048 03049 g = p->parent; 03050 tmp_ep = g->endpoints; 03051 while (tmp_ep) { 03052 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03053 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03054 struct mgcp_subchannel *tmp_sub, *first_sub; 03055 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03056 03057 first_sub = tmp_ep->sub; 03058 tmp_sub = tmp_ep->sub; 03059 while (tmp_sub) { 03060 mgcp_queue_hangup(tmp_sub); 03061 tmp_sub = tmp_sub->next; 03062 if (tmp_sub == first_sub) 03063 break; 03064 } 03065 } 03066 tmp_ep = tmp_ep->next; 03067 } 03068 } else if (sub->owner) { 03069 mgcp_queue_hangup(sub); 03070 } 03071 transmit_response(sub, "200", req, "OK"); 03072 /* We dont send NTFY or AUEP to wildcard ep */ 03073 if (strcmp(p->name, p->parent->wcardep) != 0) { 03074 transmit_notify_request(sub, ""); 03075 /* Audit endpoint. 03076 Idea is to prevent lost lines due to race conditions 03077 */ 03078 transmit_audit_endpoint(p); 03079 } 03080 } 03081 } else if (!strcasecmp(req->verb, "NTFY")) { 03082 /* Acknowledge and be sure we keep looking for the same things */ 03083 transmit_response(sub, "200", req, "OK"); 03084 /* Notified of an event */ 03085 ev = get_header(req, "O"); 03086 s = strchr(ev, '/'); 03087 if (s) ev = s + 1; 03088 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03089 /* Keep looking for events unless this was a hangup */ 03090 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03091 transmit_notify_request(sub, p->curtone); 03092 } 03093 if (!strcasecmp(ev, "hd")) { 03094 p->hookstate = MGCP_OFFHOOK; 03095 sub->cxmode = MGCP_CX_SENDRECV; 03096 handle_hd_hf(sub, ev); 03097 } else if (!strcasecmp(ev, "hf")) { 03098 /* We can assume we are offhook if we received a hookflash */ 03099 /* First let's just do call wait and ignore threeway */ 03100 /* We're currently in charge */ 03101 if (p->hookstate != MGCP_OFFHOOK) { 03102 /* Cisco c7940 sends hf even if the phone is onhook */ 03103 /* Thanks to point on IRC for pointing this out */ 03104 return -1; 03105 } 03106 /* do not let * conference two down channels */ 03107 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) 03108 return -1; 03109 03110 if (p->callwaiting || p->transfer || p->threewaycalling) { 03111 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03112 p->sub = p->sub->next; 03113 03114 /* transfer control to our next subchannel */ 03115 if (!sub->next->owner) { 03116 /* plave the first call on hold and start up a new call */ 03117 sub->cxmode = MGCP_CX_MUTE; 03118 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03119 transmit_modify_request(sub); 03120 if (sub->owner && ast_bridged_channel(sub->owner)) 03121 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03122 sub->next->cxmode = MGCP_CX_RECVONLY; 03123 handle_hd_hf(sub->next, ev); 03124 } else if (sub->owner && sub->next->owner) { 03125 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03126 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03127 /* We made both calls lets conferenct */ 03128 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", 03129 sub->id, sub->next->id, p->name, p->parent->name); 03130 sub->cxmode = MGCP_CX_CONF; 03131 sub->next->cxmode = MGCP_CX_CONF; 03132 if (ast_bridged_channel(sub->next->owner)) 03133 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03134 transmit_modify_request(sub); 03135 transmit_modify_request(sub->next); 03136 } else { 03137 /* Let's flipflop between calls */ 03138 /* XXX Need to check for state up ??? */ 03139 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03140 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03141 sub->id, sub->next->id, p->name, p->parent->name); 03142 sub->cxmode = MGCP_CX_MUTE; 03143 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03144 transmit_modify_request(sub); 03145 if (ast_bridged_channel(sub->owner)) 03146 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03147 03148 if (ast_bridged_channel(sub->next->owner)) 03149 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03150 03151 handle_hd_hf(sub->next, ev); 03152 } 03153 } else { 03154 /* We've most likely lost one of our calls find an active call and bring it up */ 03155 if (sub->owner) { 03156 p->sub = sub; 03157 } else if (sub->next->owner) { 03158 p->sub = sub->next; 03159 } else { 03160 /* We seem to have lost both our calls */ 03161 /* XXX - What do we do now? */ 03162 return -1; 03163 } 03164 if (ast_bridged_channel(p->sub->owner)) 03165 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03166 p->sub->cxmode = MGCP_CX_SENDRECV; 03167 transmit_modify_request(p->sub); 03168 } 03169 } else { 03170 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03171 p->name, p->parent->name); 03172 } 03173 } else if (!strcasecmp(ev, "hu")) { 03174 p->hookstate = MGCP_ONHOOK; 03175 sub->cxmode = MGCP_CX_RECVONLY; 03176 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03177 /* Do we need to send MDCX before a DLCX ? 03178 if (sub->rtp) { 03179 transmit_modify_request(sub); 03180 } 03181 */ 03182 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03183 /* We're allowed to transfer, we have two avtive calls and */ 03184 /* we made at least one of the calls. Let's try and transfer */ 03185 ast_mutex_lock(&p->sub->next->lock); 03186 res = attempt_transfer(p); 03187 if (res < 0) { 03188 if (p->sub->next->owner) { 03189 sub->next->alreadygone = 1; 03190 mgcp_queue_hangup(sub->next); 03191 } 03192 } else if (res) { 03193 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03194 ast_mutex_unlock(&p->sub->next->lock); 03195 return -1; 03196 } 03197 ast_mutex_unlock(&p->sub->next->lock); 03198 } else { 03199 /* Hangup the current call */ 03200 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03201 if (sub->owner) { 03202 sub->alreadygone = 1; 03203 mgcp_queue_hangup(sub); 03204 } else { 03205 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03206 p->name, p->parent->name, sub->id); 03207 /* Instruct the other side to remove the connection since it apparently * 03208 * still thinks the channel is active. * 03209 * For Cisco IAD2421 /BAK/ */ 03210 transmit_connection_del(sub); 03211 } 03212 } 03213 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03214 p->hidecallerid = 0; 03215 if (p->hascallwaiting && !p->callwaiting) { 03216 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03217 p->callwaiting = -1; 03218 } 03219 if (has_voicemail(p)) { 03220 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03221 transmit_notify_request(sub, "L/vmwi(+)"); 03222 } else { 03223 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03224 transmit_notify_request(sub, "L/vmwi(-)"); 03225 } 03226 } 03227 } else if ((strlen(ev) == 1) && 03228 (((ev[0] >= '0') && (ev[0] <= '9')) || 03229 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03230 (ev[0] == '*') || (ev[0] == '#'))) { 03231 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) { 03232 f.frametype = AST_FRAME_DTMF; 03233 f.subclass = ev[0]; 03234 f.src = "mgcp"; 03235 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03236 mgcp_queue_frame(sub, &f); 03237 ast_mutex_lock(&sub->next->lock); 03238 if (sub->next->owner) 03239 mgcp_queue_frame(sub->next, &f); 03240 ast_mutex_unlock(&sub->next->lock); 03241 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) { 03242 memset(p->curtone, 0, sizeof(p->curtone)); 03243 } 03244 } else { 03245 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; 03246 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; 03247 } 03248 } else if (!strcasecmp(ev, "T")) { 03249 /* Digit timeout -- unimportant */ 03250 } else if (!strcasecmp(ev, "ping")) { 03251 /* ping -- unimportant */ 03252 } else { 03253 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03254 } 03255 } else { 03256 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03257 transmit_response(sub, "510", req, "Unknown verb"); 03258 } 03259 return 0; 03260 }
| 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 2453 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().
02455 { 02456 char *c; 02457 struct mgcp_request *req; 02458 struct mgcp_gateway *gw = p->parent; 02459 02460 if (result < 200) { 02461 /* provisional response */ 02462 return; 02463 } 02464 02465 if (p->slowsequence) 02466 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02467 else if (sub) 02468 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02469 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02470 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02471 02472 if (!req) { 02473 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", 02474 gw->name, ident); 02475 return; 02476 } 02477 02478 if (p && (result >= 400) && (result <= 599)) { 02479 switch (result) { 02480 case 401: 02481 p->hookstate = MGCP_OFFHOOK; 02482 break; 02483 case 402: 02484 p->hookstate = MGCP_ONHOOK; 02485 break; 02486 case 406: 02487 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02488 break; 02489 case 407: 02490 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02491 break; 02492 } 02493 if (sub) { 02494 if (sub->owner) { 02495 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02496 result, p->name, p->parent->name, sub ? sub->id:-1); 02497 mgcp_queue_hangup(sub); 02498 } 02499 } else { 02500 if (p->sub->next->owner) { 02501 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02502 result, p->name, p->parent->name, sub ? sub->id:-1); 02503 mgcp_queue_hangup(p->sub); 02504 } 02505 02506 if (p->sub->owner) { 02507 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02508 result, p->name, p->parent->name, sub ? sub->id:-1); 02509 mgcp_queue_hangup(p->sub); 02510 } 02511 02512 dump_cmd_queues(p, NULL); 02513 } 02514 } 02515 02516 if (resp) { 02517 if (req->cmd == MGCP_CMD_CRCX) { 02518 if ((c = get_header(resp, "I"))) { 02519 if (!ast_strlen_zero(c) && sub) { 02520 /* if we are hanging up do not process this conn. */ 02521 if (sub->owner) { 02522 if (!ast_strlen_zero(sub->cxident)) { 02523 if (strcasecmp(c, sub->cxident)) { 02524 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02525 } 02526 } 02527 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02528 if (sub->tmpdest.sin_addr.s_addr) { 02529 transmit_modify_with_sdp(sub, NULL, 0); 02530 } 02531 } else { 02532 /* XXX delete this one 02533 callid and conn id may already be lost. 02534 so the following del conn may have a side effect of 02535 cleaning up the next subchannel */ 02536 transmit_connection_del(sub); 02537 } 02538 } 02539 } 02540 } 02541 02542 if (req->cmd == MGCP_CMD_AUEP) { 02543 /* check stale connection ids */ 02544 if ((c = get_header(resp, "I"))) { 02545 char *v, *n; 02546 int len; 02547 while ((v = get_csv(c, &len, &n))) { 02548 if (len) { 02549 if (strncasecmp(v, p->sub->cxident, len) && 02550 strncasecmp(v, p->sub->next->cxident, len)) { 02551 /* connection id not found. delete it */ 02552 char cxident[80] = ""; 02553 02554 if (len > (sizeof(cxident) - 1)) 02555 len = sizeof(cxident) - 1; 02556 ast_copy_string(cxident, v, len); 02557 ast_verb(3, "Non existing connection id %s on %s@%s \n", 02558 cxident, p->name, gw->name); 02559 transmit_connection_del_w_params(p, NULL, cxident); 02560 } 02561 } 02562 c = n; 02563 } 02564 } 02565 02566 /* Try to determine the hookstate returned from an audit endpoint command */ 02567 if ((c = get_header(resp, "ES"))) { 02568 if (!ast_strlen_zero(c)) { 02569 if (strstr(c, "hu")) { 02570 if (p->hookstate != MGCP_ONHOOK) { 02571 /* XXX cleanup if we think we are offhook XXX */ 02572 if ((p->sub->owner || p->sub->next->owner ) && 02573 p->hookstate == MGCP_OFFHOOK) 02574 mgcp_queue_hangup(sub); 02575 p->hookstate = MGCP_ONHOOK; 02576 02577 /* update the requested events according to the new hookstate */ 02578 transmit_notify_request(p->sub, ""); 02579 02580 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02581 } 02582 } else if (strstr(c, "hd")) { 02583 if (p->hookstate != MGCP_OFFHOOK) { 02584 p->hookstate = MGCP_OFFHOOK; 02585 02586 /* update the requested events according to the new hookstate */ 02587 transmit_notify_request(p->sub, ""); 02588 02589 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02590 } 02591 } 02592 } 02593 } 02594 } 02595 02596 if (resp && resp->lines) { 02597 /* do not process sdp if we are hanging up. this may be a late response */ 02598 if (sub && sub->owner) { 02599 if (!sub->rtp) 02600 start_rtp(sub); 02601 if (sub->rtp) 02602 process_sdp(sub, resp); 02603 } 02604 } 02605 } 02606 02607 ast_free(req); 02608 }
| 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_strlen_zero(), mgcp_endpoint::mailbox, and mbox().
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 1986 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().
01987 { 01988 /* Initialize a response */ 01989 if (req->headers || req->len) { 01990 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 01991 return -1; 01992 } 01993 req->header[req->headers] = req->data + req->len; 01994 /* check if we need brackets around the gw name */ 01995 if (p->parent->isnamedottedip) 01996 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); 01997 else 01998 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); 01999 req->len += strlen(req->header[req->headers]); 02000 if (req->headers < MGCP_MAX_HEADERS) 02001 req->headers++; 02002 else 02003 ast_log(LOG_WARNING, "Out of header space\n"); 02004 return 0; 02005 }
| static int init_resp | ( | struct mgcp_request * | req, | |
| char * | resp, | |||
| struct mgcp_request * | orig, | |||
| char * | resprest | |||
| ) | [static] |
Definition at line 1969 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().
01970 { 01971 /* Initialize a response */ 01972 if (req->headers || req->len) { 01973 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 01974 return -1; 01975 } 01976 req->header[req->headers] = req->data + req->len; 01977 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 01978 req->len += strlen(req->header[req->headers]); 01979 if (req->headers < MGCP_MAX_HEADERS) 01980 req->headers++; 01981 else 01982 ast_log(LOG_WARNING, "Out of header space\n"); 01983 return 0; 01984 }
| static int load_module | ( | void | ) | [static] |
load_module: PBX load module - initialization ---
Definition at line 4256 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().
04257 { 04258 if (!(sched = sched_context_create())) { 04259 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 04260 return AST_MODULE_LOAD_FAILURE; 04261 } 04262 04263 if (!(io = io_context_create())) { 04264 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 04265 sched_context_destroy(sched); 04266 return AST_MODULE_LOAD_FAILURE; 04267 } 04268 04269 if (reload_config(0)) 04270 return AST_MODULE_LOAD_DECLINE; 04271 04272 /* Make sure we can register our mgcp channel type */ 04273 if (ast_channel_register(&mgcp_tech)) { 04274 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); 04275 io_context_destroy(io); 04276 sched_context_destroy(sched); 04277 return AST_MODULE_LOAD_FAILURE; 04278 } 04279 04280 ast_rtp_proto_register(&mgcp_rtp); 04281 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04282 04283 /* And start the monitor for the first time */ 04284 restart_monitor(); 04285 04286 return AST_MODULE_LOAD_SUCCESS; 04287 }
| static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1177 of file chan_mgcp.c.
References ast_channel::_state, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verb, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_subchannel::lock, MGCP_CX_SENDRECV, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01178 { 01179 int res = 0; 01180 struct mgcp_subchannel *sub = ast->tech_pvt; 01181 struct mgcp_endpoint *p = sub->parent; 01182 01183 ast_mutex_lock(&sub->lock); 01184 sub->cxmode = MGCP_CX_SENDRECV; 01185 if (!sub->rtp) { 01186 start_rtp(sub); 01187 } else { 01188 transmit_modify_request(sub); 01189 } 01190 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", 01191 ast->name, p->name, p->parent->name, sub->id); 01192 if (ast->_state != AST_STATE_UP) { 01193 ast_setstate(ast, AST_STATE_UP); 01194 ast_debug(1, "mgcp_answer(%s)\n", ast->name); 01195 transmit_notify_request(sub, ""); 01196 transmit_modify_request(sub); 01197 } 01198 ast_mutex_unlock(&sub->lock); 01199 return res; 01200 }
| 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, ast_var_t::entries, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, and ast_channel::varshead.
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 1346 of file chan_mgcp.c.
References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock(), ast_mutex_unlock(), mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, and mgcp_gateway::next.
01347 { 01348 struct mgcp_gateway *g; 01349 struct mgcp_endpoint *e = NULL; 01350 char *tmp, *endpt, *gw; 01351 int ret = AST_DEVICE_INVALID; 01352 01353 endpt = ast_strdupa(data); 01354 if ((tmp = strchr(endpt, '@'))) { 01355 *tmp++ = '\0'; 01356 gw = tmp; 01357 } else 01358 goto error; 01359 01360 ast_mutex_lock(&gatelock); 01361 g = gateways; 01362 while (g) { 01363 if (strcasecmp(g->name, gw) == 0) { 01364 e = g->endpoints; 01365 break; 01366 } 01367 g = g->next; 01368 } 01369 01370 if (!e) 01371 goto error; 01372 01373 while (e) { 01374 if (strcasecmp(e->name, endpt) == 0) 01375 break; 01376 e = e->next; 01377 } 01378 01379 if (!e) 01380 goto error; 01381 01382 /* 01383 * As long as the gateway/endpoint is valid, we'll 01384 * assume that the device is available and its state 01385 * can be tracked. 01386 */ 01387 ret = AST_DEVICE_UNKNOWN; 01388 01389 error: 01390 ast_mutex_unlock(&gatelock); 01391 return ret; 01392 }
| static int mgcp_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 1273 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, ast_channel::name, mgcp_subchannel::owner, and ast_channel::tech_pvt.
01274 { 01275 struct mgcp_subchannel *sub = newchan->tech_pvt; 01276 01277 ast_mutex_lock(&sub->lock); 01278 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name); 01279 if (sub->owner != oldchan) { 01280 ast_mutex_unlock(&sub->lock); 01281 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01282 return -1; 01283 } 01284 sub->owner = newchan; 01285 ast_mutex_unlock(&sub->lock); 01286 return 0; 01287 }
| static enum ast_rtp_get_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp ** | rtp | |||
| ) | [static] |
Definition at line 3944 of file chan_mgcp.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, mgcp_endpoint::directmedia, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
03945 { 03946 struct mgcp_subchannel *sub = NULL; 03947 03948 if (!(sub = chan->tech_pvt) || !(sub->rtp)) 03949 return AST_RTP_GET_FAILED; 03950 03951 *rtp = sub->rtp; 03952 03953 if (sub->parent->directmedia) 03954 return AST_RTP_TRY_NATIVE; 03955 else 03956 return AST_RTP_TRY_PARTIAL; 03957 }
| 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, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
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 1426 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, ast_channel::name, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_notify_request().
01427 { 01428 struct mgcp_subchannel *sub = ast->tech_pvt; 01429 int res = 0; 01430 01431 if (mgcpdebug) { 01432 ast_verb(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", 01433 ind, control2str(ind), ast->name); 01434 } 01435 ast_mutex_lock(&sub->lock); 01436 switch(ind) { 01437 case AST_CONTROL_RINGING: 01438 #ifdef DLINK_BUGGY_FIRMWARE 01439 transmit_notify_request(sub, "rt"); 01440 #else 01441 transmit_notify_request(sub, "G/rt"); 01442 #endif 01443 break; 01444 case AST_CONTROL_BUSY: 01445 transmit_notify_request(sub, "L/bz"); 01446 break; 01447 case AST_CONTROL_CONGESTION: 01448 transmit_notify_request(sub, "G/cg"); 01449 break; 01450 case AST_CONTROL_HOLD: 01451 ast_moh_start(ast, data, NULL); 01452 break; 01453 case AST_CONTROL_UNHOLD: 01454 ast_moh_stop(ast); 01455 break; 01456 case AST_CONTROL_SRCUPDATE: 01457 ast_rtp_new_source(sub->rtp); 01458 break; 01459 case -1: 01460 transmit_notify_request(sub, ""); 01461 break; 01462 default: 01463 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); 01464 res = -1; 01465 } 01466 ast_mutex_unlock(&sub->lock); 01467 return res; 01468 }
| static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, | |
| int | state | |||
| ) | [static, read] |
Definition at line 1470 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, ast_channel::name, name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by handle_hd_hf(), and mgcp_request().
01471 { 01472 struct ast_channel *tmp; 01473 struct mgcp_endpoint *i = sub->parent; 01474 int fmt; 01475 01476 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); 01477 if (tmp) { 01478 tmp->tech = &mgcp_tech; 01479 tmp->nativeformats = i->capability; 01480 if (!tmp->nativeformats) 01481 tmp->nativeformats = capability; 01482 fmt = ast_best_codec(tmp->nativeformats); 01483 ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); 01484 if (sub->rtp) 01485 ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp)); 01486 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { 01487 i->dsp = ast_dsp_new(); 01488 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); 01489 /* this is to prevent clipping of dtmf tones during dsp processing */ 01490 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); 01491 } else { 01492 i->dsp = NULL; 01493 } 01494 if (state == AST_STATE_RING) 01495 tmp->rings = 1; 01496 tmp->writeformat = fmt; 01497 tmp->rawwriteformat = fmt; 01498 tmp->readformat = fmt; 01499 tmp->rawreadformat = fmt; 01500 tmp->tech_pvt = sub; 01501 if (!ast_strlen_zero(i->language)) 01502 ast_string_field_set(tmp, language, i->language); 01503 if (!ast_strlen_zero(i->accountcode)) 01504 ast_string_field_set(tmp, accountcode, i->accountcode); 01505 if (i->amaflags) 01506 tmp->amaflags = i->amaflags; 01507 sub->owner = tmp; 01508 ast_module_ref(ast_module_info->self); 01509 tmp->callgroup = i->callgroup; 01510 tmp->pickupgroup = i->pickupgroup; 01511 ast_string_field_set(tmp, call_forward, i->call_forward); 01512 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 01513 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 01514 01515 /* Don't use ast_set_callerid() here because it will 01516 * generate a needless NewCallerID event */ 01517 tmp->cid.cid_ani = ast_strdup(i->cid_num); 01518 01519 if (!i->adsi) 01520 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01521 tmp->priority = 1; 01522 if (sub->rtp) 01523 ast_jb_configure(tmp, &global_jbconf); 01524 if (state != AST_STATE_DOWN) { 01525 if (ast_pbx_start(tmp)) { 01526 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 01527 ast_hangup(tmp); 01528 tmp = NULL; 01529 } 01530 } 01531 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", 01532 tmp->name, ast_state2str(state)); 01533 } else { 01534 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01535 } 01536 return tmp; 01537 }
| 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 1233 of file chan_mgcp.c.
References ast_mutex_lock(), ast_mutex_unlock(), f, mgcp_subchannel::lock, mgcp_rtp_read(), and ast_channel::tech_pvt.
01234 { 01235 struct ast_frame *f; 01236 struct mgcp_subchannel *sub = ast->tech_pvt; 01237 ast_mutex_lock(&sub->lock); 01238 f = mgcp_rtp_read(sub); 01239 ast_mutex_unlock(&sub->lock); 01240 return f; 01241 }
| static char * mgcp_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4289 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().
04290 { 04291 static int deprecated = 0; 04292 04293 if (e) { 04294 switch (cmd) { 04295 case CLI_INIT: 04296 e->command = "mgcp reload"; 04297 e->usage = 04298 "Usage: mgcp reload\n" 04299 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; 04300 return NULL; 04301 case CLI_GENERATE: 04302 return NULL; 04303 } 04304 } 04305 04306 if (!deprecated && a && a->argc > 0) { 04307 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); 04308 deprecated = 1; 04309 } 04310 04311 ast_mutex_lock(&mgcp_reload_lock); 04312 if (mgcp_reloading) { 04313 ast_verbose("Previous mgcp reload not yet done\n"); 04314 } else 04315 mgcp_reloading = 1; 04316 ast_mutex_unlock(&mgcp_reload_lock); 04317 restart_monitor(); 04318 return CLI_SUCCESS; 04319 }
| static struct ast_channel * mgcp_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 3498 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().
03499 { 03500 int oldformat; 03501 struct mgcp_subchannel *sub; 03502 struct ast_channel *tmpc = NULL; 03503 char tmp[256]; 03504 char *dest = data; 03505 03506 oldformat = format; 03507 format &= capability; 03508 if (!format) { 03509 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); 03510 return NULL; 03511 } 03512 ast_copy_string(tmp, dest, sizeof(tmp)); 03513 if (ast_strlen_zero(tmp)) { 03514 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); 03515 return NULL; 03516 } 03517 sub = find_subchannel_and_lock(tmp, 0, NULL); 03518 if (!sub) { 03519 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); 03520 *cause = AST_CAUSE_UNREGISTERED; 03521 return NULL; 03522 } 03523 03524 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); 03525 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 03526 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); 03527 /* Must be busy */ 03528 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || 03529 ((!sub->parent->callwaiting) && (sub->owner)) || 03530 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { 03531 if (sub->parent->hookstate == MGCP_ONHOOK) { 03532 if (has_voicemail(sub->parent)) { 03533 transmit_notify_request(sub,"L/vmwi(+)"); 03534 } else { 03535 transmit_notify_request(sub,"L/vmwi(-)"); 03536 } 03537 } 03538 *cause = AST_CAUSE_BUSY; 03539 ast_mutex_unlock(&sub->lock); 03540 return NULL; 03541 } 03542 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN); 03543 ast_mutex_unlock(&sub->lock); 03544 if (!tmpc) 03545 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); 03546 restart_monitor(); 03547 return tmpc; 03548 }
| static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static, read] |
Definition at line 1202 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().
01203 { 01204 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ 01205 struct ast_frame *f; 01206 01207 f = ast_rtp_read(sub->rtp); 01208 /* Don't send RFC2833 if we're not supposed to */ 01209 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) 01210 return &ast_null_frame; 01211 if (sub->owner) { 01212 /* We already hold the channel lock */ 01213 if (f->frametype == AST_FRAME_VOICE) { 01214 if (f->subclass != sub->owner->nativeformats) { 01215 ast_debug(1, "Oooh, format changed to %d\n", f->subclass); 01216 sub->owner->nativeformats = f->subclass; 01217 ast_set_read_format(sub->owner, sub->owner->readformat); 01218 ast_set_write_format(sub->owner, sub->owner->writeformat); 01219 } 01220 /* Courtesy fearnor aka alex@pilosoft.com */ 01221 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { 01222 #if 0 01223 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); 01224 #endif 01225 f = ast_dsp_process(sub->owner, sub->parent->dsp, f); 01226 } 01227 } 01228 } 01229 return f; 01230 }
| static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1289 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.
01290 { 01291 struct mgcp_subchannel *sub = ast->tech_pvt; 01292 struct mgcp_endpoint *p = sub->parent; 01293 int res = 0; 01294 01295 ast_mutex_lock(&sub->lock); 01296 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01297 ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n"); 01298 res = -1; /* Let asterisk play inband indications */ 01299 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01300 ast_log(LOG_DEBUG, "Sending DTMF using RFC2833"); 01301 ast_rtp_senddigit_begin(sub->rtp, digit); 01302 } else { 01303 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01304 } 01305 ast_mutex_unlock(&sub->lock); 01306 01307 return res; 01308 }
| static int mgcp_senddigit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1310 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().
01311 { 01312 struct mgcp_subchannel *sub = ast->tech_pvt; 01313 struct mgcp_endpoint *p = sub->parent; 01314 int res = 0; 01315 char tmp[4]; 01316 01317 ast_mutex_lock(&sub->lock); 01318 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01319 ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n"); 01320 res = -1; /* Tell Asterisk to stop inband indications */ 01321 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01322 ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n"); 01323 tmp[0] = 'D'; 01324 tmp[1] = '/'; 01325 tmp[2] = digit; 01326 tmp[3] = '\0'; 01327 transmit_notify_request(sub, tmp); 01328 ast_rtp_senddigit_end(sub->rtp, digit); 01329 } else { 01330 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01331 } 01332 ast_mutex_unlock(&sub->lock); 01333 01334 return res; 01335 }
| 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 3959 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_channel::tech_pvt, and transmit_modify_with_sdp().
03960 { 03961 /* XXX Is there such thing as video support with MGCP? XXX */ 03962 struct mgcp_subchannel *sub; 03963 sub = chan->tech_pvt; 03964 if (sub && !sub->alreadygone) { 03965 transmit_modify_with_sdp(sub, rtp, codecs); 03966 return 0; 03967 } 03968 return -1; 03969 }
| static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2637 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, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, 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().
02638 { 02639 struct ast_channel *chan = data; 02640 struct mgcp_subchannel *sub = chan->tech_pvt; 02641 struct mgcp_endpoint *p = sub->parent; 02642 /* char exten[AST_MAX_EXTENSION] = ""; */ 02643 int len = 0; 02644 int timeout = firstdigittimeout; 02645 int res= 0; 02646 int getforward = 0; 02647 int loop_pause = 100; 02648 02649 len = strlen(p->dtmf_buf); 02650 02651 while(len < AST_MAX_EXTENSION-1) { 02652 res = 1; /* Assume that we will get a digit */ 02653 while (strlen(p->dtmf_buf) == len){ 02654 ast_safe_sleep(chan, loop_pause); 02655 timeout -= loop_pause; 02656 if (timeout <= 0){ 02657 res = 0; 02658 break; 02659 } 02660 res = 1; 02661 } 02662 02663 timeout = 0; 02664 len = strlen(p->dtmf_buf); 02665 02666 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) { 02667 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02668 ast_indicate(chan, -1); 02669 } else { 02670 /* XXX Redundant? We should already be playing dialtone */ 02671 /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02672 transmit_notify_request(sub, "L/dl"); 02673 } 02674 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02675 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02676 if (getforward) { 02677 /* Record this as the forwarding extension */ 02678 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 02679 ast_verb(3, "Setting call forward to '%s' on channel %s\n", 02680 p->call_forward, chan->name); 02681 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02682 transmit_notify_request(sub, "L/sl"); 02683 if (res) 02684 break; 02685 usleep(500000); 02686 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02687 ast_indicate(chan, -1); 02688 sleep(1); 02689 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02690 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02691 transmit_notify_request(sub, "L/dl"); 02692 len = 0; 02693 getforward = 0; 02694 } else { 02695 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02696 ast_indicate(chan, -1); 02697 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten)); 02698 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02699 ast_set_callerid(chan, 02700 p->hidecallerid ? "" : p->cid_num, 02701 p->hidecallerid ? "" : p->cid_name, 02702 chan->cid.cid_ani ? NULL : p->cid_num); 02703 ast_setstate(chan, AST_STATE_RING); 02704 /*dahdi_enable_ec(p);*/ 02705 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 02706 p->dtmfmode |= MGCP_DTMF_INBAND; 02707 ast_indicate(chan, -1); 02708 } 02709 res = ast_pbx_run(chan); 02710 if (res) { 02711 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 02712 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 02713 /*transmit_notify_request(p, "nbz", 1);*/ 02714 transmit_notify_request(sub, "G/cg"); 02715 } 02716 return NULL; 02717 } 02718 } else { 02719 /* It's a match, but they just typed a digit, and there is an ambiguous match, 02720 so just set the timeout to matchdigittimeout and wait some more */ 02721 timeout = matchdigittimeout; 02722 } 02723 } else if (res == 0) { 02724 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 02725 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 02726 transmit_notify_request(sub, "G/cg"); 02727 /*dahdi_wait_event(p->subs[index].zfd);*/ 02728 ast_hangup(chan); 02729 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02730 return NULL; 02731 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { 02732 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 02733 /* Disable call waiting if enabled */ 02734 p->callwaiting = 0; 02735 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02736 transmit_notify_request(sub, "L/sl"); 02737 len = 0; 02738 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02739 timeout = firstdigittimeout; 02740 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { 02741 /* Scan all channels and see if any there 02742 * ringing channqels with that have call groups 02743 * that equal this channels pickup group 02744 */ 02745 if (ast_pickup_call(chan)) { 02746 ast_log(LOG_WARNING, "No call pickup possible...\n"); 02747 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 02748 transmit_notify_request(sub, "G/cg"); 02749 } 02750 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02751 ast_hangup(chan); 02752 return NULL; 02753 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { 02754 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 02755 /* Disable Caller*ID if enabled */ 02756 p->hidecallerid = 1; 02757 ast_set_callerid(chan, "", "", NULL); 02758 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02759 transmit_notify_request(sub, "L/sl"); 02760 len = 0; 02761 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02762 timeout = firstdigittimeout; 02763 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { 02764 res = 0; 02765 if (!ast_strlen_zero(p->lastcallerid)) { 02766 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language); 02767 } 02768 if (!res) 02769 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02770 transmit_notify_request(sub, "L/sl"); 02771 break; 02772 } else if (!strcmp(p->dtmf_buf, "*78")) { 02773 /* Do not disturb */ 02774 ast_verb(3, "Enabled DND on channel %s\n", chan->name); 02775 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02776 transmit_notify_request(sub, "L/sl"); 02777 p->dnd = 1; 02778 getforward = 0; 02779 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02780 len = 0; 02781 } else if (!strcmp(p->dtmf_buf, "*79")) { 02782 /* Do not disturb */ 02783 ast_verb(3, "Disabled DND on channel %s\n", chan->name); 02784 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02785 transmit_notify_request(sub, "L/sl"); 02786 p->dnd = 0; 02787 getforward = 0; 02788 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02789 len = 0; 02790 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { 02791 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02792 transmit_notify_request(sub, "L/sl"); 02793 getforward = 1; 02794 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02795 len = 0; 02796 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { 02797 ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name); 02798 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02799 transmit_notify_request(sub, "L/sl"); 02800 memset(p->call_forward, 0, sizeof(p->call_forward)); 02801 getforward = 0; 02802 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02803 len = 0; 02804 } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) && 02805 sub->next->owner && ast_bridged_channel(sub->next->owner)) { 02806 /* This is a three way call, the main call being a real channel, 02807 and we're parking the first call. */ 02808 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL); 02809 ast_verb(3, "Parking call to '%s'\n", chan->name); 02810 break; 02811 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { 02812 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); 02813 res = ast_db_put("blacklist", p->lastcallerid, "1"); 02814 if (!res) { 02815 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02816 transmit_notify_request(sub, "L/sl"); 02817 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02818 len = 0; 02819 } 02820 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { 02821 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 02822 /* Enable Caller*ID if enabled */ 02823 p->hidecallerid = 0; 02824 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 02825 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02826 transmit_notify_request(sub, "L/sl"); 02827 len = 0; 02828 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02829 timeout = firstdigittimeout; 02830 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) && 02831 ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 02832 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); 02833 break; 02834 } 02835 if (!timeout) 02836 timeout = gendigittimeout; 02837 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf)) 02838 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02839 ast_indicate(chan, -1); 02840 } 02841 #if 0 02842 for (;;) { 02843 res = ast_waitfordigit(chan, to); 02844 if (!res) { 02845 ast_debug(1, "Timeout...\n"); 02846 break; 02847 } 02848 if (res < 0) { 02849 ast_debug(1, "Got hangup...\n"); 02850 ast_hangup(chan); 02851 break; 02852 } 02853 exten[pos++] = res; 02854 if (!ast_ignore_pattern(chan->context, exten)) 02855 ast_indicate(chan, -1); 02856 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { 02857 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 02858 to = 3000; 02859 else 02860 to = 8000; 02861 } else 02862 break; 02863 } 02864 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { 02865 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); 02866 if (!p->rtp) { 02867 start_rtp(p); 02868 } 02869 ast_setstate(chan, AST_STATE_RING); 02870 chan->rings = 1; 02871 if (ast_pbx_run(chan)) { 02872 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); 02873 } else { 02874 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02875 return NULL; 02876 } 02877 } 02878 #endif 02879 ast_hangup(chan); 02880 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 02881 return NULL; 02882 }
| static int mgcp_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 1243 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.
01244 { 01245 struct mgcp_subchannel *sub = ast->tech_pvt; 01246 int res = 0; 01247 if (frame->frametype != AST_FRAME_VOICE) { 01248 if (frame->frametype == AST_FRAME_IMAGE) 01249 return 0; 01250 else { 01251 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); 01252 return 0; 01253 } 01254 } else { 01255 if (!(frame->subclass & ast->nativeformats)) { 01256 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 01257 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat); 01258 return -1; 01259 } 01260 } 01261 if (sub) { 01262 ast_mutex_lock(&sub->lock); 01263 if ((sub->parent->sub == sub) || !sub->parent->singlepath) { 01264 if (sub->rtp) { 01265 res = ast_rtp_write(sub->rtp, frame); 01266 } 01267 } 01268 ast_mutex_unlock(&sub->lock); 01269 } 01270 return res; 01271 }
| static int mgcpsock_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | ignore | |||
| ) | [static] |
Definition at line 3294 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().
03295 { 03296 struct mgcp_request req; 03297 struct sockaddr_in sin; 03298 struct mgcp_subchannel *sub; 03299 int res; 03300 socklen_t len; 03301 int result; 03302 int ident; 03303 len = sizeof(sin); 03304 memset(&req, 0, sizeof(req)); 03305 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 03306 if (res < 0) { 03307 if (errno != ECONNREFUSED) 03308 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 03309 return 1; 03310 } 03311 req.data[res] = '\0'; 03312 req.len = res; 03313 if (mgcpdebug) { 03314 ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 03315 } 03316 parse(&req); 03317 if (req.headers < 1) { 03318 /* Must have at least one header */ 03319 return 1; 03320 } 03321 if (ast_strlen_zero(req.identifier)) { 03322 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); 03323 return 1; 03324 } 03325 03326 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { 03327 /* Try to find who this message is for, if it's important */ 03328 sub = find_subchannel_and_lock(NULL, ident, &sin); 03329 if (sub) { 03330 struct mgcp_gateway *gw = sub->parent->parent; 03331 struct mgcp_message *cur, *prev; 03332 03333 ast_mutex_unlock(&sub->lock); 03334 ast_mutex_lock(&gw->msgs_lock); 03335 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 03336 if (cur->seqno == ident) { 03337 ast_debug(1, "Got response back on transaction %d\n", ident); 03338 if (prev) 03339 prev->next = cur->next; 03340 else 03341 gw->msgs = cur->next; 03342 break; 03343 } 03344 } 03345 03346 /* stop retrans timer if the queue is empty */ 03347 if (!gw->msgs) { 03348 AST_SCHED_DEL(sched, gw->retransid); 03349 } 03350 03351 ast_mutex_unlock(&gw->msgs_lock); 03352 if (cur) { 03353 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); 03354 ast_free(cur); 03355 return 1; 03356 } 03357 03358 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 03359 gw->name, ident); 03360 } 03361 } else { 03362 if (ast_strlen_zero(req.endpoint) || 03363 ast_strlen_zero(req.version) || 03364 ast_strlen_zero(req.verb)) { 03365 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); 03366 return 1; 03367 } 03368 /* Process request, with iflock held */ 03369 sub = find_subchannel_and_lock(req.endpoint, 0, &sin); 03370 if (sub) { 03371 /* look first to find a matching response in the queue */ 03372 if (!find_and_retrans(sub, &req)) 03373 /* pass the request off to the currently mastering subchannel */ 03374 handle_request(sub, &req, &sin); 03375 ast_mutex_unlock(&sub->lock); 03376 } 03377 } 03378 return 1; 03379 }
| 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 1737 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(), confbridge_exec(), config_function_read(), cut_internal(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), 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(), originate_exec(), oss_call(), oss_request(), page_exec(), park_call_exec(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_waitexten(), play_moh_exec(), pqm_exec(), privacy_exec(), ql_exec(), queue_exec(), rcvfax_exec(), record_exec(), reload_agents(), reload_single_member(), 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().
01738 { 01739 /* Divide fields by NULL's */ 01740 char *c; 01741 int f = 0; 01742 c = req->data; 01743 01744 /* First header starts immediately */ 01745 req->header[f] = c; 01746 while(*c) { 01747 if (*c == '\n') { 01748 /* We've got a new header */ 01749 *c = 0; 01750 #if 0 01751 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f])); 01752 #endif 01753 if (ast_strlen_zero(req->header[f])) { 01754 /* Line by itself means we're now in content */ 01755 c++; 01756 break; 01757 } 01758 if (f >= MGCP_MAX_HEADERS - 1) { 01759 ast_log(LOG_WARNING, "Too many MGCP headers...\n"); 01760 } else 01761 f++; 01762 req->header[f] = c + 1; 01763 } else if (*c == '\r') { 01764 /* Ignore but eliminate \r's */ 01765 *c = 0; 01766 } 01767 c++; 01768 } 01769 /* Check for last header */ 01770 if (!ast_strlen_zero(req->header[f])) 01771 f++; 01772 req->headers = f; 01773 /* Now we process any mime content */ 01774 f = 0; 01775 req->line[f] = c; 01776 while(*c) { 01777 if (*c == '\n') { 01778 /* We've got a new line */ 01779 *c = 0; 01780 #if 0 01781 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f])); 01782 #endif 01783 if (f >= MGCP_MAX_LINES - 1) { 01784 ast_log(LOG_WARNING, "Too many SDP lines...\n"); 01785 } else 01786 f++; 01787 req->line[f] = c + 1; 01788 } else if (*c == '\r') { 01789 /* Ignore and eliminate \r's */ 01790 *c = 0; 01791 } 01792 c++; 01793 } 01794 /* Check for last line */ 01795 if (!ast_strlen_zero(req->line[f])) 01796 f++; 01797 req->lines = f; 01798 /* Parse up the initial header */ 01799 c = req->header[0]; 01800 while(*c && *c < 33) c++; 01801 /* First the verb */ 01802 req->verb = c; 01803 while(*c && (*c > 32)) c++; 01804 if (*c) { 01805 *c = '\0'; 01806 c++; 01807 while(*c && (*c < 33)) c++; 01808 req->identifier = c; 01809 while(*c && (*c > 32)) c++; 01810 if (*c) { 01811 *c = '\0'; 01812 c++; 01813 while(*c && (*c < 33)) c++; 01814 req->endpoint = c; 01815 while(*c && (*c > 32)) c++; 01816 if (*c) { 01817 *c = '\0'; 01818 c++; 01819 while(*c && (*c < 33)) c++; 01820 req->version = c; 01821 while(*c && (*c > 32)) c++; 01822 while(*c && (*c < 33)) c++; 01823 while(*c && (*c > 32)) c++; 01824 *c = '\0'; 01825 } 01826 } 01827 } 01828 01829 if (mgcpdebug) { 01830 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", 01831 req->verb, req->identifier, req->endpoint, req->version); 01832 ast_verbose("%d headers, %d lines\n", req->headers, req->lines); 01833 } 01834 if (*c) 01835 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); 01836 }
| static int process_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 1838 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_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().
01839 { 01840 char *m; 01841 char *c; 01842 char *a; 01843 char host[258]; 01844 int len; 01845 int portno; 01846 int peercapability, peerNonCodecCapability; 01847 struct sockaddr_in sin; 01848 char *codecs; 01849 struct ast_hostent ahp; struct hostent *hp; 01850 int codec, codec_count=0; 01851 int iterator; 01852 struct mgcp_endpoint *p = sub->parent; 01853 01854 /* Get codec and RTP info from SDP */ 01855 m = get_sdp(req, "m"); 01856 c = get_sdp(req, "c"); 01857 if (ast_strlen_zero(m) || ast_strlen_zero(c)) { 01858 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); 01859 return -1; 01860 } 01861 if (sscanf(c, "IN IP4 %256s", host) != 1) { 01862 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 01863 return -1; 01864 } 01865 /* XXX This could block for a long time, and block the main thread! XXX */ 01866 hp = ast_gethostbyname(host, &ahp); 01867 if (!hp) { 01868 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); 01869 return -1; 01870 } 01871 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) { 01872 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 01873 return -1; 01874 } 01875 sin.sin_family = AF_INET; 01876 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01877 sin.sin_port = htons(portno); 01878 ast_rtp_set_peer(sub->rtp, &sin); 01879 #if 0 01880 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 01881 #endif 01882 /* Scan through the RTP payload types specified in a "m=" line: */ 01883 ast_rtp_pt_clear(sub->rtp); 01884 codecs = ast_strdupa(m + len); 01885 while (!ast_strlen_zero(codecs)) { 01886 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) { 01887 if (codec_count) 01888 break; 01889 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs); 01890 return -1; 01891 } 01892 ast_rtp_set_m_type(sub->rtp, codec); 01893 codec_count++; 01894 codecs += len; 01895 } 01896 01897 /* Next, scan through each "a=rtpmap:" line, noting each */ 01898 /* specified RTP payload type (with corresponding MIME subtype): */ 01899 sdpLineNum_iterator_init(&iterator); 01900 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 01901 char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */ 01902 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2) 01903 continue; 01904 /* Note: should really look at the 'freq' and '#chans' params too */ 01905 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0); 01906 } 01907 01908 /* Now gather all of the codecs that were asked for: */ 01909 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability); 01910 p->capability = capability & peercapability; 01911 if (mgcpdebug) { 01912 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n", 01913 capability, peercapability, p->capability); 01914 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n", 01915 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); 01916 } 01917 if (!p->capability) { 01918 ast_log(LOG_WARNING, "No compatible codecs!\n"); 01919 return -1; 01920 } 01921 return 0; 01922 }
| static void prune_gateways | ( | void | ) | [static] |
Definition at line 4033 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().
04034 { 04035 struct mgcp_gateway *g, *z, *r; 04036 struct mgcp_endpoint *e, *p, *t; 04037 04038 ast_mutex_lock(&gatelock); 04039 04040 /* prune gateways */ 04041 for (z = NULL, g = gateways; g;) { 04042 /* prune endpoints */ 04043 for (p = NULL, e = g->endpoints; e; ) { 04044 if (e->delme || g->delme) { 04045 t = e; 04046 e = e->next; 04047 if (!p) 04048 g->endpoints = e; 04049 else 04050 p->next = e; 04051 destroy_endpoint(t); 04052 } else { 04053 p = e; 04054 e = e->next; 04055 } 04056 } 04057 04058 if (g->delme) { 04059 r = g; 04060 g = g->next; 04061 if (!z) 04062 gateways = g; 04063 else 04064 z->next = g; 04065 04066 destroy_gateway(r); 04067 } else { 04068 z = g; 04069 g = g->next; 04070 } 04071 } 04072 04073 ast_mutex_unlock(&gatelock); 04074 }
| static int reload | ( | void | ) | [static] |
Definition at line 4321 of file chan_mgcp.c.
References mgcp_reload().
04322 { 04323 mgcp_reload(NULL, 0, NULL); 04324 return 0; 04325 }
| static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4076 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_FILEINVALID, 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_ERROR, 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().
04077 { 04078 struct ast_config *cfg; 04079 struct ast_variable *v; 04080 struct mgcp_gateway *g; 04081 struct mgcp_endpoint *e; 04082 char *cat; 04083 struct ast_hostent ahp; 04084 struct hostent *hp; 04085 int format; 04086 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04087 04088 if (gethostname(ourhost, sizeof(ourhost)-1)) { 04089 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); 04090 return 0; 04091 } 04092 cfg = ast_config_load(config, config_flags); 04093 04094 /* We *must* have a config file otherwise stop immediately */ 04095 if (!cfg) { 04096 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); 04097 return 0; 04098 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 04099 return 0; 04100 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04101 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 04102 return 0; 04103 } 04104 04105 memset(&bindaddr, 0, sizeof(bindaddr)); 04106 dtmfmode = 0; 04107 04108 /* Copy the default jb config over global_jbconf */ 04109 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 04110 04111 v = ast_variable_browse(cfg, "general"); 04112 while (v) { 04113 /* handle jb conf */ 04114 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { 04115 v = v->next; 04116 continue; 04117 } 04118 04119 /* Create the interface list */ 04120 if (!strcasecmp(v->name, "bindaddr")) { 04121 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 04122 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 04123 } else { 04124 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 04125 } 04126 } else if (!strcasecmp(v->name, "allow")) { 04127 format = ast_getformatbyname(v->value); 04128 if (format < 1) 04129 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04130 else 04131 capability |= format; 04132 } else if (!strcasecmp(v->name, "disallow")) { 04133 format = ast_getformatbyname(v->value); 04134 if (format < 1) 04135 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value); 04136 else 04137 capability &= ~format; 04138 } else if (!strcasecmp(v->name, "tos")) { 04139 if (ast_str2tos(v->value, &qos.tos)) 04140 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04141 } else if (!strcasecmp(v->name, "tos_audio")) { 04142 if (ast_str2tos(v->value, &qos.tos_audio)) 04143 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04144 } else if (!strcasecmp(v->name, "cos")) { 04145 if (ast_str2cos(v->value, &qos.cos)) 04146 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 04147 } else if (!strcasecmp(v->name, "cos_audio")) { 04148 if (ast_str2cos(v->value, &qos.cos_audio)) 04149 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04150 } else if (!strcasecmp(v->name, "port")) { 04151 if (sscanf(v->value, "%5d", &ourport) == 1) { 04152 bindaddr.sin_port = htons(ourport); 04153 } else { 04154 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 04155 } 04156 } 04157 v = v->next; 04158 } 04159 04160 /* mark existing entries for deletion */ 04161 ast_mutex_lock(&gatelock); 04162 g = gateways; 04163 while (g) { 04164 g->delme = 1; 04165 e = g->endpoints; 04166 while (e) { 04167 e->delme = 1; 04168 e = e->next; 04169 } 04170 g = g->next; 04171 } 04172 ast_mutex_unlock(&gatelock); 04173 04174 cat = ast_category_browse(cfg, NULL); 04175 while(cat) { 04176 if (strcasecmp(cat, "general")) { 04177 ast_mutex_lock(&gatelock); 04178 g = build_gateway(cat, ast_variable_browse(cfg, cat)); 04179 if (g) { 04180 ast_verb(3, "Added gateway '%s'\n", g->name); 04181 g->next = gateways; 04182 gateways = g; 04183 } 04184 ast_mutex_unlock(&gatelock); 04185 04186 /* FS: process queue and IO */ 04187 if (monitor_thread == pthread_self()) { 04188 if (sched) ast_sched_runq(sched); 04189 if (io) ast_io_wait(io, 10); 04190 } 04191 } 04192 cat = ast_category_browse(cfg, cat); 04193 } 04194 04195 /* prune deleted entries etc. */ 04196 prune_gateways(); 04197 04198 if (ntohl(bindaddr.sin_addr.s_addr)) { 04199 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); 04200 } else { 04201 hp = ast_gethostbyname(ourhost, &ahp); 04202 if (!hp) { 04203 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); 04204 ast_config_destroy(cfg); 04205 return 0; 04206 } 04207 memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); 04208 } 04209 if (!ntohs(bindaddr.sin_port)) 04210 bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT); 04211 bindaddr.sin_family = AF_INET; 04212 ast_mutex_lock(&netlock); 04213 if (mgcpsock > -1) 04214 close(mgcpsock); 04215 04216 if (mgcpsock_read_id != NULL) 04217 ast_io_remove(io, mgcpsock_read_id); 04218 mgcpsock_read_id = NULL; 04219 04220 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); 04221 if (mgcpsock < 0) { 04222 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); 04223 } else { 04224 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 04225 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 04226 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 04227 strerror(errno)); 04228 close(mgcpsock); 04229 mgcpsock = -1; 04230 } else { 04231 ast_verb(2, "MGCP Listening on %s:%d\n", 04232 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 04233 ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); 04234 } 04235 } 04236 ast_mutex_unlock(&netlock); 04237 ast_config_destroy(cfg); 04238 04239 /* send audit only to the new endpoints */ 04240 g = gateways; 04241 while (g) { 04242 e = g->endpoints; 04243 while (e && e->needaudit) { 04244 e->needaudit = 0; 04245 transmit_audit_endpoint(e); 04246 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); 04247 e = e->next; 04248 } 04249 g = g->next; 04250 } 04251 04252 return 0; 04253 }
| static int reqprep | ( | struct mgcp_request * | req, | |
| struct mgcp_endpoint * | p, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2015 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 2008 of file chan_mgcp.c.
References init_resp().
Referenced by transmit_response().
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 3469 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().
03470 { 03471 /* If we're supposed to be stopped -- stay stopped */ 03472 if (monitor_thread == AST_PTHREADT_STOP) 03473 return 0; 03474 if (ast_mutex_lock(&monlock)) { 03475 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 03476 return -1; 03477 } 03478 if (monitor_thread == pthread_self()) { 03479 ast_mutex_unlock(&monlock); 03480 ast_log(LOG_WARNING, "Cannot kill myself\n"); 03481 return -1; 03482 } 03483 if (monitor_thread != AST_PTHREADT_NULL) { 03484 /* Wake up the thread */ 03485 pthread_kill(monitor_thread, SIGURG); 03486 } else { 03487 /* Start a new monitor */ 03488 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 03489 ast_mutex_unlock(&monlock); 03490 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 03491 return -1; 03492 } 03493 } 03494 ast_mutex_unlock(&monlock); 03495 return 0; 03496 }
| 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 1562 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 2610 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().
02611 { 02612 ast_mutex_lock(&sub->lock); 02613 /* check again to be on the safe side */ 02614 if (sub->rtp) { 02615 ast_rtp_destroy(sub->rtp); 02616 sub->rtp = NULL; 02617 } 02618 /* Allocate the RTP now */ 02619 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 02620 if (sub->rtp && sub->owner) 02621 ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp)); 02622 if (sub->rtp) { 02623 ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); 02624 ast_rtp_setnat(sub->rtp, sub->nat); 02625 } 02626 #if 0 02627 ast_rtp_set_callback(p->rtp, rtpready); 02628 ast_rtp_set_data(p->rtp, p); 02629 #endif 02630 /* Make a call*ID */ 02631 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); 02632 /* Transmit the connection create */ 02633 transmit_connect_with_sdp(sub, NULL); 02634 ast_mutex_unlock(&sub->lock); 02635 }
| static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2329 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().
02330 { 02331 struct mgcp_request resp; 02332 reqprep(&resp, p, "AUEP"); 02333 /* removed unknown param VS */ 02334 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ 02335 add_header(&resp, "F", "A"); 02336 /* fill in new fields */ 02337 resp.cmd = MGCP_CMD_AUEP; 02338 resp.trid = oseq; 02339 return send_request(p, NULL, &resp, oseq); /* SC */ 02340 }
| static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp * | rtp | |||
| ) | [static] |
Definition at line 2176 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().
02177 { 02178 struct mgcp_request resp; 02179 char local[256]; 02180 char tmp[80]; 02181 int x; 02182 struct mgcp_endpoint *p = sub->parent; 02183 02184 ast_copy_string(local, "p:20", sizeof(local)); 02185 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02186 if (p->capability & x) { 02187 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0)); 02188 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02189 } 02190 } 02191 if (mgcpdebug) { 02192 ast_verb(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02193 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02194 } 02195 reqprep(&resp, p, "CRCX"); 02196 add_header(&resp, "C", sub->callid); 02197 add_header(&resp, "L", local); 02198 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02199 /* X header should not be sent. kept for compatibility */ 02200 add_header(&resp, "X", sub->txident); 02201 /*add_header(&resp, "S", "");*/ 02202 add_sdp(&resp, sub, rtp); 02203 /* fill in new fields */ 02204 resp.cmd = MGCP_CMD_CRCX; 02205 resp.trid = oseq; 02206 return send_request(p, sub, &resp, oseq); /* SC */ 02207 }
| static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2342 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().
02343 { 02344 struct mgcp_endpoint *p = sub->parent; 02345 struct mgcp_request resp; 02346 02347 if (mgcpdebug) { 02348 ast_verb(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 02349 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02350 } 02351 reqprep(&resp, p, "DLCX"); 02352 /* check if call id is avail */ 02353 if (sub->callid[0]) 02354 add_header(&resp, "C", sub->callid); 02355 /* X header should not be sent. kept for compatibility */ 02356 add_header(&resp, "X", sub->txident); 02357 /* check if cxident is avail */ 02358 if (sub->cxident[0]) 02359 add_header(&resp, "I", sub->cxident); 02360 /* fill in new fields */ 02361 resp.cmd = MGCP_CMD_DLCX; 02362 resp.trid = oseq; 02363 return send_request(p, sub, &resp, oseq); /* SC */ 02364 }
| static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, | |
| char * | callid, | |||
| char * | cxident | |||
| ) | [static] |
Definition at line 2366 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().
02367 { 02368 struct mgcp_request resp; 02369 02370 if (mgcpdebug) { 02371 ast_verb(3, "Delete connection %s %s@%s on callid: %s\n", 02372 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); 02373 } 02374 reqprep(&resp, p, "DLCX"); 02375 /* check if call id is avail */ 02376 if (callid && *callid) 02377 add_header(&resp, "C", callid); 02378 /* check if cxident is avail */ 02379 if (cxident && *cxident) 02380 add_header(&resp, "I", cxident); 02381 /* fill in new fields */ 02382 resp.cmd = MGCP_CMD_DLCX; 02383 resp.trid = oseq; 02384 return send_request(p, p->sub, &resp, oseq); 02385 }
| static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2284 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().
02285 { 02286 struct mgcp_request resp; 02287 struct mgcp_endpoint *p = sub->parent; 02288 02289 if (ast_strlen_zero(sub->cxident)) { 02290 /* We don't have a CXident yet, store the destination and 02291 wait a bit */ 02292 return 0; 02293 } 02294 if (mgcpdebug) { 02295 ast_verb(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", 02296 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02297 } 02298 reqprep(&resp, p, "MDCX"); 02299 add_header(&resp, "C", sub->callid); 02300 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02301 /* X header should not be sent. kept for compatibility */ 02302 add_header(&resp, "X", sub->txident); 02303 add_header(&resp, "I", sub->cxident); 02304 switch (sub->parent->hookstate) { 02305 case MGCP_ONHOOK: 02306 add_header(&resp, "R", "L/hd(N)"); 02307 break; 02308 case MGCP_OFFHOOK: 02309 add_header_offhook(sub, &resp); 02310 break; 02311 } 02312 /* fill in new fields */ 02313 resp.cmd = MGCP_CMD_MDCX; 02314 resp.trid = oseq; 02315 return send_request(p, sub, &resp, oseq); /* SC */ 02316 }
| static int transmit_modify_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp * | rtp, | |||
| int | codecs | |||
| ) | [static] |
Definition at line 2140 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().
02141 { 02142 struct mgcp_request resp; 02143 char local[256]; 02144 char tmp[80]; 02145 int x; 02146 struct mgcp_endpoint *p = sub->parent; 02147 02148 if (ast_strlen_zero(sub->cxident) && rtp) { 02149 /* We don't have a CXident yet, store the destination and 02150 wait a bit */ 02151 ast_rtp_get_peer(rtp, &sub->tmpdest); 02152 return 0; 02153 } 02154 ast_copy_string(local, "p:20", sizeof(local)); 02155 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02156 if (p->capability & x) { 02157 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0)); 02158 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02159 } 02160 } 02161 reqprep(&resp, p, "MDCX"); 02162 add_header(&resp, "C", sub->callid); 02163 add_header(&resp, "L", local); 02164 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02165 /* X header should not be sent. kept for compatibility */ 02166 add_header(&resp, "X", sub->txident); 02167 add_header(&resp, "I", sub->cxident); 02168 /*add_header(&resp, "S", "");*/ 02169 add_sdp(&resp, sub, rtp); 02170 /* fill in new fields */ 02171 resp.cmd = MGCP_CMD_MDCX; 02172 resp.trid = oseq; 02173 return send_request(p, sub, &resp, oseq); /* SC */ 02174 }
| static int transmit_notify_request | ( | struct mgcp_subchannel * | sub, | |
| char * | tone | |||
| ) | [static] |
Definition at line 2209 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().
02210 { 02211 struct mgcp_request resp; 02212 struct mgcp_endpoint *p = sub->parent; 02213 02214 if (mgcpdebug) { 02215 ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02216 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02217 } 02218 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02219 reqprep(&resp, p, "RQNT"); 02220 add_header(&resp, "X", p->rqnt_ident); /* SC */ 02221 switch (p->hookstate) { 02222 case MGCP_ONHOOK: 02223 add_header(&resp, "R", "L/hd(N)"); 02224 break; 02225 case MGCP_OFFHOOK: 02226 add_header_offhook(sub, &resp); 02227 break; 02228 } 02229 if (!ast_strlen_zero(tone)) { 02230 add_header(&resp, "S", tone); 02231 } 02232 /* fill in new fields */ 02233 resp.cmd = MGCP_CMD_RQNT; 02234 resp.trid = oseq; 02235 return send_request(p, NULL, &resp, oseq); /* SC */ 02236 }
| static int transmit_notify_request_with_callerid | ( | struct mgcp_subchannel * | sub, | |
| char * | tone, | |||
| char * | callernum, | |||
| char * | callername | |||
| ) | [static] |
Definition at line 2238 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().
02239 { 02240 struct mgcp_request resp; 02241 char tone2[256]; 02242 char *l, *n; 02243 struct timeval t = ast_tvnow(); 02244 struct ast_tm tm; 02245 struct mgcp_endpoint *p = sub->parent; 02246 02247 ast_localtime(&t, &tm, NULL); 02248 n = callername; 02249 l = callernum; 02250 if (!n) 02251 n = ""; 02252 if (!l) 02253 l = ""; 02254 02255 /* Keep track of last callerid for blacklist and callreturn */ 02256 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid)); 02257 02258 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 02259 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n); 02260 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02261 reqprep(&resp, p, "RQNT"); 02262 add_header(&resp, "X", p->rqnt_ident); /* SC */ 02263 switch (p->hookstate) { 02264 case MGCP_ONHOOK: 02265 add_header(&resp, "R", "L/hd(N)"); 02266 break; 02267 case MGCP_OFFHOOK: 02268 add_header_offhook(sub, &resp); 02269 break; 02270 } 02271 if (!ast_strlen_zero(tone2)) { 02272 add_header(&resp, "S", tone2); 02273 } 02274 if (mgcpdebug) { 02275 ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02276 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02277 } 02278 /* fill in new fields */ 02279 resp.cmd = MGCP_CMD_RQNT; 02280 resp.trid = oseq; 02281 return send_request(p, NULL, &resp, oseq); /* SC */ 02282 }
| static int transmit_response | ( | struct mgcp_subchannel * | sub, | |
| char * | msg, | |||
| struct mgcp_request * | req, | |||
| char * | msgrest | |||
| ) | [static] |
Definition at line 2025 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().
02026 { 02027 struct mgcp_request resp; 02028 struct mgcp_endpoint *p = sub->parent; 02029 struct mgcp_response *mgr; 02030 02031 respprep(&resp, p, msg, req, msgrest); 02032 mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1); 02033 if (mgr) { 02034 /* Store MGCP response in case we have to retransmit */ 02035 sscanf(req->identifier, "%30d", &mgr->seqno); 02036 time(&mgr->whensent); 02037 mgr->len = resp.len; 02038 memcpy(mgr->buf, resp.data, resp.len); 02039 mgr->buf[resp.len] = '\0'; 02040 mgr->next = p->parent->responses; 02041 p->parent->responses = mgr; 02042 } 02043 return send_response(sub, &resp); 02044 }
| 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 4327 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().
04328 { 04329 struct mgcp_endpoint *e; 04330 struct mgcp_gateway *g; 04331 04332 /* Check to see if we're reloading */ 04333 if (ast_mutex_trylock(&mgcp_reload_lock)) { 04334 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n"); 04335 return -1; 04336 } else { 04337 mgcp_reloading = 1; 04338 ast_mutex_unlock(&mgcp_reload_lock); 04339 } 04340 04341 /* First, take us out of the channel loop */ 04342 ast_channel_unregister(&mgcp_tech); 04343 04344 /* Shut down the monitoring thread */ 04345 if (!ast_mutex_lock(&monlock)) { 04346 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { 04347 pthread_cancel(monitor_thread); 04348 pthread_kill(monitor_thread, SIGURG); 04349 pthread_join(monitor_thread, NULL); 04350 } 04351 monitor_thread = AST_PTHREADT_STOP; 04352 ast_mutex_unlock(&monlock); 04353 } else { 04354 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 04355 /* We always want to leave this in a consistent state */ 04356 ast_channel_register(&mgcp_tech); 04357 mgcp_reloading = 0; 04358 mgcp_reload(NULL, 0, NULL); 04359 return -1; 04360 } 04361 04362 if (!ast_mutex_lock(&gatelock)) { 04363 for (g = gateways; g; g = g->next) { 04364 g->delme = 1; 04365 for (e = g->endpoints; e; e = e->next) 04366 e->delme = 1; 04367 } 04368 04369 prune_gateways(); 04370 ast_mutex_unlock(&gatelock); 04371 } else { 04372 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n"); 04373 /* We always want to leave this in a consistent state */ 04374 ast_channel_register(&mgcp_tech); 04375 /* Allow the monitor to restart */ 04376 monitor_thread = AST_PTHREADT_NULL; 04377 mgcp_reloading = 0; 04378 mgcp_reload(NULL, 0, NULL); 04379 return -1; 04380 } 04381 04382 close(mgcpsock); 04383 ast_rtp_proto_unregister(&mgcp_rtp); 04384 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04385 sched_context_destroy(sched); 04386 04387 return 0; 04388 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 4394 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 4394 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 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(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_peer_defaults(), 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(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_peer_defaults(), set_pvt_defaults(), sla_ring_station(), socket_process(), and store_callerid().
struct ast_cli_entry cli_mgcp[] [static] |
Definition at line 1170 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 directmedia = DIRECTMEDIA [static] |
Definition at line 181 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(), minivm_mwi_exec(), mkintf(), notify_message(), peer_mailboxes_to_str(), queue_mwi_event(), realtime_directory(), sip_subscribe_mwi(), unistim_send_mwi_to_peer(), and update_registry().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match
Definition at line 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 3971 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 3381 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.2