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