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