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