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