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