#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_engine.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"
#include "asterisk/chanvars.h"
#include "asterisk/pktccops.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 | DEFAULT_EXPIRY 120 |
#define | DEFAULT_MGCP_CA_PORT 2727 |
#define | DEFAULT_MGCP_GW_PORT 2427 |
#define | DEFAULT_RETRANS 1000 |
#define | DIRECTMEDIA 1 |
#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, char *def) |
static int | __mgcp_xmit (struct mgcp_gateway *gw, char *data, int len) |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen) |
static int | add_header (struct mgcp_request *req, const char *var, const char *value) |
static void | add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone) |
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_instance *rtp) |
static struct ast_variable * | add_var (const char *buf, struct ast_variable *list) |
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 struct ast_variable * | copy_vars (struct ast_variable *src) |
duplicate a list of channel variables, | |
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_gateway * | find_realtime_gw (char *name, char *at, struct sockaddr_in *sin) |
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_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_alloc_pktcgate (struct mgcp_subchannel *sub) |
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 format_t | mgcp_get_codec (struct ast_channel *chan) |
static enum ast_rtp_glue_result | mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
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, const char *linkedid) |
static int | mgcp_pktcgate_open (struct cops_gate *gate) |
static int | mgcp_pktcgate_remove (struct cops_gate *gate) |
static int | mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno) |
static int | mgcp_prune_realtime_gateway (struct mgcp_gateway *g) |
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, format_t format, const struct ast_channel *requestor, 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_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t 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 (struct mgcp_subchannel *sub) |
static int | transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp_instance *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_instance *rtp, format_t 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_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } |
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 format_t | capability = AST_FORMAT_ULAW |
static char | cid_name [AST_MAX_EXTENSION] = "" |
static char | cid_num [AST_MAX_EXTENSION] = "" |
static struct ast_cli_entry | cli_mgcp [] |
static const char | config [] = "mgcp.conf" |
static char | context [AST_MAX_EXTENSION] = "default" |
static ast_group_t | cur_callergroup = 0 |
static ast_group_t | cur_pickupgroup = 0 |
static struct ast_jb_conf | default_jbconf |
static int | directmedia = DIRECTMEDIA |
static int | dtmfmode = 0 |
static int | firstdigittimeout = 16000 |
static ast_mutex_t | gatelock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
gatelock: mutex for gateway/endpoint lists | |
static struct mgcp_gateway * | gateways |
static int | gendigittimeout = 8000 |
static struct ast_jb_conf | global_jbconf |
static int | hangupongateremove = 0 |
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 const char *const | mgcp_cxmodes [] |
static ast_mutex_t | mgcp_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static int | mgcp_reloading = 0 |
static struct ast_rtp_glue | mgcp_rtp_glue |
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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static char | musicclass [MAX_MUSICCLASS] = "" |
static int | nat = 0 |
static int | ncs = 0 |
static ast_mutex_t | netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static int | nonCodecCapability = AST_RTP_DTMF |
static unsigned int | oseq |
static char | ourhost [MAXHOSTNAMELEN] |
static int | ourport |
static char | parkinglot [AST_MAX_CONTEXT] |
static int | pktcgatealloc = 0 |
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 DEFAULT_EXPIRY 120 |
Definition at line 89 of file chan_mgcp.c.
#define DEFAULT_MGCP_CA_PORT 2727 |
From RFC 2705
Definition at line 117 of file chan_mgcp.c.
#define DEFAULT_MGCP_GW_PORT 2427 |
From RFC 2705
Definition at line 116 of file chan_mgcp.c.
#define DEFAULT_RETRANS 1000 |
How frequently to retransmit
Definition at line 119 of file chan_mgcp.c.
Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt().
#define DIRECTMEDIA 1 |
#define INADDR_NONE (in_addr_t)(-1) |
Definition at line 94 of file chan_mgcp.c.
#define MAX_EXPIRY 3600 |
Definition at line 90 of file chan_mgcp.c.
#define MAX_RETRANS 5 |
Try only 5 times for retransmissions
Definition at line 120 of file chan_mgcp.c.
Referenced by retrans_pkt().
#define MAX_SUBS 2 |
Definition at line 283 of file chan_mgcp.c.
Referenced by mgcp_prune_realtime_gateway(), reload_config(), and unistim_info().
#define MGCP_CX_CONF 3 |
#define MGCP_CX_CONFERENCE 3 |
Definition at line 127 of file chan_mgcp.c.
#define MGCP_CX_INACTIVE 4 |
#define MGCP_CX_MUTE 4 |
#define MGCP_CX_RECVONLY 1 |
Definition at line 124 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 123 of file chan_mgcp.c.
#define MGCP_CX_SENDRECV 2 |
Definition at line 125 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 114 of file chan_mgcp.c.
Referenced by add_header_offhook(), mgcp_hangup(), mgcp_new(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().
#define MGCP_DTMF_INBAND (1 << 1) |
Definition at line 113 of file chan_mgcp.c.
Referenced by add_header_offhook(), 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 112 of file chan_mgcp.c.
Referenced by 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 242 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 118 of file chan_mgcp.c.
#define MGCP_OFFHOOK 2 |
Definition at line 319 of file chan_mgcp.c.
Referenced by handle_hd_hf(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), transmit_notify_request(), and transmit_notify_request_with_callerid().
#define MGCP_ONHOOK 1 |
Definition at line 318 of file chan_mgcp.c.
Referenced by do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_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 294 of file chan_mgcp.c.
Referenced by mgcp_hangup().
#define MGCPDUMPER |
Definition at line 88 of file chan_mgcp.c.
#define RESPONSE_TIMEOUT 30 |
#define SUB_ALT 1 |
Definition at line 286 of file chan_mgcp.c.
#define SUB_REAL 0 |
Definition at line 285 of file chan_mgcp.c.
#define TYPE_LINE 2 |
Definition at line 322 of file chan_mgcp.c.
Referenced by config_line(), config_parse_variables(), do_monitor(), and mgcp_call().
#define TYPE_TRUNK 1 |
Definition at line 321 of file chan_mgcp.c.
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 140 of file chan_mgcp.c.
00140 { 00141 MGCP_CMD_EPCF, 00142 MGCP_CMD_CRCX, 00143 MGCP_CMD_MDCX, 00144 MGCP_CMD_DLCX, 00145 MGCP_CMD_RQNT, 00146 MGCP_CMD_NTFY, 00147 MGCP_CMD_AUEP, 00148 MGCP_CMD_AUCX, 00149 MGCP_CMD_RSIP 00150 };
static char* __get_header | ( | struct mgcp_request * | req, | |
char * | name, | |||
int * | start, | |||
char * | def | |||
) | [static] |
Definition at line 1615 of file chan_mgcp.c.
References mgcp_request::header, mgcp_request::headers, and len().
Referenced by build_route(), copy_all_header(), copy_via_headers(), func_header_read(), get_header(), handle_incoming(), handle_request_subscribe(), handle_response_register(), and parse_register_contact().
01616 { 01617 int x; 01618 int len = strlen(name); 01619 char *r; 01620 for (x = *start; x < req->headers; x++) { 01621 if (!strncasecmp(req->header[x], name, len) && 01622 (req->header[x][len] == ':')) { 01623 r = req->header[x] + len + 1; 01624 while (*r && (*r < 33)) { 01625 r++; 01626 } 01627 *start = x + 1; 01628 return r; 01629 } 01630 } 01631 /* Don't return NULL, so get_header is always a valid pointer */ 01632 return def; 01633 }
static int __mgcp_xmit | ( | struct mgcp_gateway * | gw, | |
char * | data, | |||
int | len | |||
) | [static] |
Definition at line 544 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().
00545 { 00546 int res; 00547 if (gw->addr.sin_addr.s_addr) 00548 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); 00549 else 00550 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); 00551 if (res != len) { 00552 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); 00553 } 00554 return res; 00555 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 4922 of file chan_mgcp.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4922 of file chan_mgcp.c.
static int acf_channel_read | ( | struct ast_channel * | chan, | |
const char * | funcname, | |||
char * | preparse, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 4443 of file chan_mgcp.c.
References ast_log(), LOG_ERROR, mgcp_tech, mgcp_endpoint::ncs, mgcp_subchannel::parent, ast_channel::tech, and ast_channel::tech_pvt.
04444 { 04445 struct mgcp_subchannel *sub = chan->tech_pvt; 04446 int res = 0; 04447 04448 /* Sanity check */ 04449 if (!chan || chan->tech != &mgcp_tech) { 04450 ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n"); 04451 return -1; 04452 } 04453 04454 if (!strcasecmp(args, "ncs")) { 04455 snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no"); 04456 } else { 04457 res = -1; 04458 } 04459 return res; 04460 }
static int add_header | ( | struct mgcp_request * | req, | |
const char * | var, | |||
const char * | value | |||
) | [static] |
Definition at line 2044 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_cc_call_info_to_response(), add_digit(), add_diversion_header(), add_header_max_forwards(), add_header_offhook(), add_route(), add_rpid(), add_sdp(), add_supported_header(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), finalize_content(), initreqprep(), reqprep(), respprep(), transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_invite(), 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_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sip_etag(), transmit_response_with_unsupported(), transmit_state_notify(), and update_connectedline().
02045 { 02046 if (req->len >= sizeof(req->data) - 4) { 02047 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02048 return -1; 02049 } 02050 if (req->lines) { 02051 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 02052 return -1; 02053 } 02054 req->header[req->headers] = req->data + req->len; 02055 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); 02056 req->len += strlen(req->header[req->headers]); 02057 if (req->headers < MGCP_MAX_HEADERS) { 02058 req->headers++; 02059 } else { 02060 ast_log(LOG_WARNING, "Out of header space\n"); 02061 return -1; 02062 } 02063 return 0; 02064 }
static void add_header_offhook | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | resp, | |||
char * | tone | |||
) | [static] |
Definition at line 2598 of file chan_mgcp.c.
References ast_channel::_state, add_header(), ast_debug, AST_STATE_RINGING, mgcp_endpoint::dtmfmode, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_endpoint::ncs, mgcp_subchannel::owner, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by transmit_notify_request(), and transmit_notify_request_with_callerid().
02599 { 02600 struct mgcp_endpoint *p = sub->parent; 02601 char tone_indicate_end = 0; 02602 02603 /* We also should check the tone to indicate, because it have no sense 02604 to request notify D/[0-9#*] (dtmf keys) if we are sending congestion 02605 tone for example G/cg */ 02606 if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) { 02607 tone_indicate_end = 1; 02608 } 02609 02610 if (p && p->sub && p->sub->owner && 02611 p->sub->owner->_state >= AST_STATE_RINGING && 02612 (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) { 02613 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02614 02615 } else if (!tone_indicate_end){ 02616 add_header(resp, "R", (p->ncs ? "L/hu(N),L/hf(N),L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)")); 02617 } else { 02618 ast_debug(1, "We don't want more digits if we will end the call\n"); 02619 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02620 } 02621 }
static int add_line | ( | struct mgcp_request * | req, | |
char * | line | |||
) | [static] |
Definition at line 2066 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.
02067 { 02068 if (req->len >= sizeof(req->data) - 4) { 02069 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02070 return -1; 02071 } 02072 if (!req->lines) { 02073 /* Add extra empty return */ 02074 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); 02075 req->len += strlen(req->data + req->len); 02076 } 02077 req->line[req->lines] = req->data + req->len; 02078 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 02079 req->len += strlen(req->line[req->lines]); 02080 if (req->lines < MGCP_MAX_LINES) { 02081 req->lines++; 02082 } else { 02083 ast_log(LOG_WARNING, "Out of line space\n"); 02084 return -1; 02085 } 02086 return 0; 02087 }
static int add_sdp | ( | struct mgcp_request * | resp, | |
struct mgcp_subchannel * | sub, | |||
struct ast_rtp_instance * | rtp | |||
) | [static] |
Definition at line 2176 of file chan_mgcp.c.
References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, mgcp_endpoint::capability, len(), LOG_WARNING, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.
Referenced by transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and update_connectedline().
02177 { 02178 int len; 02179 int codec; 02180 char costr[80]; 02181 struct sockaddr_in sin; 02182 struct ast_sockaddr sin_tmp; 02183 char v[256]; 02184 char s[256]; 02185 char o[256]; 02186 char c[256]; 02187 char t[256]; 02188 char m[256] = ""; 02189 char a[1024] = ""; 02190 format_t x; 02191 struct sockaddr_in dest = { 0, }; 02192 struct ast_sockaddr dest_tmp; 02193 struct mgcp_endpoint *p = sub->parent; 02194 /* XXX We break with the "recommendation" and send our IP, in order that our 02195 peer doesn't have to ast_gethostbyname() us XXX */ 02196 len = 0; 02197 if (!sub->rtp) { 02198 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02199 return -1; 02200 } 02201 ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp); 02202 ast_sockaddr_to_sin(&sin_tmp, &sin); 02203 if (rtp) { 02204 ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp); 02205 ast_sockaddr_to_sin(&dest_tmp, &dest); 02206 } else { 02207 if (sub->tmpdest.sin_addr.s_addr) { 02208 dest.sin_addr = sub->tmpdest.sin_addr; 02209 dest.sin_port = sub->tmpdest.sin_port; 02210 /* Reset temporary destination */ 02211 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02212 } else { 02213 dest.sin_addr = p->parent->ourip; 02214 dest.sin_port = sin.sin_port; 02215 } 02216 } 02217 ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02218 ast_copy_string(v, "v=0\r\n", sizeof(v)); 02219 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); 02220 ast_copy_string(s, "s=session\r\n", sizeof(s)); 02221 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02222 ast_copy_string(t, "t=0 0\r\n", sizeof(t)); 02223 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02224 for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02225 if (!(x & AST_FORMAT_AUDIO_MASK)) { 02226 /* Audio is now discontiguous */ 02227 continue; 02228 } 02229 if (p->capability & x) { 02230 ast_debug(1, "Answering with capability %s\n", ast_getformatname(x)); 02231 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, x); 02232 if (codec > -1) { 02233 snprintf(costr, sizeof(costr), " %d", codec); 02234 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02235 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, x, 0)); 02236 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02237 } 02238 } 02239 } 02240 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { 02241 if (p->nonCodecCapability & x) { 02242 ast_debug(1, "Answering with non-codec capability %d\n", (int) x); 02243 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, x); 02244 if (codec > -1) { 02245 snprintf(costr, sizeof(costr), " %d", codec); 02246 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02247 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, x, 0)); 02248 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02249 if (x == AST_RTP_DTMF) { 02250 /* Indicate we support DTMF... Not sure about 16, 02251 but MSN supports it so dang it, we will too... */ 02252 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02253 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02254 } 02255 } 02256 } 02257 } 02258 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02259 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02260 snprintf(costr, sizeof(costr), "%d", len); 02261 add_line(resp, v); 02262 add_line(resp, o); 02263 add_line(resp, s); 02264 add_line(resp, c); 02265 add_line(resp, t); 02266 add_line(resp, m); 02267 add_line(resp, a); 02268 return 0; 02269 }
static struct ast_variable * add_var | ( | const char * | buf, | |
struct ast_variable * | list | |||
) | [static] |
Definition at line 4573 of file chan_mgcp.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
Referenced by build_peer(), and config_parse_variables().
04574 { 04575 struct ast_variable *tmpvar = NULL; 04576 char *varname = ast_strdupa(buf), *varval = NULL; 04577 04578 if ((varval = strchr(varname, '='))) { 04579 *varval++ = '\0'; 04580 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 04581 tmpvar->next = list; 04582 list = tmpvar; 04583 } 04584 } 04585 return list; 04586 }
static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 3200 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().
03201 { 03202 /* ************************* 03203 * I hope this works. 03204 * Copied out of chan_zap 03205 * Cross your fingers 03206 * *************************/ 03207 03208 /* In order to transfer, we need at least one of the channels to 03209 actually be in a call bridge. We can't conference two applications 03210 together (but then, why would we want to?) */ 03211 if (ast_bridged_channel(p->sub->owner)) { 03212 /* The three-way person we're about to transfer to could still be in MOH, so 03213 stop if now if appropriate */ 03214 if (ast_bridged_channel(p->sub->next->owner)) 03215 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03216 if (p->sub->owner->_state == AST_STATE_RINGING) { 03217 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03218 } 03219 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 03220 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03221 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); 03222 return -1; 03223 } 03224 /* Orphan the channel */ 03225 unalloc_sub(p->sub->next); 03226 } else if (ast_bridged_channel(p->sub->next->owner)) { 03227 if (p->sub->owner->_state == AST_STATE_RINGING) { 03228 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03229 } 03230 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03231 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 03232 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03233 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); 03234 return -1; 03235 } 03236 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 03237 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03238 p->sub = p->sub->next; 03239 unalloc_sub(p->sub->next); 03240 /* Tell the caller not to hangup */ 03241 return 1; 03242 } else { 03243 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03244 p->sub->owner->name, p->sub->next->owner->name); 03245 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03246 if (p->sub->next->owner) { 03247 p->sub->next->alreadygone = 1; 03248 mgcp_queue_hangup(p->sub->next); 03249 } 03250 } 03251 return 0; 03252 }
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 3958 of file chan_mgcp.c.
References mgcp_gateway::delme, DIRECTMEDIA, directmedia, gateways, mgcp_gateway::name, and mgcp_gateway::next.
03959 { 03960 struct mgcp_gateway *gw; 03961 struct mgcp_endpoint *e; 03962 struct mgcp_subchannel *sub; 03963 struct ast_variable *chanvars = NULL; 03964 03965 /*char txident[80];*/ 03966 int i=0, y=0; 03967 int gw_reload = 0; 03968 int ep_reload = 0; 03969 directmedia = DIRECTMEDIA; 03970 03971 /* locate existing gateway */ 03972 for (gw = gateways; gw; gw = gw->next) { 03973 if (!strcasecmp(cat, gw->name)) { 03974 /* gateway already exists */ 03975 gw->delme = 0; 03976 gw_reload = 1; 03977 break; 03978 } 03979 } 03980 03981 if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) { 03982 return NULL; 03983 } 03984 03985 if (!gw_reload) { 03986 gw->expire = -1; 03987 gw->realtime = 0; 03988 gw->retransid = -1; 03989 ast_mutex_init(&gw->msgs_lock); 03990 ast_copy_string(gw->name, cat, sizeof(gw->name)); 03991 /* check if the name is numeric ip */ 03992 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 03993 gw->isnamedottedip = 1; 03994 } 03995 for (; v; v = v->next) { 03996 if (!strcasecmp(v->name, "host")) { 03997 if (!strcasecmp(v->value, "dynamic")) { 03998 /* They'll register with us */ 03999 gw->dynamic = 1; 04000 memset(&gw->addr.sin_addr, 0, 4); 04001 if (gw->addr.sin_port) { 04002 /* If we've already got a port, make it the default rather than absolute */ 04003 gw->defaddr.sin_port = gw->addr.sin_port; 04004 gw->addr.sin_port = 0; 04005 } 04006 } else { 04007 /* Non-dynamic. Make sure we become that way if we're not */ 04008 AST_SCHED_DEL(sched, gw->expire); 04009 gw->dynamic = 0; 04010 { 04011 struct ast_sockaddr tmp; 04012 04013 ast_sockaddr_from_sin(&tmp, &gw->addr); 04014 if (ast_get_ip(&tmp, v->value)) { 04015 if (!gw_reload) { 04016 ast_mutex_destroy(&gw->msgs_lock); 04017 ast_free(gw); 04018 } 04019 return NULL; 04020 } 04021 ast_sockaddr_to_sin(&tmp, &gw->addr); 04022 } 04023 } 04024 } else if (!strcasecmp(v->name, "defaultip")) { 04025 struct ast_sockaddr tmp; 04026 04027 ast_sockaddr_from_sin(&tmp, &gw->defaddr); 04028 if (ast_get_ip(&tmp, v->value)) { 04029 if (!gw_reload) { 04030 ast_mutex_destroy(&gw->msgs_lock); 04031 ast_free(gw); 04032 } 04033 return NULL; 04034 } 04035 ast_sockaddr_to_sin(&tmp, &gw->defaddr); 04036 } else if (!strcasecmp(v->name, "permit") || 04037 !strcasecmp(v->name, "deny")) { 04038 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 04039 } else if (!strcasecmp(v->name, "port")) { 04040 gw->addr.sin_port = htons(atoi(v->value)); 04041 } else if (!strcasecmp(v->name, "context")) { 04042 ast_copy_string(context, v->value, sizeof(context)); 04043 } else if (!strcasecmp(v->name, "dtmfmode")) { 04044 if (!strcasecmp(v->value, "inband")) 04045 dtmfmode = MGCP_DTMF_INBAND; 04046 else if (!strcasecmp(v->value, "rfc2833")) 04047 dtmfmode = MGCP_DTMF_RFC2833; 04048 else if (!strcasecmp(v->value, "hybrid")) 04049 dtmfmode = MGCP_DTMF_HYBRID; 04050 else if (!strcasecmp(v->value, "none")) 04051 dtmfmode = 0; 04052 else 04053 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 04054 } else if (!strcasecmp(v->name, "nat")) { 04055 nat = ast_true(v->value); 04056 } else if (!strcasecmp(v->name, "ncs")) { 04057 ncs = ast_true(v->value); 04058 } else if (!strcasecmp(v->name, "hangupongateremove")) { 04059 hangupongateremove = ast_true(v->value); 04060 } else if (!strcasecmp(v->name, "pktcgatealloc")) { 04061 pktcgatealloc = ast_true(v->value); 04062 } else if (!strcasecmp(v->name, "callerid")) { 04063 if (!strcasecmp(v->value, "asreceived")) { 04064 cid_num[0] = '\0'; 04065 cid_name[0] = '\0'; 04066 } else { 04067 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 04068 } 04069 } else if (!strcasecmp(v->name, "language")) { 04070 ast_copy_string(language, v->value, sizeof(language)); 04071 } else if (!strcasecmp(v->name, "accountcode")) { 04072 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 04073 } else if (!strcasecmp(v->name, "amaflags")) { 04074 y = ast_cdr_amaflags2int(v->value); 04075 if (y < 0) { 04076 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 04077 } else { 04078 amaflags = y; 04079 } 04080 } else if (!strcasecmp(v->name, "setvar")) { 04081 chanvars = add_var(v->value, chanvars); 04082 } else if (!strcasecmp(v->name, "clearvars")) { 04083 if (chanvars) { 04084 ast_variables_destroy(chanvars); 04085 chanvars = NULL; 04086 } 04087 } else if (!strcasecmp(v->name, "musiconhold")) { 04088 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 04089 } else if (!strcasecmp(v->name, "parkinglot")) { 04090 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 04091 } else if (!strcasecmp(v->name, "callgroup")) { 04092 cur_callergroup = ast_get_group(v->value); 04093 } else if (!strcasecmp(v->name, "pickupgroup")) { 04094 cur_pickupgroup = ast_get_group(v->value); 04095 } else if (!strcasecmp(v->name, "immediate")) { 04096 immediate = ast_true(v->value); 04097 } else if (!strcasecmp(v->name, "cancallforward")) { 04098 cancallforward = ast_true(v->value); 04099 } else if (!strcasecmp(v->name, "singlepath")) { 04100 singlepath = ast_true(v->value); 04101 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 04102 directmedia = ast_true(v->value); 04103 } else if (!strcasecmp(v->name, "mailbox")) { 04104 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 04105 } else if (!strcasecmp(v->name, "hasvoicemail")) { 04106 if (ast_true(v->value) && ast_strlen_zero(mailbox)) { 04107 ast_copy_string(mailbox, gw->name, sizeof(mailbox)); 04108 } 04109 } else if (!strcasecmp(v->name, "adsi")) { 04110 adsi = ast_true(v->value); 04111 } else if (!strcasecmp(v->name, "callreturn")) { 04112 callreturn = ast_true(v->value); 04113 } else if (!strcasecmp(v->name, "callwaiting")) { 04114 callwaiting = ast_true(v->value); 04115 } else if (!strcasecmp(v->name, "slowsequence")) { 04116 slowsequence = ast_true(v->value); 04117 } else if (!strcasecmp(v->name, "transfer")) { 04118 transfer = ast_true(v->value); 04119 } else if (!strcasecmp(v->name, "threewaycalling")) { 04120 threewaycalling = ast_true(v->value); 04121 } else if (!strcasecmp(v->name, "wcardep")) { 04122 /* locate existing endpoint */ 04123 for (e = gw->endpoints; e; e = e->next) { 04124 if (!strcasecmp(v->value, e->name)) { 04125 /* endpoint already exists */ 04126 e->delme = 0; 04127 ep_reload = 1; 04128 break; 04129 } 04130 } 04131 04132 if (!e) { 04133 /* Allocate wildcard endpoint */ 04134 e = ast_calloc(1, sizeof(*e)); 04135 ep_reload = 0; 04136 } 04137 04138 if (e) { 04139 if (!ep_reload) { 04140 memset(e, 0, sizeof(struct mgcp_endpoint)); 04141 ast_mutex_init(&e->lock); 04142 ast_mutex_init(&e->rqnt_queue_lock); 04143 ast_mutex_init(&e->cmd_queue_lock); 04144 ast_copy_string(e->name, v->value, sizeof(e->name)); 04145 e->needaudit = 1; 04146 } 04147 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 04148 /* XXX Should we really check for uniqueness?? XXX */ 04149 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04150 ast_copy_string(e->context, context, sizeof(e->context)); 04151 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04152 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04153 ast_copy_string(e->language, language, sizeof(e->language)); 04154 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04155 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04156 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04157 if (!ast_strlen_zero(e->mailbox)) { 04158 char *mbox, *cntx; 04159 cntx = mbox = ast_strdupa(e->mailbox); 04160 strsep(&cntx, "@"); 04161 if (ast_strlen_zero(cntx)) { 04162 cntx = "default"; 04163 } 04164 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL, 04165 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 04166 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 04167 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 04168 AST_EVENT_IE_END); 04169 } 04170 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04171 e->msgstate = -1; 04172 e->amaflags = amaflags; 04173 e->capability = capability; 04174 e->parent = gw; 04175 e->ncs = ncs; 04176 e->dtmfmode = dtmfmode; 04177 if (!ep_reload && e->sub && e->sub->rtp) { 04178 e->dtmfmode |= MGCP_DTMF_INBAND; 04179 } 04180 e->adsi = adsi; 04181 e->type = TYPE_LINE; 04182 e->immediate = immediate; 04183 e->callgroup=cur_callergroup; 04184 e->pickupgroup=cur_pickupgroup; 04185 e->callreturn = callreturn; 04186 e->cancallforward = cancallforward; 04187 e->singlepath = singlepath; 04188 e->directmedia = directmedia; 04189 e->callwaiting = callwaiting; 04190 e->hascallwaiting = callwaiting; 04191 e->slowsequence = slowsequence; 04192 e->transfer = transfer; 04193 e->threewaycalling = threewaycalling; 04194 e->onhooktime = time(NULL); 04195 /* ASSUME we're onhook */ 04196 e->hookstate = MGCP_ONHOOK; 04197 e->chanvars = copy_vars(chanvars); 04198 if (!ep_reload) { 04199 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 04200 for (i = 0; i < MAX_SUBS; i++) { 04201 sub = ast_calloc(1, sizeof(*sub)); 04202 if (sub) { 04203 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04204 ast_mutex_init(&sub->lock); 04205 ast_mutex_init(&sub->cx_queue_lock); 04206 sub->parent = e; 04207 sub->id = i; 04208 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04209 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 04210 sub->cxmode = MGCP_CX_INACTIVE; 04211 sub->nat = nat; 04212 sub->gate = NULL; 04213 sub->sdpsent = 0; 04214 sub->next = e->sub; 04215 e->sub = sub; 04216 } else { 04217 /* XXX Should find a way to clean up our memory */ 04218 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04219 return NULL; 04220 } 04221 } 04222 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04223 /* find the end of the list */ 04224 for (sub = e->sub; sub && sub->next; sub = sub->next); 04225 /* set the last sub->next to the first sub */ 04226 sub->next = e->sub; 04227 04228 e->next = gw->endpoints; 04229 gw->endpoints = e; 04230 } 04231 } 04232 } else if (!strcasecmp(v->name, "trunk") || 04233 !strcasecmp(v->name, "line")) { 04234 04235 /* locate existing endpoint */ 04236 for (e = gw->endpoints; e; e = e->next) { 04237 if (!strcasecmp(v->value, e->name)) { 04238 /* endpoint already exists */ 04239 e->delme = 0; 04240 ep_reload = 1; 04241 break; 04242 } 04243 } 04244 04245 if (!e) { 04246 e = ast_calloc(1, sizeof(*e)); 04247 ep_reload = 0; 04248 } 04249 04250 if (e) { 04251 if (!ep_reload) { 04252 ast_mutex_init(&e->lock); 04253 ast_mutex_init(&e->rqnt_queue_lock); 04254 ast_mutex_init(&e->cmd_queue_lock); 04255 ast_copy_string(e->name, v->value, sizeof(e->name)); 04256 e->needaudit = 1; 04257 } 04258 /* XXX Should we really check for uniqueness?? XXX */ 04259 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04260 ast_copy_string(e->context, context, sizeof(e->context)); 04261 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04262 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04263 ast_copy_string(e->language, language, sizeof(e->language)); 04264 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04265 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04266 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04267 if (!ast_strlen_zero(mailbox)) { 04268 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 04269 } 04270 if (!ep_reload) { 04271 /* XXX potential issue due to reload */ 04272 e->msgstate = -1; 04273 e->parent = gw; 04274 } 04275 e->amaflags = amaflags; 04276 e->capability = capability; 04277 e->dtmfmode = dtmfmode; 04278 e->ncs = ncs; 04279 e->pktcgatealloc = pktcgatealloc; 04280 e->hangupongateremove = hangupongateremove; 04281 e->adsi = adsi; 04282 e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE; 04283 e->immediate = immediate; 04284 e->callgroup=cur_callergroup; 04285 e->pickupgroup=cur_pickupgroup; 04286 e->callreturn = callreturn; 04287 e->cancallforward = cancallforward; 04288 e->directmedia = directmedia; 04289 e->singlepath = singlepath; 04290 e->callwaiting = callwaiting; 04291 e->hascallwaiting = callwaiting; 04292 e->slowsequence = slowsequence; 04293 e->transfer = transfer; 04294 e->threewaycalling = threewaycalling; 04295 04296 /* If we already have a valid chanvars, it's not a new endpoint (it's a reload), 04297 so first, free previous mem 04298 */ 04299 if (e->chanvars) { 04300 ast_variables_destroy(e->chanvars); 04301 e->chanvars = NULL; 04302 } 04303 e->chanvars = copy_vars(chanvars); 04304 04305 if (!ep_reload) { 04306 e->onhooktime = time(NULL); 04307 /* ASSUME we're onhook */ 04308 e->hookstate = MGCP_ONHOOK; 04309 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04310 } 04311 04312 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 04313 if (!ep_reload) { 04314 sub = ast_calloc(1, sizeof(*sub)); 04315 } else { 04316 if (!sub) { 04317 sub = e->sub; 04318 } else { 04319 sub = sub->next; 04320 } 04321 } 04322 04323 if (sub) { 04324 if (!ep_reload) { 04325 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04326 ast_mutex_init(&sub->lock); 04327 ast_mutex_init(&sub->cx_queue_lock); 04328 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 04329 sub->parent = e; 04330 sub->id = i; 04331 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04332 sub->cxmode = MGCP_CX_INACTIVE; 04333 sub->next = e->sub; 04334 e->sub = sub; 04335 } 04336 sub->nat = nat; 04337 } else { 04338 /* XXX Should find a way to clean up our memory */ 04339 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04340 return NULL; 04341 } 04342 } 04343 if (!ep_reload) { 04344 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04345 /* find the end of the list */ 04346 for (sub = e->sub; sub && sub->next; sub = sub->next); 04347 /* set the last sub->next to the first sub */ 04348 sub->next = e->sub; 04349 04350 e->next = gw->endpoints; 04351 gw->endpoints = e; 04352 } 04353 } 04354 } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) { 04355 /* just eliminate realtime warnings */ 04356 } else { 04357 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 04358 } 04359 } 04360 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 04361 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 04362 if (!gw_reload) { 04363 ast_mutex_destroy(&gw->msgs_lock); 04364 ast_free(gw); 04365 } 04366 04367 /* Return NULL */ 04368 gw_reload = 1; 04369 } else { 04370 gw->defaddr.sin_family = AF_INET; 04371 gw->addr.sin_family = AF_INET; 04372 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) { 04373 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04374 } 04375 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) { 04376 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04377 } 04378 { 04379 struct ast_sockaddr tmp1, tmp2; 04380 struct sockaddr_in tmp3 = {0,}; 04381 04382 tmp3.sin_addr = gw->ourip; 04383 ast_sockaddr_from_sin(&tmp1, &gw->addr); 04384 ast_sockaddr_from_sin(&tmp2, &tmp3); 04385 if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) { 04386 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 04387 } else { 04388 ast_sockaddr_to_sin(&tmp2, &tmp3); 04389 gw->ourip = tmp3.sin_addr; 04390 } 04391 } 04392 } 04393 04394 if (chanvars) { 04395 ast_variables_destroy(chanvars); 04396 chanvars = NULL; 04397 } 04398 return (gw_reload ? NULL : gw); 04399 }
static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1407 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().
01407 { 01408 switch (ind) { 01409 case AST_CONTROL_HANGUP: 01410 return "Other end has hungup"; 01411 case AST_CONTROL_RING: 01412 return "Local ring"; 01413 case AST_CONTROL_RINGING: 01414 return "Remote end is ringing"; 01415 case AST_CONTROL_ANSWER: 01416 return "Remote end has answered"; 01417 case AST_CONTROL_BUSY: 01418 return "Remote end is busy"; 01419 case AST_CONTROL_TAKEOFFHOOK: 01420 return "Make it go off hook"; 01421 case AST_CONTROL_OFFHOOK: 01422 return "Line is off hook"; 01423 case AST_CONTROL_CONGESTION: 01424 return "Congestion (circuits busy)"; 01425 case AST_CONTROL_FLASH: 01426 return "Flash hook"; 01427 case AST_CONTROL_WINK: 01428 return "Wink"; 01429 case AST_CONTROL_OPTION: 01430 return "Set a low-level option"; 01431 case AST_CONTROL_RADIO_KEY: 01432 return "Key Radio"; 01433 case AST_CONTROL_RADIO_UNKEY: 01434 return "Un-Key Radio"; 01435 } 01436 return "UNKNOWN"; 01437 }
static struct ast_variable * copy_vars | ( | struct ast_variable * | src | ) | [static] |
duplicate a list of channel variables,
Definition at line 4591 of file chan_mgcp.c.
References ast_variable_new(), and ast_variable::next.
Referenced by check_peer_ok(), and create_addr_from_peer().
04592 { 04593 struct ast_variable *res = NULL, *tmp, *v = NULL; 04594 04595 for (v = src ; v ; v = v->next) { 04596 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 04597 tmp->next = res; 04598 res = tmp; 04599 } 04600 } 04601 return res; 04602 }
static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 4463 of file chan_mgcp.c.
References ast_mutex_lock, ast_rtp_instance_destroy(), ast_strlen_zero(), mgcp_subchannel::cxident, mgcp_subchannel::lock, mgcp_subchannel::next, mgcp_subchannel::rtp, mgcp_endpoint::sub, and transmit_connection_del().
Referenced by prune_gateways().
04464 { 04465 struct mgcp_subchannel *sub = e->sub->next, *s; 04466 int i; 04467 04468 for (i = 0; i < MAX_SUBS; i++) { 04469 ast_mutex_lock(&sub->lock); 04470 if (!ast_strlen_zero(sub->cxident)) { 04471 transmit_connection_del(sub); 04472 } 04473 if (sub->rtp) { 04474 ast_rtp_instance_destroy(sub->rtp); 04475 sub->rtp = NULL; 04476 } 04477 memset(sub->magic, 0, sizeof(sub->magic)); 04478 mgcp_queue_hangup(sub); 04479 dump_cmd_queues(NULL, sub); 04480 if(sub->gate) { 04481 sub->gate->tech_pvt = NULL; 04482 sub->gate->got_dq_gi = NULL; 04483 sub->gate->gate_remove = NULL; 04484 sub->gate->gate_open = NULL; 04485 } 04486 ast_mutex_unlock(&sub->lock); 04487 sub = sub->next; 04488 } 04489 04490 if (e->dsp) { 04491 ast_dsp_free(e->dsp); 04492 } 04493 04494 dump_queue(e->parent, e); 04495 dump_cmd_queues(e, NULL); 04496 04497 sub = e->sub; 04498 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04499 s = sub; 04500 sub = sub->next; 04501 ast_mutex_destroy(&s->lock); 04502 ast_mutex_destroy(&s->cx_queue_lock); 04503 ast_free(s); 04504 } 04505 04506 if (e->mwi_event_sub) 04507 ast_event_unsubscribe(e->mwi_event_sub); 04508 04509 if (e->chanvars) { 04510 ast_variables_destroy(e->chanvars); 04511 e->chanvars = NULL; 04512 } 04513 04514 ast_mutex_destroy(&e->lock); 04515 ast_mutex_destroy(&e->rqnt_queue_lock); 04516 ast_mutex_destroy(&e->cmd_queue_lock); 04517 ast_free(e); 04518 }
static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4520 of file chan_mgcp.c.
References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.
04521 { 04522 if (g->ha) 04523 ast_free_ha(g->ha); 04524 04525 dump_queue(g, NULL); 04526 04527 ast_free(g); 04528 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3760 of file chan_mgcp.c.
References ast_io_add(), AST_IO_IN, ast_io_wait(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, mgcp_gateway::endpoints, free, gatelock, gateways, has_voicemail(), io, MGCP_ONHOOK, mgcp_prune_realtime_gateway(), mgcp_reload_lock, mgcp_reloading, mgcpsock, mgcpsock_read(), mgcpsock_read_id, monlock, netlock, mgcp_gateway::next, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.
03761 { 03762 int res; 03763 int reloading; 03764 struct mgcp_gateway *g, *gprev; 03765 /*struct mgcp_gateway *g;*/ 03766 /*struct mgcp_endpoint *e;*/ 03767 /*time_t thispass = 0, lastpass = 0;*/ 03768 time_t lastrun = 0; 03769 03770 /* Add an I/O event to our UDP socket */ 03771 if (mgcpsock > -1) { 03772 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03773 } 03774 /* This thread monitors all the frame relay interfaces which are not yet in use 03775 (and thus do not have a separate thread) indefinitely */ 03776 /* From here on out, we die whenever asked */ 03777 for (;;) { 03778 /* Check for a reload request */ 03779 ast_mutex_lock(&mgcp_reload_lock); 03780 reloading = mgcp_reloading; 03781 mgcp_reloading = 0; 03782 ast_mutex_unlock(&mgcp_reload_lock); 03783 if (reloading) { 03784 ast_verb(1, "Reloading MGCP\n"); 03785 reload_config(1); 03786 /* Add an I/O event to our UDP socket */ 03787 if (mgcpsock > -1 && !mgcpsock_read_id) { 03788 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03789 } 03790 } 03791 03792 /* Check for interfaces needing to be killed */ 03793 /* Don't let anybody kill us right away. Nobody should lock the interface list 03794 and wait for the monitor list, but the other way around is okay. */ 03795 ast_mutex_lock(&monlock); 03796 /* Lock the network interface */ 03797 ast_mutex_lock(&netlock); 03798 03799 #if 0 03800 /* XXX THIS IS COMPLETELY HOSED */ 03801 /* The gateway goes into a state of panic */ 03802 /* If the vmwi indicator is sent while it is reseting interfaces */ 03803 lastpass = thispass; 03804 thispass = time(NULL); 03805 g = gateways; 03806 while(g) { 03807 if (thispass != lastpass) { 03808 e = g->endpoints; 03809 while(e) { 03810 if (e->type == TYPE_LINE) { 03811 res = has_voicemail(e); 03812 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03813 if (res) { 03814 transmit_notify_request(e, "L/vmwi(+)"); 03815 } else { 03816 transmit_notify_request(e, "L/vmwi(-)"); 03817 } 03818 e->msgstate = res; 03819 e->onhooktime = thispass; 03820 } 03821 } 03822 e = e->next; 03823 } 03824 } 03825 g = g->next; 03826 } 03827 #endif 03828 /* pruning unused realtime gateways, running in every 60 seconds*/ 03829 if(time(NULL) > (lastrun + 60)) { 03830 ast_mutex_lock(&gatelock); 03831 g = gateways; 03832 gprev = NULL; 03833 while(g) { 03834 if(g->realtime) { 03835 if(mgcp_prune_realtime_gateway(g)) { 03836 if(gprev) { 03837 gprev->next = g->next; 03838 } else { 03839 gateways = g->next; 03840 } 03841 ast_mutex_unlock(&g->msgs_lock); 03842 ast_mutex_destroy(&g->msgs_lock); 03843 free(g); 03844 } else { 03845 ast_mutex_unlock(&g->msgs_lock); 03846 gprev = g; 03847 } 03848 } else { 03849 gprev = g; 03850 } 03851 g = g->next; 03852 } 03853 ast_mutex_unlock(&gatelock); 03854 lastrun = time(NULL); 03855 } 03856 /* Okay, now that we know what to do, release the network lock */ 03857 ast_mutex_unlock(&netlock); 03858 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03859 ast_mutex_unlock(&monlock); 03860 pthread_testcancel(); 03861 /* Wait for sched or io */ 03862 res = ast_sched_wait(sched); 03863 /* copied from chan_sip.c */ 03864 if ((res < 0) || (res > 1000)) { 03865 res = 1000; 03866 } 03867 res = ast_io_wait(io, res); 03868 ast_mutex_lock(&monlock); 03869 if (res >= 0) { 03870 ast_sched_runq(sched); 03871 } 03872 ast_mutex_unlock(&monlock); 03873 } 03874 /* Never reached */ 03875 return NULL; 03876 }
static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub | |||
) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2681 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().
02682 { 02683 struct mgcp_request *t, *q; 02684 02685 if (p) { 02686 ast_mutex_lock(&p->rqnt_queue_lock); 02687 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); 02688 p->rqnt_queue = NULL; 02689 ast_mutex_unlock(&p->rqnt_queue_lock); 02690 02691 ast_mutex_lock(&p->cmd_queue_lock); 02692 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); 02693 p->cmd_queue = NULL; 02694 ast_mutex_unlock(&p->cmd_queue_lock); 02695 02696 ast_mutex_lock(&p->sub->cx_queue_lock); 02697 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02698 p->sub->cx_queue = NULL; 02699 ast_mutex_unlock(&p->sub->cx_queue_lock); 02700 02701 ast_mutex_lock(&p->sub->next->cx_queue_lock); 02702 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); 02703 p->sub->next->cx_queue = NULL; 02704 ast_mutex_unlock(&p->sub->next->cx_queue_lock); 02705 } else if (sub) { 02706 ast_mutex_lock(&sub->cx_queue_lock); 02707 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02708 sub->cx_queue = NULL; 02709 ast_mutex_unlock(&sub->cx_queue_lock); 02710 } 02711 }
static void dump_queue | ( | struct mgcp_gateway * | gw, | |
struct mgcp_endpoint * | p | |||
) | [static] |
Definition at line 580 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, mgcp_message::next, mgcp_message::owner_ep, and mgcp_message::seqno.
Referenced by destroy_gateway(), and handle_request().
00581 { 00582 struct mgcp_message *cur, *q = NULL, *w, *prev; 00583 00584 ast_mutex_lock(&gw->msgs_lock); 00585 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00586 if (!p || cur->owner_ep == p) { 00587 if (prev) { 00588 prev->next = cur->next; 00589 } else { 00590 gw->msgs = cur->next; 00591 } 00592 00593 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 00594 gw->name, cur->seqno); 00595 00596 w = cur; 00597 if (q) { 00598 w->next = q; 00599 } else { 00600 w->next = NULL; 00601 } 00602 q = w; 00603 } 00604 } 00605 ast_mutex_unlock(&gw->msgs_lock); 00606 00607 while (q) { 00608 cur = q; 00609 q = q->next; 00610 ast_free(cur); 00611 } 00612 }
static int find_and_retrans | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req | |||
) | [static] |
Definition at line 3581 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().
03582 { 03583 int seqno=0; 03584 time_t now; 03585 struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL; 03586 time(&now); 03587 if (sscanf(req->identifier, "%30d", &seqno) != 1) { 03588 seqno = 0; 03589 } 03590 for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) { 03591 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03592 /* Delete this entry */ 03593 if (prev) 03594 prev->next = next; 03595 else 03596 sub->parent->parent->responses = next; 03597 ast_free(cur); 03598 } else { 03599 if (seqno == cur->seqno) 03600 answer = cur; 03601 prev = cur; 03602 } 03603 } 03604 if (answer) { 03605 resend_response(sub, answer); 03606 return 1; 03607 } 03608 return 0; 03609 }
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 2715 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), ast_mutex_lock, mgcp_postrequest(), mgcp_request::next, and mgcp_endpoint::parent.
Referenced by agi_handle_command(), ast_agi_register(), handle_cli_agi_show(), and handle_response().
02717 { 02718 struct mgcp_request *prev, *req; 02719 02720 ast_mutex_lock(l); 02721 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02722 if (req->trid == ident) { 02723 /* remove from queue */ 02724 if (!prev) 02725 *queue = req->next; 02726 else 02727 prev->next = req->next; 02728 02729 /* send next pending command */ 02730 if (*queue) { 02731 ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02732 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02733 02734 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02735 } 02736 break; 02737 } 02738 } 02739 ast_mutex_unlock(l); 02740 return req; 02741 }
static struct mgcp_gateway* find_realtime_gw | ( | char * | name, | |
char * | at, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 1666 of file chan_mgcp.c.
References ast_check_realtime(), ast_copy_string(), ast_debug, ast_load_realtime(), ast_strlen_zero(), ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by find_subchannel_and_lock().
01667 { 01668 struct mgcp_gateway *g = NULL; 01669 struct ast_variable *mgcpgwconfig = NULL; 01670 struct ast_variable *gwv, *epname = NULL; 01671 struct mgcp_endpoint *e; 01672 char lines[256]; 01673 int i, j; 01674 01675 ast_debug(1, "*** find Realtime MGCPGW\n"); 01676 01677 if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) { 01678 return NULL; 01679 } 01680 01681 if (ast_strlen_zero(at)) { 01682 ast_debug(1, "null gw name\n"); 01683 return NULL; 01684 } 01685 01686 if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) { 01687 return NULL; 01688 } 01689 01690 /*! 01691 * \note This is a fairly odd way of instantiating lines. Instead of each 01692 * line created by virtue of being in the database (and loaded via 01693 * ast_load_realtime_multientry), this code forces a specific order with a 01694 * "lines" entry in the "mgcpgw" record. This has benefits, because as with 01695 * chan_dahdi, values are inherited across definitions. The downside is 01696 * that it's not as clear what the values will be simply by looking at a 01697 * single row in the database, and it's probable that the sanest configuration 01698 * should have the first column in the "mgcpep" table be "clearvars", with a 01699 * static value of "all", if any variables are set at all. It may be worth 01700 * making this assumption explicit in the code in the future, and then just 01701 * using ast_load_realtime_multientry for the "mgcpep" records. 01702 */ 01703 lines[0] = '\0'; 01704 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) { 01705 if (!strcasecmp(gwv->name, "lines")) { 01706 ast_copy_string(lines, gwv->value, sizeof(lines)); 01707 break; 01708 } 01709 } 01710 /* Position gwv at the end of the list */ 01711 for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next); 01712 01713 if (!ast_strlen_zero(lines)) { 01714 AST_DECLARE_APP_ARGS(args, 01715 AST_APP_ARG(line)[100]; 01716 ); 01717 AST_STANDARD_APP_ARGS(args, lines); 01718 for (i = 0; i < args.argc; i++) { 01719 gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL); 01720 01721 /* Remove "line" AND position gwv at the end of the list. */ 01722 for (epname = NULL; gwv->next; gwv = gwv->next) { 01723 if (!strcasecmp(gwv->next->name, "line")) { 01724 /* Remove it from the list */ 01725 epname = gwv->next; 01726 gwv->next = gwv->next->next; 01727 } 01728 } 01729 /* Since "line" instantiates the configuration, we have to move it to the end. */ 01730 if (epname) { 01731 gwv->next = epname; 01732 epname->next = NULL; 01733 gwv = gwv->next; 01734 } 01735 } 01736 } 01737 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) { 01738 ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value); 01739 } 01740 01741 if (mgcpgwconfig) { 01742 g = build_gateway(at, mgcpgwconfig); 01743 ast_variables_destroy(mgcpgwconfig); 01744 } 01745 if (g) { 01746 g->next = gateways; 01747 g->realtime = 1; 01748 gateways = g; 01749 for (e = g->endpoints; e; e = e->next) { 01750 transmit_audit_endpoint(e); 01751 e->needaudit = 0; 01752 } 01753 } 01754 return g; 01755 }
static struct mgcp_subchannel* find_subchannel_and_lock | ( | char * | name, | |
int | msgid, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 1757 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_sockaddr_from_sin, ast_sockaddr_to_sin, ast_verb, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, find_realtime_gw(), gatelock, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, mgcp_gateway::ourip, and mgcp_endpoint::sub.
Referenced by mgcp_request(), and mgcpsock_read().
01758 { 01759 struct mgcp_endpoint *p = NULL; 01760 struct mgcp_subchannel *sub = NULL; 01761 struct mgcp_gateway *g; 01762 char tmp[256] = ""; 01763 char *at = NULL, *c; 01764 int found = 0; 01765 if (name) { 01766 ast_copy_string(tmp, name, sizeof(tmp)); 01767 at = strchr(tmp, '@'); 01768 if (!at) { 01769 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); 01770 return NULL; 01771 } 01772 *at++ = '\0'; 01773 } 01774 ast_mutex_lock(&gatelock); 01775 if (at && (at[0] == '[')) { 01776 at++; 01777 c = strrchr(at, ']'); 01778 if (c) { 01779 *c = '\0'; 01780 } 01781 } 01782 for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) { 01783 if ((!name || !strcasecmp(g->name, at)) && 01784 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { 01785 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ 01786 if (sin && g->dynamic && name) { 01787 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01788 (g->addr.sin_port != sin->sin_port)) { 01789 memcpy(&g->addr, sin, sizeof(g->addr)); 01790 { 01791 struct ast_sockaddr tmp1, tmp2; 01792 struct sockaddr_in tmp3 = {0,}; 01793 01794 tmp3.sin_addr = g->ourip; 01795 ast_sockaddr_from_sin(&tmp1, &g->addr); 01796 ast_sockaddr_from_sin(&tmp2, &tmp3); 01797 if (ast_ouraddrfor(&tmp1, &tmp2)) { 01798 memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 01799 } 01800 ast_sockaddr_to_sin(&tmp2, &tmp3); 01801 g->ourip = tmp3.sin_addr; 01802 } 01803 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)); 01804 } 01805 /* not dynamic, check if the name matches */ 01806 } else if (name) { 01807 if (strcasecmp(g->name, at)) { 01808 g = g->next; 01809 continue; 01810 } 01811 /* not dynamic, no name, check if the addr matches */ 01812 } else if (!name && sin) { 01813 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01814 (g->addr.sin_port != sin->sin_port)) { 01815 if(!g->next) 01816 g = find_realtime_gw(name, at, sin); 01817 else 01818 g = g->next; 01819 continue; 01820 } 01821 } else { 01822 continue; 01823 } 01824 for (p = g->endpoints; p; p = p->next) { 01825 ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name); 01826 if (msgid) { 01827 sub = p->sub; 01828 found = 1; 01829 break; 01830 } else if (name && !strcasecmp(p->name, tmp)) { 01831 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 01832 p->name, g->name, p->sub->id); 01833 sub = p->sub; 01834 found = 1; 01835 break; 01836 } 01837 } 01838 if (sub && found) { 01839 ast_mutex_lock(&sub->lock); 01840 break; 01841 } 01842 } 01843 } 01844 ast_mutex_unlock(&gatelock); 01845 if (!sub) { 01846 if (name) { 01847 if (g) { 01848 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); 01849 } else { 01850 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); 01851 } 01852 } 01853 } 01854 return sub; 01855 }
static char* get_csv | ( | char * | c, | |
int * | len, | |||
char ** | next | |||
) | [static] |
get_csv: (SC:) get comma separated value
Definition at line 1642 of file chan_mgcp.c.
Referenced by handle_response().
01643 { 01644 char *s; 01645 01646 *next = NULL, *len = 0; 01647 if (!c) return NULL; 01648 01649 while (*c && (*c < 33 || *c == ',')) { 01650 c++; 01651 } 01652 01653 s = c; 01654 while (*c && (*c >= 33 && *c != ',')) { 01655 c++, (*len)++; 01656 } 01657 *next = c; 01658 01659 if (*len == 0) { 01660 s = NULL, *next = NULL; 01661 } 01662 01663 return s; 01664 }
static char* get_header | ( | struct mgcp_request * | req, | |
char * | name | |||
) | [static] |
Definition at line 1635 of file chan_mgcp.c.
References __get_header().
Referenced by __transmit_response(), build_route(), cc_handle_publish_error(), change_redirecting_information(), check_auth(), check_user_full(), check_via(), check_via_response(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_pai(), get_rdnis(), get_realm(), get_refer_info(), get_rpid(), gettag(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_request(), handle_request_bye(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_register(), handle_request_subscribe(), handle_request_update(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_publish(), handle_response_refer(), handle_response_register(), handle_response_subscribe(), handle_response_update(), parse_allowed_methods(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), proc_422_rsp(), process_via(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_alloc(), sip_get_cc_information(), sip_pidf_validate(), 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().
01636 { 01637 int start = 0; 01638 return __get_header(req, name, &start, ""); 01639 }
static char* get_sdp | ( | struct mgcp_request * | req, | |
char * | name | |||
) | [static] |
Definition at line 1586 of file chan_mgcp.c.
References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.
Referenced by process_sdp().
01587 { 01588 int x; 01589 int len = strlen(name); 01590 char *r; 01591 01592 for (x = 0; x < req->lines; x++) { 01593 r = get_sdp_by_line(req->line[x], name, len); 01594 if (r[0] != '\0') return r; 01595 } 01596 return ""; 01597 }
static char* get_sdp_by_line | ( | char * | line, | |
char * | name, | |||
int | nameLen | |||
) | [static] |
Definition at line 1576 of file chan_mgcp.c.
Referenced by get_sdp(), and get_sdp_iterate().
01577 { 01578 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { 01579 char *r = line + nameLen + 1; 01580 while (*r && (*r < 33)) ++r; 01581 return r; 01582 } 01583 return ""; 01584 }
static char* get_sdp_iterate | ( | int * | iterator, | |
struct mgcp_request * | req, | |||
char * | name | |||
) | [static] |
Definition at line 1604 of file chan_mgcp.c.
References get_sdp_by_line(), len(), and mgcp_request::line.
Referenced by get_ip_and_port_from_sdp(), and process_sdp().
01605 { 01606 int len = strlen(name); 01607 char *r; 01608 while (*iterator < req->lines) { 01609 r = get_sdp_by_line(req->line[(*iterator)++], name, len); 01610 if (r[0] != '\0') return r; 01611 } 01612 return ""; 01613 }
static void handle_hd_hf | ( | struct mgcp_subchannel * | sub, | |
char * | ev | |||
) | [static] |
Definition at line 3254 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_endpoint::ncs, 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().
03255 { 03256 struct mgcp_endpoint *p = sub->parent; 03257 struct ast_channel *c; 03258 pthread_t t; 03259 03260 /* Off hook / answer */ 03261 if (sub->outgoing) { 03262 /* Answered */ 03263 if (sub->owner) { 03264 if (ast_bridged_channel(sub->owner)) 03265 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03266 sub->cxmode = MGCP_CX_SENDRECV; 03267 if (!sub->rtp) { 03268 start_rtp(sub); 03269 } else { 03270 transmit_modify_request(sub); 03271 } 03272 /*transmit_notify_request(sub, "aw");*/ 03273 transmit_notify_request(sub, ""); 03274 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 03275 } 03276 } else { 03277 /* Start switch */ 03278 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 03279 if (!sub->owner) { 03280 if (!sub->rtp) { 03281 start_rtp(sub); 03282 } else { 03283 transmit_modify_request(sub); 03284 } 03285 if (p->immediate) { 03286 /* The channel is immediately up. Start right away */ 03287 #ifdef DLINK_BUGGY_FIRMWARE 03288 transmit_notify_request(sub, "rt"); 03289 #else 03290 transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt"); 03291 #endif 03292 c = mgcp_new(sub, AST_STATE_RING, NULL); 03293 if (!c) { 03294 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 03295 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03296 ast_hangup(c); 03297 } 03298 } else { 03299 if (has_voicemail(p)) { 03300 transmit_notify_request(sub, "L/sl"); 03301 } else { 03302 transmit_notify_request(sub, "L/dl"); 03303 } 03304 c = mgcp_new(sub, AST_STATE_DOWN, NULL); 03305 if (c) { 03306 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { 03307 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 03308 ast_hangup(c); 03309 } 03310 } else { 03311 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 03312 } 03313 } 03314 } else { 03315 if (p->hookstate == MGCP_OFFHOOK) { 03316 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03317 } else { 03318 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03319 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 03320 } 03321 if (ast_bridged_channel(sub->owner)) 03322 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03323 sub->cxmode = MGCP_CX_SENDRECV; 03324 if (!sub->rtp) { 03325 start_rtp(sub); 03326 } else { 03327 transmit_modify_request(sub); 03328 } 03329 /*transmit_notify_request(sub, "aw");*/ 03330 transmit_notify_request(sub, ""); 03331 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03332 } 03333 } 03334 }
static char* handle_mgcp_audit_endpoint | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1080 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_mutex_lock, ast_strdupa, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, mgcp_gateway::endpoints, gatelock, gateways, mgcpdebug, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, transmit_audit_endpoint(), and ast_cli_entry::usage.
01081 { 01082 struct mgcp_gateway *mg; 01083 struct mgcp_endpoint *me; 01084 int found = 0; 01085 char *ename,*gname, *c; 01086 01087 switch (cmd) { 01088 case CLI_INIT: 01089 e->command = "mgcp audit endpoint"; 01090 e->usage = 01091 "Usage: mgcp audit endpoint <endpointid>\n" 01092 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n" 01093 " mgcp debug MUST be on to see the results of this command.\n"; 01094 return NULL; 01095 case CLI_GENERATE: 01096 return NULL; 01097 } 01098 01099 if (!mgcpdebug) { 01100 return CLI_SHOWUSAGE; 01101 } 01102 if (a->argc != 4) 01103 return CLI_SHOWUSAGE; 01104 /* split the name into parts by null */ 01105 ename = ast_strdupa(a->argv[3]); 01106 for (gname = ename; *gname; gname++) { 01107 if (*gname == '@') { 01108 *gname = 0; 01109 gname++; 01110 break; 01111 } 01112 } 01113 if (gname[0] == '[') { 01114 gname++; 01115 } 01116 if ((c = strrchr(gname, ']'))) { 01117 *c = '\0'; 01118 } 01119 ast_mutex_lock(&gatelock); 01120 for (mg = gateways; mg; mg = mg->next) { 01121 if (!strcasecmp(mg->name, gname)) { 01122 for (me = mg->endpoints; me; me = me->next) { 01123 if (!strcasecmp(me->name, ename)) { 01124 found = 1; 01125 transmit_audit_endpoint(me); 01126 break; 01127 } 01128 } 01129 if (found) { 01130 break; 01131 } 01132 } 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 1141 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.
01142 { 01143 switch (cmd) { 01144 case CLI_INIT: 01145 e->command = "mgcp set debug {on|off}"; 01146 e->usage = 01147 "Usage: mgcp set debug {on|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 != e->args) 01155 return CLI_SHOWUSAGE; 01156 01157 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 01158 mgcpdebug = 1; 01159 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01160 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01161 mgcpdebug = 0; 01162 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01163 } else { 01164 return CLI_SHOWUSAGE; 01165 } 01166 return CLI_SUCCESS; 01167 }
static char* handle_mgcp_show_endpoints | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1038 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock, mgcp_endpoint::chanvars, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, mgcp_endpoint::context, mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, ast_variable::name, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_subchannel::owner, mgcp_gateway::realtime, mgcp_endpoint::sub, ast_cli_entry::usage, and ast_variable::value.
01039 { 01040 struct mgcp_gateway *mg; 01041 struct mgcp_endpoint *me; 01042 int hasendpoints = 0; 01043 struct ast_variable * v = NULL; 01044 01045 switch (cmd) { 01046 case CLI_INIT: 01047 e->command = "mgcp show endpoints"; 01048 e->usage = 01049 "Usage: mgcp show endpoints\n" 01050 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n"; 01051 return NULL; 01052 case CLI_GENERATE: 01053 return NULL; 01054 } 01055 01056 if (a->argc != 3) { 01057 return CLI_SHOWUSAGE; 01058 } 01059 ast_mutex_lock(&gatelock); 01060 for (mg = gateways; mg; mg = mg->next) { 01061 ast_cli(a->fd, "Gateway '%s' at %s (%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->realtime ? "Realtime, " : "", mg->dynamic ? "Dynamic" : "Static"); 01062 for (me = mg->endpoints; me; me = me->next) { 01063 ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle"); 01064 if (me->chanvars) { 01065 ast_cli(a->fd, " Variables:\n"); 01066 for (v = me->chanvars ; v ; v = v->next) { 01067 ast_cli(a->fd, " %s = '%s'\n", v->name, v->value); 01068 } 01069 } 01070 hasendpoints = 1; 01071 } 01072 if (!hasendpoints) { 01073 ast_cli(a->fd, " << No Endpoints Defined >> "); 01074 } 01075 } 01076 ast_mutex_unlock(&gatelock); 01077 return CLI_SUCCESS; 01078 }
static int handle_request | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 3336 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, 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_endpoint::ncs, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, 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().
03337 { 03338 char *ev, *s; 03339 struct ast_frame f = { 0, }; 03340 struct mgcp_endpoint *p = sub->parent; 03341 struct mgcp_gateway *g = NULL; 03342 int res; 03343 03344 ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03345 /* Clear out potential response */ 03346 if (!strcasecmp(req->verb, "RSIP")) { 03347 /* Test if this RSIP request is just a keepalive */ 03348 if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03349 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03350 transmit_response(sub, "200", req, "OK"); 03351 } else { 03352 dump_queue(p->parent, p); 03353 dump_cmd_queues(p, NULL); 03354 03355 if ((strcmp(p->name, p->parent->wcardep) != 0)) { 03356 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); 03357 } 03358 /* For RSIP on wildcard we reset all endpoints */ 03359 if (!strcmp(p->name, p->parent->wcardep)) { 03360 /* Reset all endpoints */ 03361 struct mgcp_endpoint *tmp_ep; 03362 03363 g = p->parent; 03364 for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) { 03365 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03366 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03367 struct mgcp_subchannel *tmp_sub, *first_sub; 03368 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03369 03370 first_sub = tmp_ep->sub; 03371 tmp_sub = tmp_ep->sub; 03372 while (tmp_sub) { 03373 mgcp_queue_hangup(tmp_sub); 03374 tmp_sub = tmp_sub->next; 03375 if (tmp_sub == first_sub) 03376 break; 03377 } 03378 } 03379 } 03380 } else if (sub->owner) { 03381 mgcp_queue_hangup(sub); 03382 } 03383 transmit_response(sub, "200", req, "OK"); 03384 /* We don't send NTFY or AUEP to wildcard ep */ 03385 if (strcmp(p->name, p->parent->wcardep) != 0) { 03386 transmit_notify_request(sub, ""); 03387 /* Audit endpoint. 03388 Idea is to prevent lost lines due to race conditions 03389 */ 03390 transmit_audit_endpoint(p); 03391 } 03392 } 03393 } else if (!strcasecmp(req->verb, "NTFY")) { 03394 /* Acknowledge and be sure we keep looking for the same things */ 03395 transmit_response(sub, "200", req, "OK"); 03396 /* Notified of an event */ 03397 ev = get_header(req, "O"); 03398 s = strchr(ev, '/'); 03399 if (s) ev = s + 1; 03400 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03401 /* Keep looking for events unless this was a hangup */ 03402 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03403 transmit_notify_request(sub, p->curtone); 03404 } 03405 if (!strcasecmp(ev, "hd")) { 03406 p->hookstate = MGCP_OFFHOOK; 03407 sub->cxmode = MGCP_CX_SENDRECV; 03408 03409 if (p) { 03410 /* When the endpoint have a Off hook transition we allways 03411 starts without any previous dtmfs */ 03412 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03413 } 03414 03415 handle_hd_hf(sub, ev); 03416 } else if (!strcasecmp(ev, "hf")) { 03417 /* We can assume we are offhook if we received a hookflash */ 03418 /* First let's just do call wait and ignore threeway */ 03419 /* We're currently in charge */ 03420 if (p->hookstate != MGCP_OFFHOOK) { 03421 /* Cisco c7940 sends hf even if the phone is onhook */ 03422 /* Thanks to point on IRC for pointing this out */ 03423 return -1; 03424 } 03425 /* do not let * conference two down channels */ 03426 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) 03427 return -1; 03428 03429 if (p->callwaiting || p->transfer || p->threewaycalling) { 03430 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03431 p->sub = p->sub->next; 03432 03433 /* transfer control to our next subchannel */ 03434 if (!sub->next->owner) { 03435 /* plave the first call on hold and start up a new call */ 03436 sub->cxmode = MGCP_CX_MUTE; 03437 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03438 transmit_modify_request(sub); 03439 if (sub->owner && ast_bridged_channel(sub->owner)) 03440 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03441 sub->next->cxmode = MGCP_CX_RECVONLY; 03442 handle_hd_hf(sub->next, ev); 03443 } else if (sub->owner && sub->next->owner) { 03444 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03445 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03446 /* We made both calls lets conferenct */ 03447 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", 03448 sub->id, sub->next->id, p->name, p->parent->name); 03449 sub->cxmode = MGCP_CX_CONF; 03450 sub->next->cxmode = MGCP_CX_CONF; 03451 if (ast_bridged_channel(sub->next->owner)) 03452 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03453 transmit_modify_request(sub); 03454 transmit_modify_request(sub->next); 03455 } else { 03456 /* Let's flipflop between calls */ 03457 /* XXX Need to check for state up ??? */ 03458 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03459 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03460 sub->id, sub->next->id, p->name, p->parent->name); 03461 sub->cxmode = MGCP_CX_MUTE; 03462 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03463 transmit_modify_request(sub); 03464 if (ast_bridged_channel(sub->owner)) 03465 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03466 03467 if (ast_bridged_channel(sub->next->owner)) 03468 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03469 03470 handle_hd_hf(sub->next, ev); 03471 } 03472 } else { 03473 /* We've most likely lost one of our calls find an active call and bring it up */ 03474 if (sub->owner) { 03475 p->sub = sub; 03476 } else if (sub->next->owner) { 03477 p->sub = sub->next; 03478 } else { 03479 /* We seem to have lost both our calls */ 03480 /* XXX - What do we do now? */ 03481 return -1; 03482 } 03483 if (ast_bridged_channel(p->sub->owner)) 03484 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03485 p->sub->cxmode = MGCP_CX_SENDRECV; 03486 transmit_modify_request(p->sub); 03487 } 03488 } else { 03489 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03490 p->name, p->parent->name); 03491 } 03492 } else if (!strcasecmp(ev, "hu")) { 03493 p->hookstate = MGCP_ONHOOK; 03494 sub->cxmode = MGCP_CX_RECVONLY; 03495 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03496 /* Do we need to send MDCX before a DLCX ? 03497 if (sub->rtp) { 03498 transmit_modify_request(sub); 03499 } 03500 */ 03501 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03502 /* We're allowed to transfer, we have two avtive calls and */ 03503 /* we made at least one of the calls. Let's try and transfer */ 03504 ast_mutex_lock(&p->sub->next->lock); 03505 res = attempt_transfer(p); 03506 if (res < 0) { 03507 if (p->sub->next->owner) { 03508 sub->next->alreadygone = 1; 03509 mgcp_queue_hangup(sub->next); 03510 } 03511 } else if (res) { 03512 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03513 ast_mutex_unlock(&p->sub->next->lock); 03514 return -1; 03515 } 03516 ast_mutex_unlock(&p->sub->next->lock); 03517 } else { 03518 /* Hangup the current call */ 03519 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03520 if (sub->owner) { 03521 sub->alreadygone = 1; 03522 mgcp_queue_hangup(sub); 03523 } else { 03524 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03525 p->name, p->parent->name, sub->id); 03526 /* Instruct the other side to remove the connection since it apparently * 03527 * still thinks the channel is active. * 03528 * For Cisco IAD2421 /BAK/ */ 03529 transmit_connection_del(sub); 03530 } 03531 } 03532 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03533 p->hidecallerid = 0; 03534 if (p->hascallwaiting && !p->callwaiting) { 03535 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03536 p->callwaiting = -1; 03537 } 03538 if (has_voicemail(p)) { 03539 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03540 transmit_notify_request(sub, "L/vmwi(+)"); 03541 } else { 03542 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03543 transmit_notify_request(sub, "L/vmwi(-)"); 03544 } 03545 } 03546 } else if ((strlen(ev) == 1) && 03547 (((ev[0] >= '0') && (ev[0] <= '9')) || 03548 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03549 (ev[0] == '*') || (ev[0] == '#'))) { 03550 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) { 03551 f.frametype = AST_FRAME_DTMF; 03552 f.subclass.integer = ev[0]; 03553 f.src = "mgcp"; 03554 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03555 mgcp_queue_frame(sub, &f); 03556 ast_mutex_lock(&sub->next->lock); 03557 if (sub->next->owner) 03558 mgcp_queue_frame(sub->next, &f); 03559 ast_mutex_unlock(&sub->next->lock); 03560 if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) { 03561 memset(p->curtone, 0, sizeof(p->curtone)); 03562 } 03563 } else { 03564 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; 03565 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; 03566 } 03567 } else if (!strcasecmp(ev, "T")) { 03568 /* Digit timeout -- unimportant */ 03569 } else if (!strcasecmp(ev, "ping")) { 03570 /* ping -- unimportant */ 03571 } else { 03572 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03573 } 03574 } else { 03575 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03576 transmit_response(sub, "510", req, "Unknown verb"); 03577 } 03578 return 0; 03579 }
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 2744 of file chan_mgcp.c.
References AST_CONTROL_RINGING, ast_copy_string(), ast_free, ast_log(), ast_queue_control(), AST_STATE_RINGING, 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_CMD_MDCX, 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(), transmit_notify_request(), and transmit_response().
Referenced by handle_incoming(), mgcpsock_read(), and retrans_pkt().
02746 { 02747 char *c; 02748 struct mgcp_request *req; 02749 struct mgcp_gateway *gw = p->parent; 02750 02751 if (result < 200) { 02752 /* provisional response */ 02753 return; 02754 } 02755 02756 if (p->slowsequence) 02757 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02758 else if (sub) 02759 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02760 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02761 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02762 02763 if (!req) { 02764 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", 02765 gw->name, ident); 02766 return; 02767 } 02768 02769 if (p && (result >= 400) && (result <= 599)) { 02770 switch (result) { 02771 case 401: 02772 p->hookstate = MGCP_OFFHOOK; 02773 break; 02774 case 402: 02775 p->hookstate = MGCP_ONHOOK; 02776 break; 02777 case 406: 02778 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02779 break; 02780 case 407: 02781 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02782 break; 02783 } 02784 if (sub) { 02785 if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) { 02786 ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result); 02787 transmit_connection_del(sub); 02788 } 02789 if (sub->owner) { 02790 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02791 result, p->name, p->parent->name, sub ? sub->id:-1); 02792 mgcp_queue_hangup(sub); 02793 } 02794 } else { 02795 if (p->sub->next->owner) { 02796 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02797 result, p->name, p->parent->name, sub ? sub->id:-1); 02798 mgcp_queue_hangup(p->sub); 02799 } 02800 02801 if (p->sub->owner) { 02802 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02803 result, p->name, p->parent->name, sub ? sub->id:-1); 02804 mgcp_queue_hangup(p->sub); 02805 } 02806 02807 dump_cmd_queues(p, NULL); 02808 } 02809 } 02810 02811 if (resp) { 02812 /* responseAck: */ 02813 if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) { 02814 if (sub) { 02815 transmit_response(sub, "000", resp, "OK"); 02816 if (sub->owner && sub->owner->_state == AST_STATE_RINGING) { 02817 ast_queue_control(sub->owner, AST_CONTROL_RINGING); 02818 } 02819 } 02820 } 02821 if (req->cmd == MGCP_CMD_CRCX) { 02822 if ((c = get_header(resp, "I"))) { 02823 if (!ast_strlen_zero(c) && sub) { 02824 /* if we are hanging up do not process this conn. */ 02825 if (sub->owner) { 02826 if (!ast_strlen_zero(sub->cxident)) { 02827 if (strcasecmp(c, sub->cxident)) { 02828 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02829 } 02830 } 02831 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02832 if (sub->tmpdest.sin_addr.s_addr) { 02833 transmit_modify_with_sdp(sub, NULL, 0); 02834 } 02835 } else { 02836 /* XXX delete this one 02837 callid and conn id may already be lost. 02838 so the following del conn may have a side effect of 02839 cleaning up the next subchannel */ 02840 transmit_connection_del(sub); 02841 } 02842 } 02843 } 02844 } 02845 02846 if (req->cmd == MGCP_CMD_AUEP) { 02847 /* check stale connection ids */ 02848 if ((c = get_header(resp, "I"))) { 02849 char *v, *n; 02850 int len; 02851 while ((v = get_csv(c, &len, &n))) { 02852 if (len) { 02853 if (strncasecmp(v, p->sub->cxident, len) && 02854 strncasecmp(v, p->sub->next->cxident, len)) { 02855 /* connection id not found. delete it */ 02856 char cxident[80] = ""; 02857 02858 if (len > (sizeof(cxident) - 1)) 02859 len = sizeof(cxident) - 1; 02860 ast_copy_string(cxident, v, len); 02861 ast_verb(3, "Non existing connection id %s on %s@%s \n", 02862 cxident, p->name, gw->name); 02863 transmit_connection_del_w_params(p, NULL, cxident); 02864 } 02865 } 02866 c = n; 02867 } 02868 } 02869 02870 /* Try to determine the hookstate returned from an audit endpoint command */ 02871 if ((c = get_header(resp, "ES"))) { 02872 if (!ast_strlen_zero(c)) { 02873 if (strstr(c, "hu")) { 02874 if (p->hookstate != MGCP_ONHOOK) { 02875 /* XXX cleanup if we think we are offhook XXX */ 02876 if ((p->sub->owner || p->sub->next->owner ) && 02877 p->hookstate == MGCP_OFFHOOK) 02878 mgcp_queue_hangup(sub); 02879 p->hookstate = MGCP_ONHOOK; 02880 02881 /* update the requested events according to the new hookstate */ 02882 transmit_notify_request(p->sub, ""); 02883 02884 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02885 } 02886 } else if (strstr(c, "hd")) { 02887 if (p->hookstate != MGCP_OFFHOOK) { 02888 p->hookstate = MGCP_OFFHOOK; 02889 02890 /* update the requested events according to the new hookstate */ 02891 transmit_notify_request(p->sub, ""); 02892 02893 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02894 } 02895 } 02896 } 02897 } 02898 } 02899 02900 if (resp && resp->lines) { 02901 /* do not process sdp if we are hanging up. this may be a late response */ 02902 if (sub && sub->owner) { 02903 if (!sub->rtp) 02904 start_rtp(sub); 02905 if (sub->rtp) 02906 process_sdp(sub, resp); 02907 } 02908 } 02909 } 02910 02911 ast_free(req); 02912 }
static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 491 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().
00492 { 00493 int new_msgs; 00494 struct ast_event *event; 00495 char *mbox, *cntx; 00496 00497 cntx = mbox = ast_strdupa(p->mailbox); 00498 strsep(&cntx, "@"); 00499 if (ast_strlen_zero(cntx)) 00500 cntx = "default"; 00501 00502 event = ast_event_get_cached(AST_EVENT_MWI, 00503 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 00504 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 00505 AST_EVENT_IE_END); 00506 00507 if (event) { 00508 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 00509 ast_event_destroy(event); 00510 } else 00511 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 00512 00513 return new_msgs; 00514 }
static int init_req | ( | struct mgcp_endpoint * | p, | |
struct mgcp_request * | req, | |||
char * | verb | |||
) | [static] |
Definition at line 2107 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, mgcp_endpoint::ncs, oseq, and mgcp_endpoint::parent.
Referenced by initreqprep(), reqprep(), and transmit_register().
02108 { 02109 /* Initialize a response */ 02110 if (req->headers || req->len) { 02111 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02112 return -1; 02113 } 02114 req->header[req->headers] = req->data + req->len; 02115 /* check if we need brackets around the gw name */ 02116 if (p->parent->isnamedottedip) { 02117 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : ""); 02118 } else { 02119 + snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : ""); 02120 } 02121 req->len += strlen(req->header[req->headers]); 02122 if (req->headers < MGCP_MAX_HEADERS) { 02123 req->headers++; 02124 } else { 02125 ast_log(LOG_WARNING, "Out of header space\n"); 02126 } 02127 return 0; 02128 }
static int init_resp | ( | struct mgcp_request * | req, | |
char * | resp, | |||
struct mgcp_request * | orig, | |||
char * | resprest | |||
) | [static] |
Definition at line 2089 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().
02090 { 02091 /* Initialize a response */ 02092 if (req->headers || req->len) { 02093 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02094 return -1; 02095 } 02096 req->header[req->headers] = req->data + req->len; 02097 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 02098 req->len += strlen(req->header[req->headers]); 02099 if (req->headers < MGCP_MAX_HEADERS) { 02100 req->headers++; 02101 } else { 02102 ast_log(LOG_WARNING, "Out of header space\n"); 02103 } 02104 return 0; 02105 }
static int load_module | ( | void | ) | [static] |
load_module: PBX load module - initialization ---
Definition at line 4780 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_glue_register, cli_mgcp, io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, mgcp_rtp_glue, mgcp_tech, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().
04781 { 04782 if (!(sched = sched_context_create())) { 04783 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 04784 return AST_MODULE_LOAD_FAILURE; 04785 } 04786 04787 if (!(io = io_context_create())) { 04788 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 04789 sched_context_destroy(sched); 04790 return AST_MODULE_LOAD_FAILURE; 04791 } 04792 04793 if (reload_config(0)) 04794 return AST_MODULE_LOAD_DECLINE; 04795 04796 /* Make sure we can register our mgcp channel type */ 04797 if (ast_channel_register(&mgcp_tech)) { 04798 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); 04799 io_context_destroy(io); 04800 sched_context_destroy(sched); 04801 return AST_MODULE_LOAD_FAILURE; 04802 } 04803 04804 ast_rtp_glue_register(&mgcp_rtp_glue); 04805 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04806 04807 /* And start the monitor for the first time */ 04808 restart_monitor(); 04809 04810 return AST_MODULE_LOAD_SUCCESS; 04811 }
static int mgcp_alloc_pktcgate | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2409 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_pktccops_gate_alloc(), mgcp_subchannel::gate, cops_gate::gate_open, GATE_SET, mgcp_pktcgate_open(), mgcp_pktcgate_remove(), mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::sub, and cops_gate::tech_pvt.
Referenced by start_rtp().
02410 { 02411 struct mgcp_endpoint *p = sub->parent; 02412 sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr), 02413 8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove); 02414 02415 if (!sub->gate) { 02416 return 0; 02417 } 02418 sub->gate->tech_pvt = sub; 02419 sub->gate->gate_open = &mgcp_pktcgate_open; 02420 return 1; 02421 }
static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1176 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().
01177 { 01178 int res = 0; 01179 struct mgcp_subchannel *sub = ast->tech_pvt; 01180 struct mgcp_endpoint *p = sub->parent; 01181 01182 ast_mutex_lock(&sub->lock); 01183 sub->cxmode = MGCP_CX_SENDRECV; 01184 if (!sub->rtp) { 01185 start_rtp(sub); 01186 } else { 01187 transmit_modify_request(sub); 01188 } 01189 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", 01190 ast->name, p->name, p->parent->name, sub->id); 01191 if (ast->_state != AST_STATE_UP) { 01192 ast_setstate(ast, AST_STATE_UP); 01193 ast_debug(1, "mgcp_answer(%s)\n", ast->name); 01194 transmit_notify_request(sub, ""); 01195 transmit_modify_request(sub); 01196 } 01197 ast_mutex_unlock(&sub->lock); 01198 return res; 01199 }
static int mgcp_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 836 of file chan_mgcp.c.
References ast_channel::_state, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), mgcp_subchannel::callid, ast_channel::connected, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, ast_party_connected_line::id, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, ast_party_id::name, ast_channel::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, S_COR, start_rtp(), ast_party_name::str, ast_party_number::str, ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, ast_party_name::valid, ast_party_number::valid, and ast_channel::varshead.
00837 { 00838 int res; 00839 struct mgcp_endpoint *p; 00840 struct mgcp_subchannel *sub; 00841 char tone[50] = ""; 00842 const char *distinctive_ring = NULL; 00843 struct varshead *headp; 00844 struct ast_var_t *current; 00845 00846 ast_debug(3, "MGCP mgcp_call(%s)\n", ast->name); 00847 sub = ast->tech_pvt; 00848 p = sub->parent; 00849 headp = &ast->varshead; 00850 AST_LIST_TRAVERSE(headp,current,entries) { 00851 /* Check whether there is an ALERT_INFO variable */ 00852 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { 00853 distinctive_ring = ast_var_value(current); 00854 } 00855 } 00856 00857 ast_mutex_lock(&sub->lock); 00858 switch (p->hookstate) { 00859 case MGCP_OFFHOOK: 00860 if (!ast_strlen_zero(distinctive_ring)) { 00861 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); 00862 ast_debug(3, "MGCP distinctive callwait %s\n", tone); 00863 } else { 00864 ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone)); 00865 ast_debug(3, "MGCP normal callwait %s\n", tone); 00866 } 00867 break; 00868 case MGCP_ONHOOK: 00869 default: 00870 if (!ast_strlen_zero(distinctive_ring)) { 00871 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); 00872 ast_debug(3, "MGCP distinctive ring %s\n", tone); 00873 } else { 00874 ast_copy_string(tone, "L/rg", sizeof(tone)); 00875 ast_debug(3, "MGCP default ring\n"); 00876 } 00877 break; 00878 } 00879 00880 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00881 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name); 00882 ast_mutex_unlock(&sub->lock); 00883 return -1; 00884 } 00885 00886 res = 0; 00887 sub->outgoing = 1; 00888 sub->cxmode = MGCP_CX_RECVONLY; 00889 ast_setstate(ast, AST_STATE_RINGING); 00890 if (p->type == TYPE_LINE) { 00891 if (!sub->rtp) { 00892 start_rtp(sub); 00893 } else { 00894 transmit_modify_request(sub); 00895 } 00896 00897 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00898 /* try to prevent a callwait from disturbing the other connection */ 00899 sub->next->cxmode = MGCP_CX_RECVONLY; 00900 transmit_modify_request(sub->next); 00901 } 00902 00903 transmit_notify_request_with_callerid(sub, tone, 00904 S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""), 00905 S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, "")); 00906 ast_setstate(ast, AST_STATE_RINGING); 00907 00908 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00909 /* Put the connection back in sendrecv */ 00910 sub->next->cxmode = MGCP_CX_SENDRECV; 00911 transmit_modify_request(sub->next); 00912 } 00913 } else { 00914 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); 00915 res = -1; 00916 } 00917 ast_mutex_unlock(&sub->lock); 00918 return res; 00919 }
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 1361 of file chan_mgcp.c.
References AST_DEVICE_INVALID, ast_mutex_lock, ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_gateway::name, and mgcp_gateway::next.
01362 { 01363 struct mgcp_gateway *g; 01364 struct mgcp_endpoint *e = NULL; 01365 char *tmp, *endpt, *gw; 01366 int ret = AST_DEVICE_INVALID; 01367 01368 endpt = ast_strdupa(data); 01369 if ((tmp = strchr(endpt, '@'))) { 01370 *tmp++ = '\0'; 01371 gw = tmp; 01372 } else 01373 goto error; 01374 01375 ast_mutex_lock(&gatelock); 01376 for (g = gateways; g; g = g->next) { 01377 if (strcasecmp(g->name, gw) == 0) { 01378 e = g->endpoints; 01379 break; 01380 } 01381 } 01382 01383 if (!e) 01384 goto error; 01385 01386 for (; e; e = e->next) { 01387 if (strcasecmp(e->name, endpt) == 0) { 01388 break; 01389 } 01390 } 01391 01392 if (!e) 01393 goto error; 01394 01395 /* 01396 * As long as the gateway/endpoint is valid, we'll 01397 * assume that the device is available and its state 01398 * can be tracked. 01399 */ 01400 ret = AST_DEVICE_UNKNOWN; 01401 01402 error: 01403 ast_mutex_unlock(&gatelock); 01404 return ret; 01405 }
static int mgcp_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 1283 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.
01284 { 01285 struct mgcp_subchannel *sub = newchan->tech_pvt; 01286 01287 ast_mutex_lock(&sub->lock); 01288 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name); 01289 if (sub->owner != oldchan) { 01290 ast_mutex_unlock(&sub->lock); 01291 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01292 return -1; 01293 } 01294 sub->owner = newchan; 01295 ast_mutex_unlock(&sub->lock); 01296 return 0; 01297 }
static format_t mgcp_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 4428 of file chan_mgcp.c.
References mgcp_endpoint::capability, mgcp_subchannel::parent, mgcp_endpoint::sub, and ast_channel::tech_pvt.
04429 { 04430 struct mgcp_subchannel *sub = chan->tech_pvt; 04431 struct mgcp_endpoint *p = sub->parent; 04432 return p->capability; 04433 }
static enum ast_rtp_glue_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp_instance ** | instance | |||
) | [static] |
Definition at line 4401 of file chan_mgcp.c.
References ao2_ref, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, mgcp_endpoint::directmedia, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
04402 { 04403 struct mgcp_subchannel *sub = NULL; 04404 04405 if (!(sub = chan->tech_pvt) || !(sub->rtp)) 04406 return AST_RTP_GLUE_RESULT_FORBID; 04407 04408 *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL; 04409 04410 if (sub->parent->directmedia) 04411 return AST_RTP_GLUE_RESULT_REMOTE; 04412 else 04413 return AST_RTP_GLUE_RESULT_LOCAL; 04414 }
static int mgcp_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 921 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_pktccops_gate_alloc(), ast_rtp_instance_destroy(), ast_strlen_zero(), ast_verb, ast_channel::caller, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, cops_gate::deltimer, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, mgcp_subchannel::gate, GATE_ALLOC_PROGRESS, GATE_ALLOCATED, GATE_DEL, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, ast_party_caller::id, 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, ast_party_id::name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, mgcp_subchannel::rtp, S_COR, cops_gate::state, ast_party_name::str, ast_party_number::str, mgcp_endpoint::sub, cops_gate::tech_pvt, ast_channel::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), transmit_notify_request_with_callerid(), ast_party_name::valid, and ast_party_number::valid.
00922 { 00923 struct mgcp_subchannel *sub = ast->tech_pvt; 00924 struct mgcp_endpoint *p = sub->parent; 00925 struct ast_channel *bridged; 00926 00927 ast_debug(1, "mgcp_hangup(%s)\n", ast->name); 00928 if (!ast->tech_pvt) { 00929 ast_debug(1, "Asked to hangup channel not connected\n"); 00930 return 0; 00931 } 00932 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) { 00933 ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n"); 00934 return 0; 00935 } 00936 ast_mutex_lock(&sub->lock); 00937 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name); 00938 00939 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) { 00940 /* check whether other channel is active. */ 00941 if (!sub->next->owner) { 00942 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 00943 p->dtmfmode &= ~MGCP_DTMF_INBAND; 00944 } 00945 ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name); 00946 ast_dsp_free(p->dsp); 00947 p->dsp = NULL; 00948 } 00949 } 00950 00951 sub->owner = NULL; 00952 00953 /* for deleting gate */ 00954 if (p->pktcgatealloc && sub->gate) { 00955 sub->gate->gate_open = NULL; 00956 sub->gate->gate_remove = NULL; 00957 sub->gate->got_dq_gi = NULL; 00958 sub->gate->tech_pvt = NULL; 00959 if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) { 00960 ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL); 00961 } else { 00962 sub->gate->deltimer = time(NULL) + 5; 00963 } 00964 sub->gate = NULL; 00965 } 00966 00967 if (!ast_strlen_zero(sub->cxident)) { 00968 transmit_connection_del(sub); 00969 } 00970 sub->cxident[0] = '\0'; 00971 if ((sub == p->sub) && sub->next->owner) { 00972 if (p->hookstate == MGCP_OFFHOOK) { 00973 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00974 /* ncs fix! */ 00975 bridged = ast_bridged_channel(sub->next->owner); 00976 transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"), 00977 S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""), 00978 S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, "")); 00979 } 00980 } else { 00981 /* set our other connection as the primary and swith over to it */ 00982 p->sub = sub->next; 00983 p->sub->cxmode = MGCP_CX_RECVONLY; 00984 transmit_modify_request(p->sub); 00985 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00986 bridged = ast_bridged_channel(sub->next->owner); 00987 transmit_notify_request_with_callerid(p->sub, "L/rg", 00988 S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""), 00989 S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, "")); 00990 } 00991 } 00992 00993 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) { 00994 transmit_notify_request(sub, p->ncs ? "" : "L/v"); 00995 } else if (p->hookstate == MGCP_OFFHOOK) { 00996 transmit_notify_request(sub, "L/ro"); 00997 } else { 00998 transmit_notify_request(sub, ""); 00999 } 01000 01001 ast->tech_pvt = NULL; 01002 sub->alreadygone = 0; 01003 sub->outgoing = 0; 01004 sub->cxmode = MGCP_CX_INACTIVE; 01005 sub->callid[0] = '\0'; 01006 if (p) { 01007 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 01008 } 01009 /* Reset temporary destination */ 01010 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 01011 if (sub->rtp) { 01012 ast_rtp_instance_destroy(sub->rtp); 01013 sub->rtp = NULL; 01014 } 01015 01016 ast_module_unref(ast_module_info->self); 01017 01018 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) { 01019 p->hidecallerid = 0; 01020 if (p->hascallwaiting && !p->callwaiting) { 01021 ast_verb(3, "Enabling call waiting on %s\n", ast->name); 01022 p->callwaiting = -1; 01023 } 01024 if (has_voicemail(p)) { 01025 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 01026 ast->name, p->name, p->parent->name); 01027 transmit_notify_request(sub, "L/vmwi(+)"); 01028 } else { 01029 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 01030 ast->name, p->name, p->parent->name); 01031 transmit_notify_request(sub, "L/vmwi(-)"); 01032 } 01033 } 01034 ast_mutex_unlock(&sub->lock); 01035 return 0; 01036 }
static int mgcp_indicate | ( | struct ast_channel * | ast, | |
int | ind, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 1439 of file chan_mgcp.c.
References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), control2str(), mgcp_subchannel::lock, LOG_WARNING, ast_channel::name, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01440 { 01441 struct mgcp_subchannel *sub = ast->tech_pvt; 01442 int res = 0; 01443 01444 ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", 01445 ind, control2str(ind), ast->name); 01446 ast_mutex_lock(&sub->lock); 01447 switch(ind) { 01448 case AST_CONTROL_RINGING: 01449 #ifdef DLINK_BUGGY_FIRMWARE 01450 transmit_notify_request(sub, "rt"); 01451 #else 01452 if (!sub->sdpsent) { /* will hide the inband progress!!! */ 01453 transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt"); 01454 } 01455 #endif 01456 break; 01457 case AST_CONTROL_BUSY: 01458 transmit_notify_request(sub, "L/bz"); 01459 break; 01460 case AST_CONTROL_INCOMPLETE: 01461 /* We do not currently support resetting of the Interdigit Timer, so treat 01462 * Incomplete control frames as a congestion response 01463 */ 01464 case AST_CONTROL_CONGESTION: 01465 transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg"); 01466 break; 01467 case AST_CONTROL_HOLD: 01468 ast_moh_start(ast, data, NULL); 01469 break; 01470 case AST_CONTROL_UNHOLD: 01471 ast_moh_stop(ast); 01472 break; 01473 case AST_CONTROL_SRCUPDATE: 01474 ast_rtp_instance_update_source(sub->rtp); 01475 break; 01476 case AST_CONTROL_SRCCHANGE: 01477 ast_rtp_instance_change_source(sub->rtp); 01478 break; 01479 case AST_CONTROL_PROGRESS: 01480 case AST_CONTROL_PROCEEDING: 01481 transmit_modify_request(sub); 01482 case -1: 01483 transmit_notify_request(sub, ""); 01484 break; 01485 default: 01486 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); 01487 res = -1; 01488 } 01489 ast_mutex_unlock(&sub->lock); 01490 return res; 01491 }
static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, | |
int | state, | |||
const char * | linkedid | |||
) | [static] |
Definition at line 1493 of file chan_mgcp.c.
References accountcode, mgcp_endpoint::accountcode, mgcp_endpoint::adsi, ast_channel::adsicpe, ast_channel::amaflags, mgcp_endpoint::amaflags, ast_party_caller::ani, 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_get_encoded_str(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_instance_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, ast_channel::caller, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, mgcp_endpoint::chanvars, 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, ast_variable::name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, ast_variable::next, ast_party_id::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, ast_party_number::str, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, and ast_channel::writeformat.
Referenced by handle_hd_hf(), and mgcp_request().
01494 { 01495 struct ast_channel *tmp; 01496 struct ast_variable *v = NULL; 01497 struct mgcp_endpoint *i = sub->parent; 01498 int fmt; 01499 01500 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); 01501 if (tmp) { 01502 tmp->tech = &mgcp_tech; 01503 tmp->nativeformats = i->capability; 01504 if (!tmp->nativeformats) { 01505 tmp->nativeformats = capability; 01506 } 01507 fmt = ast_best_codec(tmp->nativeformats); 01508 if (sub->rtp) { 01509 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); 01510 } 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 if (!ast_strlen_zero(i->cid_num)) { 01543 tmp->caller.ani.number.valid = 1; 01544 tmp->caller.ani.number.str = ast_strdup(i->cid_num); 01545 } 01546 01547 if (!i->adsi) { 01548 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 01549 } 01550 tmp->priority = 1; 01551 01552 /* Set channel variables for this call from configuration */ 01553 for (v = i->chanvars ; v ; v = v->next) { 01554 char valuebuf[1024]; 01555 pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf))); 01556 } 01557 01558 if (sub->rtp) { 01559 ast_jb_configure(tmp, &global_jbconf); 01560 } 01561 if (state != AST_STATE_DOWN) { 01562 if (ast_pbx_start(tmp)) { 01563 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 01564 ast_hangup(tmp); 01565 tmp = NULL; 01566 } 01567 } 01568 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", 01569 tmp->name, ast_state2str(state)); 01570 } else { 01571 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01572 } 01573 return tmp; 01574 }
static int mgcp_pktcgate_open | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2396 of file chan_mgcp.c.
References ast_debug, ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::gate, cops_gate::gateid, mgcp_subchannel::lock, mgcp_subchannel::sdpsent, cops_gate::tech_pvt, and transmit_modify_with_sdp().
Referenced by mgcp_alloc_pktcgate().
02397 { 02398 struct mgcp_subchannel *sub = gate->tech_pvt; 02399 if (!sub) { 02400 return 1; 02401 } 02402 ast_mutex_lock(&sub->lock); 02403 ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid); 02404 if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0); 02405 ast_mutex_unlock(&sub->lock); 02406 return 1; 02407 }
static int mgcp_pktcgate_remove | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2373 of file chan_mgcp.c.
References AST_CAUSE_REQUESTED_CHAN_UNAVAIL, ast_channel_unlock, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), mgcp_subchannel::gate, GATE_CLOSED, cops_gate::gateid, mgcp_endpoint::hangupongateremove, mgcp_subchannel::lock, mgcp_subchannel::owner, mgcp_subchannel::parent, cops_gate::state, and cops_gate::tech_pvt.
Referenced by mgcp_alloc_pktcgate().
02374 { 02375 struct mgcp_subchannel *sub = gate->tech_pvt; 02376 02377 if (!sub) { 02378 return 1; 02379 } 02380 02381 ast_mutex_lock(&sub->lock); 02382 ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid); 02383 if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) { 02384 sub->gate = NULL; 02385 if (sub->owner) { 02386 ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL); 02387 ast_channel_unlock(sub->owner); 02388 } 02389 } else { 02390 sub->gate = NULL; 02391 } 02392 ast_mutex_unlock(&sub->lock); 02393 return 1; 02394 }
static int mgcp_postrequest | ( | struct mgcp_endpoint * | p, | |
struct mgcp_subchannel * | sub, | |||
char * | data, | |||
int | len, | |||
unsigned int | seqno | |||
) | [static] |
Definition at line 709 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, 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().
00711 { 00712 struct mgcp_message *msg; 00713 struct mgcp_message *cur; 00714 struct mgcp_gateway *gw; 00715 struct timeval now; 00716 00717 if (!(msg = ast_malloc(sizeof(*msg) + len))) { 00718 return -1; 00719 } 00720 if (!(gw = ((p && p->parent) ? p->parent : NULL))) { 00721 ast_free(msg); 00722 return -1; 00723 } 00724 00725 msg->owner_sub = sub; 00726 msg->owner_ep = p; 00727 msg->seqno = seqno; 00728 msg->next = NULL; 00729 msg->len = len; 00730 msg->retrans = 0; 00731 memcpy(msg->buf, data, msg->len); 00732 00733 ast_mutex_lock(&gw->msgs_lock); 00734 for (cur = gw->msgs; cur && cur->next; cur = cur->next); 00735 if (cur) { 00736 cur->next = msg; 00737 } else { 00738 gw->msgs = msg; 00739 } 00740 00741 now = ast_tvnow(); 00742 msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS; 00743 00744 if (gw->retransid == -1) 00745 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw); 00746 ast_mutex_unlock(&gw->msgs_lock); 00747 __mgcp_xmit(gw, msg->buf, msg->len); 00748 /* XXX Should schedule retransmission XXX */ 00749 return 0; 00750 }
static int mgcp_prune_realtime_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 3702 of file chan_mgcp.c.
References ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_strlen_zero(), mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, mgcp_gateway::endpoints, mgcp_subchannel::gate, mgcp_gateway::ha, mgcp_subchannel::lock, mgcp_endpoint::lock, MAX_SUBS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::realtime, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, and mgcp_endpoint::sub.
Referenced by do_monitor().
03703 { 03704 struct mgcp_endpoint *enext, *e; 03705 struct mgcp_subchannel *s, *sub; 03706 int i, prune = 1; 03707 03708 if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) { 03709 ast_mutex_unlock(&g->msgs_lock); 03710 return 0; 03711 } 03712 03713 for (e = g->endpoints; e; e = e->next) { 03714 ast_mutex_lock(&e->lock); 03715 if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) { 03716 prune = 0; 03717 } else if (e->rqnt_queue || e->cmd_queue) { 03718 prune = 0; 03719 } 03720 s = e->sub; 03721 for (i = 0; (i < MAX_SUBS) && s; i++) { 03722 ast_mutex_lock(&s->lock); 03723 if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) { 03724 prune = 0; 03725 } else if (s->cx_queue) { 03726 prune = 0; 03727 } 03728 s = s->next; 03729 } 03730 } 03731 03732 for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) { 03733 for (i = 0; (i < MAX_SUBS) && sub; i++) { 03734 s = sub; 03735 sub = sub->next; 03736 ast_mutex_unlock(&s->lock); 03737 ast_mutex_unlock(&s->cx_queue_lock); 03738 if (prune) { 03739 ast_mutex_destroy(&s->lock); 03740 ast_mutex_destroy(&s->cx_queue_lock); 03741 free(s); 03742 } 03743 } 03744 ast_mutex_unlock(&e->lock); 03745 ast_mutex_unlock(&e->rqnt_queue_lock); 03746 ast_mutex_unlock(&e->cmd_queue_lock); 03747 if (prune) { 03748 ast_mutex_destroy(&e->lock); 03749 ast_mutex_destroy(&e->rqnt_queue_lock); 03750 ast_mutex_destroy(&e->cmd_queue_lock); 03751 free(e); 03752 } 03753 } 03754 if (prune) { 03755 ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name); 03756 } 03757 return prune; 03758 }
static void mgcp_queue_control | ( | struct mgcp_subchannel * | sub, | |
int | control | |||
) | [static] |
Definition at line 648 of file chan_mgcp.c.
References AST_FRAME_CONTROL, f, and mgcp_queue_frame().
Referenced by handle_hd_hf().
00649 { 00650 struct ast_frame f = { AST_FRAME_CONTROL, { control } }; 00651 return mgcp_queue_frame(sub, &f); 00652 }
static void mgcp_queue_frame | ( | struct mgcp_subchannel * | sub, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 614 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().
00615 { 00616 for (;;) { 00617 if (sub->owner) { 00618 if (!ast_channel_trylock(sub->owner)) { 00619 ast_queue_frame(sub->owner, f); 00620 ast_channel_unlock(sub->owner); 00621 break; 00622 } else { 00623 DEADLOCK_AVOIDANCE(&sub->lock); 00624 } 00625 } else { 00626 break; 00627 } 00628 } 00629 }
static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 631 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(), handle_response(), and start_rtp().
00632 { 00633 for (;;) { 00634 if (sub->owner) { 00635 if (!ast_channel_trylock(sub->owner)) { 00636 ast_queue_hangup(sub->owner); 00637 ast_channel_unlock(sub->owner); 00638 break; 00639 } else { 00640 DEADLOCK_AVOIDANCE(&sub->lock); 00641 } 00642 } else { 00643 break; 00644 } 00645 } 00646 }
static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1232 of file chan_mgcp.c.
References ast_mutex_lock, ast_mutex_unlock, f, mgcp_subchannel::lock, mgcp_rtp_read(), and ast_channel::tech_pvt.
01233 { 01234 struct ast_frame *f; 01235 struct mgcp_subchannel *sub = ast->tech_pvt; 01236 ast_mutex_lock(&sub->lock); 01237 f = mgcp_rtp_read(sub); 01238 ast_mutex_unlock(&sub->lock); 01239 return f; 01240 }
static char * mgcp_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4813 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().
04814 { 04815 static int deprecated = 0; 04816 04817 if (e) { 04818 switch (cmd) { 04819 case CLI_INIT: 04820 e->command = "mgcp reload"; 04821 e->usage = 04822 "Usage: mgcp reload\n" 04823 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; 04824 return NULL; 04825 case CLI_GENERATE: 04826 return NULL; 04827 } 04828 } 04829 04830 if (!deprecated && a && a->argc > 0) { 04831 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); 04832 deprecated = 1; 04833 } 04834 04835 ast_mutex_lock(&mgcp_reload_lock); 04836 if (mgcp_reloading) { 04837 ast_verbose("Previous mgcp reload not yet done\n"); 04838 } else { 04839 mgcp_reloading = 1; 04840 } 04841 ast_mutex_unlock(&mgcp_reload_lock); 04842 restart_monitor(); 04843 return CLI_SUCCESS; 04844 }
static struct ast_channel * mgcp_request | ( | const char * | type, | |
format_t | format, | |||
const struct ast_channel * | requestor, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 3907 of file chan_mgcp.c.
References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_getformatname_multiple(), 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, ast_channel::linkedid, 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().
03908 { 03909 struct mgcp_subchannel *sub; 03910 struct ast_channel *tmpc = NULL; 03911 char tmp[256]; 03912 char *dest = data; 03913 03914 format &= capability; 03915 if (!format) { 03916 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format)); 03917 /*return NULL;*/ 03918 } 03919 ast_copy_string(tmp, dest, sizeof(tmp)); 03920 if (ast_strlen_zero(tmp)) { 03921 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); 03922 return NULL; 03923 } 03924 if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) { 03925 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); 03926 *cause = AST_CAUSE_UNREGISTERED; 03927 return NULL; 03928 } 03929 03930 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); 03931 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 03932 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); 03933 /* Must be busy */ 03934 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || 03935 ((!sub->parent->callwaiting) && (sub->owner)) || 03936 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { 03937 if (sub->parent->hookstate == MGCP_ONHOOK) { 03938 if (has_voicemail(sub->parent)) { 03939 transmit_notify_request(sub,"L/vmwi(+)"); 03940 } else { 03941 transmit_notify_request(sub,"L/vmwi(-)"); 03942 } 03943 } 03944 *cause = AST_CAUSE_BUSY; 03945 ast_mutex_unlock(&sub->lock); 03946 return NULL; 03947 } 03948 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL); 03949 ast_mutex_unlock(&sub->lock); 03950 if (!tmpc) 03951 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); 03952 restart_monitor(); 03953 return tmpc; 03954 }
static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 1201 of file chan_mgcp.c.
References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_instance_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().
01202 { 01203 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ 01204 struct ast_frame *f; 01205 01206 f = ast_rtp_instance_read(sub->rtp, 0); 01207 /* Don't send RFC2833 if we're not supposed to */ 01208 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) 01209 return &ast_null_frame; 01210 if (sub->owner) { 01211 /* We already hold the channel lock */ 01212 if (f->frametype == AST_FRAME_VOICE) { 01213 if (f->subclass.codec != sub->owner->nativeformats) { 01214 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec)); 01215 sub->owner->nativeformats = f->subclass.codec; 01216 ast_set_read_format(sub->owner, sub->owner->readformat); 01217 ast_set_write_format(sub->owner, sub->owner->writeformat); 01218 } 01219 /* Courtesy fearnor aka alex@pilosoft.com */ 01220 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { 01221 #if 0 01222 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); 01223 #endif 01224 f = ast_dsp_process(sub->owner, sub->parent->dsp, f); 01225 } 01226 } 01227 } 01228 return f; 01229 }
static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1299 of file chan_mgcp.c.
References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, 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.
01300 { 01301 struct mgcp_subchannel *sub = ast->tech_pvt; 01302 struct mgcp_endpoint *p = sub->parent; 01303 int res = 0; 01304 01305 ast_mutex_lock(&sub->lock); 01306 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01307 ast_debug(1, "Sending DTMF using inband/hybrid\n"); 01308 res = -1; /* Let asterisk play inband indications */ 01309 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01310 ast_debug(1, "Sending DTMF using RFC2833\n"); 01311 ast_rtp_instance_dtmf_begin(sub->rtp, digit); 01312 } else { 01313 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01314 } 01315 ast_mutex_unlock(&sub->lock); 01316 01317 return res; 01318 }
static int mgcp_senddigit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1320 of file chan_mgcp.c.
References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_end(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_endpoint::ncs, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, ast_channel::tech_pvt, and transmit_notify_request().
01321 { 01322 struct mgcp_subchannel *sub = ast->tech_pvt; 01323 struct mgcp_endpoint *p = sub->parent; 01324 int res = 0; 01325 char tmp[4]; 01326 01327 ast_mutex_lock(&sub->lock); 01328 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01329 ast_debug(1, "Stopping DTMF using inband/hybrid\n"); 01330 res = -1; /* Tell Asterisk to stop inband indications */ 01331 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01332 ast_debug(1, "Stopping DTMF using RFC2833\n"); 01333 if (sub->parent->ncs) { 01334 tmp[0] = digit; 01335 tmp[1] = '\0'; 01336 } else { 01337 tmp[0] = 'D'; 01338 tmp[1] = '/'; 01339 tmp[2] = digit; 01340 tmp[3] = '\0'; 01341 } 01342 transmit_notify_request(sub, tmp); 01343 ast_rtp_instance_dtmf_end(sub->rtp, digit); 01344 } else { 01345 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01346 } 01347 ast_mutex_unlock(&sub->lock); 01348 01349 return res; 01350 }
static int mgcp_set_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp_instance * | rtp, | |||
struct ast_rtp_instance * | vrtp, | |||
struct ast_rtp_instance * | trtp, | |||
format_t | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 4416 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_modify_with_sdp().
04417 { 04418 /* XXX Is there such thing as video support with MGCP? XXX */ 04419 struct mgcp_subchannel *sub; 04420 sub = chan->tech_pvt; 04421 if (sub && !sub->alreadygone) { 04422 transmit_modify_with_sdp(sub, rtp, codecs); 04423 return 0; 04424 } 04425 return -1; 04426 }
static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2947 of file chan_mgcp.c.
References ast_party_caller::ani, 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_exten(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext_valid(), 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_strdup, ast_strlen_zero(), ast_verb, ast_waitfordigit(), mgcp_endpoint::call_forward, ast_channel::caller, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, ast_channel::dialed, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_party_caller::id, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_id::number, ast_party_dialed::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, ast_channel::rings, S_COR, start_rtp(), ast_party_number::str, ast_party_dialed::str, mgcp_endpoint::sub, ast_channel::tech_pvt, transmit_notify_request(), and ast_party_number::valid.
Referenced by handle_hd_hf().
02948 { 02949 struct ast_channel *chan = data; 02950 struct mgcp_subchannel *sub = chan->tech_pvt; 02951 struct mgcp_endpoint *p = sub->parent; 02952 /* char exten[AST_MAX_EXTENSION] = ""; */ 02953 int len = 0; 02954 int timeout = firstdigittimeout; 02955 int res= 0; 02956 int getforward = 0; 02957 int loop_pause = 100; 02958 02959 len = strlen(p->dtmf_buf); 02960 02961 while (len < AST_MAX_EXTENSION - 1) { 02962 ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name); 02963 res = 1; /* Assume that we will get a digit */ 02964 while (strlen(p->dtmf_buf) == len) { 02965 ast_safe_sleep(chan, loop_pause); 02966 timeout -= loop_pause; 02967 if (timeout <= 0){ 02968 res = 0; 02969 break; 02970 } 02971 res = 1; 02972 } 02973 02974 timeout = 0; 02975 len = strlen(p->dtmf_buf); 02976 02977 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) { 02978 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02979 ast_indicate(chan, -1); 02980 } else { 02981 /* XXX Redundant? We should already be playing dialtone */ 02982 /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02983 transmit_notify_request(sub, "L/dl"); 02984 } 02985 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02986 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 02987 if (getforward) { 02988 /* Record this as the forwarding extension */ 02989 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 02990 ast_verb(3, "Setting call forward to '%s' on channel %s\n", 02991 p->call_forward, chan->name); 02992 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 02993 transmit_notify_request(sub, "L/sl"); 02994 if (res) 02995 break; 02996 usleep(500000); 02997 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02998 ast_indicate(chan, -1); 02999 sleep(1); 03000 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03001 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 03002 transmit_notify_request(sub, "L/dl"); 03003 len = 0; 03004 getforward = 0; 03005 } else { 03006 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03007 ast_indicate(chan, -1); 03008 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten)); 03009 chan->dialed.number.str = ast_strdup(p->dtmf_buf); 03010 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03011 ast_set_callerid(chan, 03012 p->hidecallerid ? "" : p->cid_num, 03013 p->hidecallerid ? "" : p->cid_name, 03014 chan->caller.ani.number.valid ? NULL : p->cid_num); 03015 ast_setstate(chan, AST_STATE_RING); 03016 /*dahdi_enable_ec(p);*/ 03017 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 03018 p->dtmfmode |= MGCP_DTMF_INBAND; 03019 ast_indicate(chan, -1); 03020 } 03021 res = ast_pbx_run(chan); 03022 if (res) { 03023 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 03024 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03025 /*transmit_notify_request(p, "nbz", 1);*/ 03026 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03027 } 03028 return NULL; 03029 } 03030 } else { 03031 /* It's a match, but they just typed a digit, and there is an ambiguous match, 03032 so just set the timeout to matchdigittimeout and wait some more */ 03033 timeout = matchdigittimeout; 03034 } 03035 } else if (res == 0) { 03036 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 03037 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03038 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03039 /*dahdi_wait_event(p->subs[index].zfd);*/ 03040 ast_hangup(chan); 03041 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03042 return NULL; 03043 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { 03044 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 03045 /* Disable call waiting if enabled */ 03046 p->callwaiting = 0; 03047 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03048 transmit_notify_request(sub, "L/sl"); 03049 len = 0; 03050 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03051 timeout = firstdigittimeout; 03052 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { 03053 /* Scan all channels and see if any there 03054 * ringing channqels with that have call groups 03055 * that equal this channels pickup group 03056 */ 03057 if (ast_pickup_call(chan)) { 03058 ast_log(LOG_WARNING, "No call pickup possible...\n"); 03059 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03060 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03061 } 03062 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03063 ast_hangup(chan); 03064 return NULL; 03065 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { 03066 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 03067 /* Disable Caller*ID if enabled */ 03068 p->hidecallerid = 1; 03069 ast_set_callerid(chan, "", "", NULL); 03070 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03071 transmit_notify_request(sub, "L/sl"); 03072 len = 0; 03073 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03074 timeout = firstdigittimeout; 03075 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { 03076 res = 0; 03077 if (!ast_strlen_zero(p->lastcallerid)) { 03078 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language); 03079 } 03080 if (!res) 03081 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03082 transmit_notify_request(sub, "L/sl"); 03083 break; 03084 } else if (!strcmp(p->dtmf_buf, "*78")) { 03085 /* Do not disturb */ 03086 ast_verb(3, "Enabled DND on channel %s\n", chan->name); 03087 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03088 transmit_notify_request(sub, "L/sl"); 03089 p->dnd = 1; 03090 getforward = 0; 03091 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03092 len = 0; 03093 } else if (!strcmp(p->dtmf_buf, "*79")) { 03094 /* Do not disturb */ 03095 ast_verb(3, "Disabled DND on channel %s\n", chan->name); 03096 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03097 transmit_notify_request(sub, "L/sl"); 03098 p->dnd = 0; 03099 getforward = 0; 03100 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03101 len = 0; 03102 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { 03103 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03104 transmit_notify_request(sub, "L/sl"); 03105 getforward = 1; 03106 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03107 len = 0; 03108 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { 03109 ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name); 03110 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03111 transmit_notify_request(sub, "L/sl"); 03112 memset(p->call_forward, 0, sizeof(p->call_forward)); 03113 getforward = 0; 03114 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03115 len = 0; 03116 } else if (ast_parking_ext_valid(p->dtmf_buf, chan, chan->context) && 03117 sub->next->owner && ast_bridged_channel(sub->next->owner)) { 03118 /* This is a three way call, the main call being a real channel, 03119 and we're parking the first call. */ 03120 ast_masq_park_call_exten(ast_bridged_channel(sub->next->owner), chan, 03121 p->dtmf_buf, chan->context, 0, NULL); 03122 ast_verb(3, "Parking call to '%s'\n", chan->name); 03123 break; 03124 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { 03125 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); 03126 res = ast_db_put("blacklist", p->lastcallerid, "1"); 03127 if (!res) { 03128 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03129 transmit_notify_request(sub, "L/sl"); 03130 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03131 len = 0; 03132 } 03133 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { 03134 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 03135 /* Enable Caller*ID if enabled */ 03136 p->hidecallerid = 0; 03137 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 03138 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03139 transmit_notify_request(sub, "L/sl"); 03140 len = 0; 03141 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03142 timeout = firstdigittimeout; 03143 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, 03144 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 03145 && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 03146 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, 03147 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 03148 chan->context); 03149 break; 03150 } 03151 if (!timeout) 03152 timeout = gendigittimeout; 03153 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf)) 03154 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03155 ast_indicate(chan, -1); 03156 } 03157 #if 0 03158 for (;;) { 03159 res = ast_waitfordigit(chan, to); 03160 if (!res) { 03161 ast_debug(1, "Timeout...\n"); 03162 break; 03163 } 03164 if (res < 0) { 03165 ast_debug(1, "Got hangup...\n"); 03166 ast_hangup(chan); 03167 break; 03168 } 03169 exten[pos++] = res; 03170 if (!ast_ignore_pattern(chan->context, exten)) 03171 ast_indicate(chan, -1); 03172 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { 03173 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 03174 to = 3000; 03175 else 03176 to = 8000; 03177 } else 03178 break; 03179 } 03180 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { 03181 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); 03182 if (!p->rtp) { 03183 start_rtp(p); 03184 } 03185 ast_setstate(chan, AST_STATE_RING); 03186 chan->rings = 1; 03187 if (ast_pbx_run(chan)) { 03188 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); 03189 } else { 03190 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03191 return NULL; 03192 } 03193 } 03194 #endif 03195 ast_hangup(chan); 03196 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03197 return NULL; 03198 }
static int mgcp_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 1242 of file chan_mgcp.c.
References ast_debug, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::codec, ast_frame::frametype, mgcp_subchannel::gate, GATE_ALLOCATED, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, cops_gate::state, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, transmit_modify_with_sdp(), and ast_channel::writeformat.
01243 { 01244 struct mgcp_subchannel *sub = ast->tech_pvt; 01245 int res = 0; 01246 char buf[256]; 01247 01248 if (frame->frametype != AST_FRAME_VOICE) { 01249 if (frame->frametype == AST_FRAME_IMAGE) 01250 return 0; 01251 else { 01252 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); 01253 return 0; 01254 } 01255 } else { 01256 if (!(frame->subclass.codec & ast->nativeformats)) { 01257 ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01258 ast_getformatname(frame->subclass.codec), 01259 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), 01260 ast_getformatname(ast->readformat), 01261 ast_getformatname(ast->writeformat)); 01262 /* return -1; */ 01263 } 01264 } 01265 if (sub) { 01266 ast_mutex_lock(&sub->lock); 01267 if (!sub->sdpsent && sub->gate) { 01268 if (sub->gate->state == GATE_ALLOCATED) { 01269 ast_debug(1, "GATE ALLOCATED, sending sdp\n"); 01270 transmit_modify_with_sdp(sub, NULL, 0); 01271 } 01272 } 01273 if ((sub->parent->sub == sub) || !sub->parent->singlepath) { 01274 if (sub->rtp) { 01275 res = ast_rtp_instance_write(sub->rtp, frame); 01276 } 01277 } 01278 ast_mutex_unlock(&sub->lock); 01279 } 01280 return res; 01281 }
static int mgcpsock_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | ignore | |||
) | [static] |
Definition at line 3611 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(), 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().
03612 { 03613 struct mgcp_request req; 03614 struct sockaddr_in sin; 03615 struct mgcp_subchannel *sub; 03616 int res; 03617 socklen_t len; 03618 int result; 03619 int ident; 03620 len = sizeof(sin); 03621 memset(&req, 0, sizeof(req)); 03622 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 03623 if (res < 0) { 03624 if (errno != ECONNREFUSED) 03625 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 03626 return 1; 03627 } 03628 req.data[res] = '\0'; 03629 req.len = res; 03630 ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 03631 parse(&req); 03632 if (req.headers < 1) { 03633 /* Must have at least one header */ 03634 return 1; 03635 } 03636 if (ast_strlen_zero(req.identifier)) { 03637 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); 03638 return 1; 03639 } 03640 03641 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { 03642 if (result < 200) { 03643 ast_debug(1, "Ignoring provisional response on transaction %d\n", ident); 03644 return 1; 03645 } 03646 /* Try to find who this message is for, if it's important */ 03647 sub = find_subchannel_and_lock(NULL, ident, &sin); 03648 if (sub) { 03649 struct mgcp_gateway *gw = sub->parent->parent; 03650 struct mgcp_message *cur, *prev; 03651 03652 ast_mutex_unlock(&sub->lock); 03653 ast_mutex_lock(&gw->msgs_lock); 03654 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 03655 if (cur->seqno == ident) { 03656 ast_debug(1, "Got response back on transaction %d\n", ident); 03657 if (prev) 03658 prev->next = cur->next; 03659 else 03660 gw->msgs = cur->next; 03661 break; 03662 } 03663 } 03664 03665 /* stop retrans timer if the queue is empty */ 03666 if (!gw->msgs) { 03667 AST_SCHED_DEL(sched, gw->retransid); 03668 } 03669 03670 ast_mutex_unlock(&gw->msgs_lock); 03671 if (cur) { 03672 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); 03673 ast_free(cur); 03674 return 1; 03675 } 03676 03677 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 03678 gw->name, ident); 03679 } 03680 } else { 03681 if (ast_strlen_zero(req.endpoint) || 03682 ast_strlen_zero(req.version) || 03683 ast_strlen_zero(req.verb)) { 03684 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); 03685 return 1; 03686 } 03687 /* Process request, with iflock held */ 03688 sub = find_subchannel_and_lock(req.endpoint, 0, &sin); 03689 if (sub) { 03690 /* look first to find a matching response in the queue */ 03691 if (!find_and_retrans(sub, &req)) 03692 /* pass the request off to the currently mastering subchannel */ 03693 handle_request(sub, &req, &sin); 03694 ast_mutex_unlock(&sub->lock); 03695 } 03696 } 03697 return 1; 03698 }
static void mwi_event_cb | ( | const struct ast_event * | event, | |
void * | userdata | |||
) | [static] |
Definition at line 483 of file chan_mgcp.c.
00484 { 00485 /* This module does not handle MWI in an event-based manner. However, it 00486 * subscribes to MWI for each mailbox that is configured so that the core 00487 * knows that we care about it. Then, chan_mgcp will get the MWI from the 00488 * event cache instead of checking the mailbox directly. */ 00489 }
static void parse | ( | struct mgcp_request * | req | ) | [static] |
Definition at line 1857 of file chan_mgcp.c.
References ast_debug, ast_log(), ast_strlen_zero(), 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, mgcp_request::verb, and mgcp_request::version.
Referenced by acf_jabberreceive_read(), acf_meetme_info(), add_agent(), app_exec(), aqm_exec(), ast_masq_park_call_exten(), ast_park_call_exten(), ast_parse_allow_disallow(), celgenuserevent_exec(), chanspy_exec(), conf_exec(), conf_run(), confbridge_exec(), config_function_read(), cut_internal(), dahdi_accept_r2_call_exec(), dahdi_send_callrerouting_facility_exec(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), extenspy_exec(), find_conf(), function_agent(), get_comma(), get_in_brackets_full(), gosub_exec(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), man_do_variable_value(), mgcpsock_read(), mixmonitor_exec(), originate_exec(), oss_call(), oss_request(), page_exec(), park_call_exec(), parked_call_exec(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_waitexten(), pickupchan_exec(), play_moh_exec(), pqm_exec(), privacy_exec(), process_echocancel(), ql_exec(), queue_exec(), rcvfax_exec(), receivefax_exec(), record_exec(), reload_single_member(), retrydial_exec(), rqm_exec(), saycountedadj_exec(), saycountednoun_exec(), sayunixtime_exec(), sendfax_exec(), sip_acf_channel_read(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sms_exec(), sndfax_exec(), softhangup_exec(), speech_background(), srv_result_read(), start_moh_exec(), start_monitor_exec(), transfer_exec(), upqm_exec(), userevent_exec(), verbose_exec(), vm_execmain(), xfer_park_call_helper(), and zapateller_exec().
01858 { 01859 /* Divide fields by NULL's */ 01860 char *c; 01861 int f = 0; 01862 c = req->data; 01863 01864 /* First header starts immediately */ 01865 req->header[f] = c; 01866 for (; *c; c++) { 01867 if (*c == '\n') { 01868 /* We've got a new header */ 01869 *c = 0; 01870 ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f])); 01871 if (ast_strlen_zero(req->header[f])) { 01872 /* Line by itself means we're now in content */ 01873 c++; 01874 break; 01875 } 01876 if (f >= MGCP_MAX_HEADERS - 1) { 01877 ast_log(LOG_WARNING, "Too many MGCP headers...\n"); 01878 } else { 01879 f++; 01880 } 01881 req->header[f] = c + 1; 01882 } else if (*c == '\r') { 01883 /* Ignore but eliminate \r's */ 01884 *c = 0; 01885 } 01886 } 01887 /* Check for last header */ 01888 if (!ast_strlen_zero(req->header[f])) { 01889 f++; 01890 } 01891 req->headers = f; 01892 /* Now we process any mime content */ 01893 f = 0; 01894 req->line[f] = c; 01895 for (; *c; c++) { 01896 if (*c == '\n') { 01897 /* We've got a new line */ 01898 *c = 0; 01899 ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f])); 01900 if (f >= MGCP_MAX_LINES - 1) { 01901 ast_log(LOG_WARNING, "Too many SDP lines...\n"); 01902 } else { 01903 f++; 01904 } 01905 req->line[f] = c + 1; 01906 } else if (*c == '\r') { 01907 /* Ignore and eliminate \r's */ 01908 *c = 0; 01909 } 01910 } 01911 /* Check for last line */ 01912 if (!ast_strlen_zero(req->line[f])) { 01913 f++; 01914 } 01915 req->lines = f; 01916 /* Parse up the initial header */ 01917 c = req->header[0]; 01918 while (*c && *c < 33) c++; 01919 /* First the verb */ 01920 req->verb = c; 01921 while (*c && (*c > 32)) c++; 01922 if (*c) { 01923 *c = '\0'; 01924 c++; 01925 while (*c && (*c < 33)) c++; 01926 req->identifier = c; 01927 while (*c && (*c > 32)) c++; 01928 if (*c) { 01929 *c = '\0'; 01930 c++; 01931 while (*c && (*c < 33)) c++; 01932 req->endpoint = c; 01933 while (*c && (*c > 32)) c++; 01934 if (*c) { 01935 *c = '\0'; 01936 c++; 01937 while (*c && (*c < 33)) c++; 01938 req->version = c; 01939 while (*c && (*c > 32)) c++; 01940 while (*c && (*c < 33)) c++; 01941 while (*c && (*c > 32)) c++; 01942 *c = '\0'; 01943 } 01944 } 01945 } 01946 01947 ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", 01948 req->verb, req->identifier, req->endpoint, req->version); 01949 ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines); 01950 if (*c) { 01951 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); 01952 } 01953 }
static int process_sdp | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req | |||
) | [static] |
Definition at line 1955 of file chan_mgcp.c.
References ahp, ast_debug, ast_getformatname_multiple(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_formats(), ast_rtp_codecs_payloads_clear(), ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_sockaddr_from_sin, ast_strdupa, ast_strlen_zero(), capability, mgcp_endpoint::capability, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, 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().
01956 { 01957 char *m; 01958 char *c; 01959 char *a; 01960 char host[258]; 01961 int len; 01962 int portno; 01963 format_t peercapability; 01964 int peerNonCodecCapability; 01965 struct sockaddr_in sin; 01966 struct ast_sockaddr sin_tmp; 01967 char *codecs; 01968 struct ast_hostent ahp; struct hostent *hp; 01969 int codec, codec_count=0; 01970 int iterator; 01971 struct mgcp_endpoint *p = sub->parent; 01972 char tmp1[256], tmp2[256], tmp3[256]; 01973 01974 /* Get codec and RTP info from SDP */ 01975 m = get_sdp(req, "m"); 01976 c = get_sdp(req, "c"); 01977 if (ast_strlen_zero(m) || ast_strlen_zero(c)) { 01978 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); 01979 return -1; 01980 } 01981 if (sscanf(c, "IN IP4 %256s", host) != 1) { 01982 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 01983 return -1; 01984 } 01985 /* XXX This could block for a long time, and block the main thread! XXX */ 01986 hp = ast_gethostbyname(host, &ahp); 01987 if (!hp) { 01988 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); 01989 return -1; 01990 } 01991 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) { 01992 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 01993 return -1; 01994 } 01995 sin.sin_family = AF_INET; 01996 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 01997 sin.sin_port = htons(portno); 01998 ast_sockaddr_from_sin(&sin_tmp, &sin); 01999 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp); 02000 ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 02001 /* Scan through the RTP payload types specified in a "m=" line: */ 02002 ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp); 02003 codecs = ast_strdupa(m + len); 02004 while (!ast_strlen_zero(codecs)) { 02005 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) { 02006 if (codec_count) { 02007 break; 02008 } 02009 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs); 02010 return -1; 02011 } 02012 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec); 02013 codec_count++; 02014 codecs += len; 02015 } 02016 02017 /* Next, scan through each "a=rtpmap:" line, noting each */ 02018 /* specified RTP payload type (with corresponding MIME subtype): */ 02019 sdpLineNum_iterator_init(&iterator); 02020 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 02021 char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */ 02022 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2) 02023 continue; 02024 /* Note: should really look at the 'freq' and '#chans' params too */ 02025 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0); 02026 } 02027 02028 /* Now gather all of the codecs that were asked for: */ 02029 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), &peercapability, &peerNonCodecCapability); 02030 p->capability = capability & peercapability; 02031 ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n", 02032 ast_getformatname_multiple(tmp1, sizeof(tmp1), capability), 02033 ast_getformatname_multiple(tmp2, sizeof(tmp2), peercapability), 02034 ast_getformatname_multiple(tmp3, sizeof(tmp3), p->capability)); 02035 ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n", 02036 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); 02037 if (!p->capability) { 02038 ast_log(LOG_WARNING, "No compatible codecs!\n"); 02039 return -1; 02040 } 02041 return 0; 02042 }
static void prune_gateways | ( | void | ) | [static] |
Definition at line 4530 of file chan_mgcp.c.
References ast_mutex_lock, mgcp_gateway::delme, mgcp_endpoint::delme, destroy_endpoint(), mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::next, and mgcp_gateway::realtime.
Referenced by unload_module().
04531 { 04532 struct mgcp_gateway *g, *z, *r; 04533 struct mgcp_endpoint *e, *p, *t; 04534 04535 ast_mutex_lock(&gatelock); 04536 04537 /* prune gateways */ 04538 for (z = NULL, g = gateways; g;) { 04539 /* prune endpoints */ 04540 for (p = NULL, e = g->endpoints; e; ) { 04541 if (!g->realtime && (e->delme || g->delme)) { 04542 t = e; 04543 e = e->next; 04544 if (!p) 04545 g->endpoints = e; 04546 else 04547 p->next = e; 04548 destroy_endpoint(t); 04549 } else { 04550 p = e; 04551 e = e->next; 04552 } 04553 } 04554 04555 if (g->delme) { 04556 r = g; 04557 g = g->next; 04558 if (!z) 04559 gateways = g; 04560 else 04561 z->next = g; 04562 04563 destroy_gateway(r); 04564 } else { 04565 z = g; 04566 g = g->next; 04567 } 04568 } 04569 04570 ast_mutex_unlock(&gatelock); 04571 }
static int reload | ( | void | ) | [static] |
Definition at line 4846 of file chan_mgcp.c.
References mgcp_reload().
04847 { 04848 mgcp_reload(NULL, 0, NULL); 04849 return 0; 04850 }
static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4605 of file chan_mgcp.c.
References ahp, ast_config_load, ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_variable_browse(), bindaddr, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, default_jbconf, dtmfmode, format, global_jbconf, hp, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, ourhost, and ast_variable::value.
04606 { 04607 struct ast_config *cfg; 04608 struct ast_variable *v; 04609 struct mgcp_gateway *g; 04610 struct mgcp_endpoint *e; 04611 char *cat; 04612 struct ast_hostent ahp; 04613 struct hostent *hp; 04614 int format; 04615 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04616 04617 if (gethostname(ourhost, sizeof(ourhost)-1)) { 04618 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); 04619 return 0; 04620 } 04621 cfg = ast_config_load(config, config_flags); 04622 04623 /* We *must* have a config file otherwise stop immediately */ 04624 if (!cfg) { 04625 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); 04626 return 0; 04627 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 04628 return 0; 04629 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04630 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 04631 return 0; 04632 } 04633 04634 memset(&bindaddr, 0, sizeof(bindaddr)); 04635 dtmfmode = 0; 04636 04637 /* Copy the default jb config over global_jbconf */ 04638 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 04639 04640 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 04641 /* handle jb conf */ 04642 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { 04643 continue; 04644 } 04645 04646 /* Create the interface list */ 04647 if (!strcasecmp(v->name, "bindaddr")) { 04648 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 04649 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 04650 } else { 04651 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 04652 } 04653 } else if (!strcasecmp(v->name, "allow")) { 04654 format = ast_getformatbyname(v->value); 04655 if (format < 1) { 04656 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04657 } else { 04658 capability |= format; 04659 } 04660 } else if (!strcasecmp(v->name, "disallow")) { 04661 format = ast_getformatbyname(v->value); 04662 if (format < 1) { 04663 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value); 04664 } else { 04665 capability &= ~format; 04666 } 04667 } else if (!strcasecmp(v->name, "tos")) { 04668 if (ast_str2tos(v->value, &qos.tos)) { 04669 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04670 } 04671 } else if (!strcasecmp(v->name, "tos_audio")) { 04672 if (ast_str2tos(v->value, &qos.tos_audio)) 04673 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04674 } else if (!strcasecmp(v->name, "cos")) { 04675 if (ast_str2cos(v->value, &qos.cos)) 04676 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 04677 } else if (!strcasecmp(v->name, "cos_audio")) { 04678 if (ast_str2cos(v->value, &qos.cos_audio)) 04679 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04680 } else if (!strcasecmp(v->name, "port")) { 04681 if (sscanf(v->value, "%5d", &ourport) == 1) { 04682 bindaddr.sin_port = htons(ourport); 04683 } else { 04684 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 04685 } 04686 } else if (!strcasecmp(v->name, "firstdigittimeout")) { 04687 firstdigittimeout = atoi(v->value); 04688 } else if (!strcasecmp(v->name, "gendigittimeout")) { 04689 gendigittimeout = atoi(v->value); 04690 } else if (!strcasecmp(v->name, "matchdigittimeout")) { 04691 matchdigittimeout = atoi(v->value); 04692 } 04693 } 04694 04695 /* mark existing entries for deletion */ 04696 ast_mutex_lock(&gatelock); 04697 for (g = gateways; g; g = g->next) { 04698 g->delme = 1; 04699 for (e = g->endpoints; e; e = e->next) { 04700 e->delme = 1; 04701 } 04702 } 04703 ast_mutex_unlock(&gatelock); 04704 04705 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) { 04706 if (strcasecmp(cat, "general")) { 04707 ast_mutex_lock(&gatelock); 04708 if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) { 04709 ast_verb(3, "Added gateway '%s'\n", g->name); 04710 g->next = gateways; 04711 gateways = g; 04712 } 04713 ast_mutex_unlock(&gatelock); 04714 04715 /* FS: process queue and IO */ 04716 if (monitor_thread == pthread_self()) { 04717 if (sched) ast_sched_runq(sched); 04718 if (io) ast_io_wait(io, 10); 04719 } 04720 } 04721 } 04722 04723 /* prune deleted entries etc. */ 04724 prune_gateways(); 04725 04726 if (ntohl(bindaddr.sin_addr.s_addr)) { 04727 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); 04728 } else { 04729 hp = ast_gethostbyname(ourhost, &ahp); 04730 if (!hp) { 04731 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); 04732 ast_config_destroy(cfg); 04733 return 0; 04734 } 04735 memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); 04736 } 04737 if (!ntohs(bindaddr.sin_port)) 04738 bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT); 04739 bindaddr.sin_family = AF_INET; 04740 ast_mutex_lock(&netlock); 04741 if (mgcpsock > -1) 04742 close(mgcpsock); 04743 04744 if (mgcpsock_read_id != NULL) 04745 ast_io_remove(io, mgcpsock_read_id); 04746 mgcpsock_read_id = NULL; 04747 04748 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); 04749 if (mgcpsock < 0) { 04750 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); 04751 } else { 04752 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 04753 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 04754 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 04755 strerror(errno)); 04756 close(mgcpsock); 04757 mgcpsock = -1; 04758 } else { 04759 ast_verb(2, "MGCP Listening on %s:%d\n", 04760 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 04761 ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); 04762 } 04763 } 04764 ast_mutex_unlock(&netlock); 04765 ast_config_destroy(cfg); 04766 04767 /* send audit only to the new endpoints */ 04768 for (g = gateways; g; g = g->next) { 04769 for (e = g->endpoints; e && e->needaudit; e = e->next) { 04770 e->needaudit = 0; 04771 transmit_audit_endpoint(e); 04772 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); 04773 } 04774 } 04775 04776 return 0; 04777 }
static int reqprep | ( | struct mgcp_request * | req, | |
struct mgcp_endpoint * | p, | |||
char * | verb | |||
) | [static] |
Definition at line 2138 of file chan_mgcp.c.
References init_req(), and oseq.
Referenced by transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_notify_request(), transmit_notify_request_with_callerid(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_state_notify(), and update_connectedline().
02139 { 02140 memset(req, 0, sizeof(struct mgcp_request)); 02141 oseq++; 02142 if (oseq > 999999999) { 02143 oseq = 1; 02144 } 02145 init_req(p, req, verb); 02146 return 0; 02147 }
static int resend_response | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_response * | resp | |||
) | [static] |
Definition at line 557 of file chan_mgcp.c.
References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), mgcp_response::buf, mgcp_response::len, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by find_and_retrans().
00558 { 00559 struct mgcp_endpoint *p = sub->parent; 00560 int res; 00561 ast_debug(1, "Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00562 res = __mgcp_xmit(p->parent, resp->buf, resp->len); 00563 if (res > 0) 00564 res = 0; 00565 return res; 00566 }
static int respprep | ( | struct mgcp_request * | resp, | |
struct mgcp_endpoint * | p, | |||
char * | msg, | |||
struct mgcp_request * | req, | |||
char * | msgrest | |||
) | [static] |
Definition at line 2131 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_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sdp(), transmit_response_with_sip_etag(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), update_connectedline(), and update_redirecting().
02132 { 02133 memset(resp, 0, sizeof(*resp)); 02134 init_resp(resp, msg, req, msgrest); 02135 return 0; 02136 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 3878 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.
03879 { 03880 /* If we're supposed to be stopped -- stay stopped */ 03881 if (monitor_thread == AST_PTHREADT_STOP) 03882 return 0; 03883 if (ast_mutex_lock(&monlock)) { 03884 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 03885 return -1; 03886 } 03887 if (monitor_thread == pthread_self()) { 03888 ast_mutex_unlock(&monlock); 03889 ast_log(LOG_WARNING, "Cannot kill myself\n"); 03890 return -1; 03891 } 03892 if (monitor_thread != AST_PTHREADT_NULL) { 03893 /* Wake up the thread */ 03894 pthread_kill(monitor_thread, SIGURG); 03895 } else { 03896 /* Start a new monitor */ 03897 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 03898 ast_mutex_unlock(&monlock); 03899 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 03900 return -1; 03901 } 03902 } 03903 ast_mutex_unlock(&monlock); 03904 return 0; 03905 }
static int retrans_pkt | ( | const void * | data | ) | [static] |
Definition at line 654 of file chan_mgcp.c.
References __mgcp_xmit(), ast_debug, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_message::buf, handle_response(), mgcp_message::len, LOG_WARNING, MAX_RETRANS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_message::retrans, mgcp_gateway::retransid, and mgcp_message::seqno.
Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and sip_show_sched().
00655 { 00656 struct mgcp_gateway *gw = (struct mgcp_gateway *)data; 00657 struct mgcp_message *cur, *exq = NULL, *w, *prev; 00658 int res = 0; 00659 00660 /* find out expired msgs */ 00661 ast_mutex_lock(&gw->msgs_lock); 00662 00663 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00664 if (cur->retrans < MAX_RETRANS) { 00665 cur->retrans++; 00666 ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n", 00667 cur->retrans, cur->seqno, gw->name); 00668 __mgcp_xmit(gw, cur->buf, cur->len); 00669 } else { 00670 if (prev) 00671 prev->next = cur->next; 00672 else 00673 gw->msgs = cur->next; 00674 00675 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", 00676 cur->seqno, gw->name); 00677 00678 w = cur; 00679 00680 if (exq) { 00681 w->next = exq; 00682 } else { 00683 w->next = NULL; 00684 } 00685 exq = w; 00686 } 00687 } 00688 00689 if (!gw->msgs) { 00690 gw->retransid = -1; 00691 res = 0; 00692 } else { 00693 res = 1; 00694 } 00695 ast_mutex_unlock(&gw->msgs_lock); 00696 00697 while (exq) { 00698 cur = exq; 00699 /* time-out transaction */ 00700 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 00701 exq = exq->next; 00702 ast_free(cur); 00703 } 00704 00705 return res; 00706 }
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 753 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, 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(), mgcp_endpoint::ncs, mgcp_request::next, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, and mgcp_endpoint::slowsequence.
Referenced by transmit_audit_endpoint(), transmit_cc_notify(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), 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_state_notify(), and update_connectedline().
00755 { 00756 int res = 0; 00757 struct mgcp_request **queue, *q, *r, *t; 00758 ast_mutex_t *l; 00759 00760 ast_debug(1, "Slow sequence is %d\n", p->slowsequence); 00761 if (p->slowsequence) { 00762 queue = &p->cmd_queue; 00763 l = &p->cmd_queue_lock; 00764 ast_mutex_lock(l); 00765 } else { 00766 switch (req->cmd) { 00767 case MGCP_CMD_DLCX: 00768 queue = &sub->cx_queue; 00769 l = &sub->cx_queue_lock; 00770 ast_mutex_lock(l); 00771 q = sub->cx_queue; 00772 /* delete pending cx cmds */ 00773 /* buggy sb5120 */ 00774 if (!sub->parent->ncs) { 00775 while (q) { 00776 r = q->next; 00777 ast_free(q); 00778 q = r; 00779 } 00780 *queue = NULL; 00781 } 00782 break; 00783 00784 case MGCP_CMD_CRCX: 00785 case MGCP_CMD_MDCX: 00786 queue = &sub->cx_queue; 00787 l = &sub->cx_queue_lock; 00788 ast_mutex_lock(l); 00789 break; 00790 00791 case MGCP_CMD_RQNT: 00792 queue = &p->rqnt_queue; 00793 l = &p->rqnt_queue_lock; 00794 ast_mutex_lock(l); 00795 break; 00796 00797 default: 00798 queue = &p->cmd_queue; 00799 l = &p->cmd_queue_lock; 00800 ast_mutex_lock(l); 00801 break; 00802 } 00803 } 00804 00805 if (!(r = ast_malloc(sizeof(*r)))) { 00806 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n"); 00807 ast_mutex_unlock(l); 00808 return -1; 00809 } 00810 memcpy(r, req, sizeof(*r)); 00811 00812 if (!(*queue)) { 00813 ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data, 00814 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00815 00816 res = mgcp_postrequest(p, sub, req->data, req->len, seqno); 00817 } else { 00818 ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data, 00819 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00820 } 00821 00822 /* XXX find tail. We could also keep tail in the data struct for faster access */ 00823 for (t = *queue; t && t->next; t = t->next); 00824 00825 r->next = NULL; 00826 if (t) 00827 t->next = r; 00828 else 00829 *queue = r; 00830 00831 ast_mutex_unlock(l); 00832 00833 return res; 00834 }
static int send_response | ( | struct mgcp_subchannel * | sub, | |
struct mgcp_request * | req | |||
) | [static] |
Definition at line 568 of file chan_mgcp.c.
References __mgcp_xmit(), mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), 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_minexpires(), transmit_response_with_minse(), transmit_response_with_retry_after(), transmit_response_with_sdp(), transmit_response_with_sip_etag(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), update_connectedline(), and update_redirecting().
00569 { 00570 struct mgcp_endpoint *p = sub->parent; 00571 int res; 00572 ast_debug(1, "Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00573 res = __mgcp_xmit(p->parent, req->data, req->len); 00574 if (res > 0) 00575 res = 0; 00576 return res; 00577 }
static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2914 of file chan_mgcp.c.
References ast_channel_set_fd(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_rtp_instance_destroy(), ast_rtp_instance_fd(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, ast_sockaddr_from_sin, bindaddr, mgcp_subchannel::callid, mgcp_subchannel::gate, mgcp_subchannel::lock, mgcp_alloc_pktcgate(), mgcp_queue_hangup(), mgcp_subchannel::nat, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, qos, mgcp_subchannel::rtp, transmit_connect(), 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().
02915 { 02916 struct ast_sockaddr bindaddr_tmp; 02917 02918 ast_mutex_lock(&sub->lock); 02919 /* check again to be on the safe side */ 02920 if (sub->rtp) { 02921 ast_rtp_instance_destroy(sub->rtp); 02922 sub->rtp = NULL; 02923 } 02924 /* Allocate the RTP now */ 02925 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 02926 sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); 02927 if (sub->rtp && sub->owner) 02928 ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0)); 02929 if (sub->rtp) { 02930 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); 02931 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat); 02932 } 02933 /* Make a call*ID */ 02934 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); 02935 /* Transmit the connection create */ 02936 if(!sub->parent->pktcgatealloc) { 02937 transmit_connect_with_sdp(sub, NULL); 02938 } else { 02939 transmit_connect(sub); 02940 sub->gate = NULL; 02941 if(!mgcp_alloc_pktcgate(sub)) 02942 mgcp_queue_hangup(sub); 02943 } 02944 ast_mutex_unlock(&sub->lock); 02945 }
static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2626 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(), and handle_request().
02627 { 02628 struct mgcp_request resp; 02629 reqprep(&resp, p, "AUEP"); 02630 /* removed unknown param VS */ 02631 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ 02632 add_header(&resp, "F", "A"); 02633 /* fill in new fields */ 02634 resp.cmd = MGCP_CMD_AUEP; 02635 resp.trid = oseq; 02636 return send_request(p, NULL, &resp, oseq); 02637 }
static int transmit_connect | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2423 of file chan_mgcp.c.
References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), mgcp_endpoint::capability, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by skinny_unhold(), and start_rtp().
02424 { 02425 struct mgcp_request resp; 02426 char local[256]; 02427 char tmp[80]; 02428 format_t x; 02429 struct mgcp_endpoint *p = sub->parent; 02430 02431 ast_copy_string(local, "p:20, s:off, e:on", sizeof(local)); 02432 02433 for (x = 1LL; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02434 if (p->capability & x) { 02435 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02436 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02437 } 02438 } 02439 02440 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02441 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02442 sub->sdpsent = 0; 02443 reqprep(&resp, p, "CRCX"); 02444 add_header(&resp, "C", sub->callid); 02445 add_header(&resp, "L", local); 02446 add_header(&resp, "M", "inactive"); 02447 /* X header should not be sent. kept for compatibility */ 02448 add_header(&resp, "X", sub->txident); 02449 /*add_header(&resp, "S", "");*/ 02450 /* fill in new fields */ 02451 resp.cmd = MGCP_CMD_CRCX; 02452 resp.trid = oseq; 02453 return send_request(p, sub, &resp, oseq); 02454 }
static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, | |
struct ast_rtp_instance * | rtp | |||
) | [static] |
Definition at line 2328 of file chan_mgcp.c.
References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by start_rtp().
02329 { 02330 struct mgcp_request resp; 02331 char local[256]; 02332 char tmp[80]; 02333 int x; 02334 struct mgcp_endpoint *p = sub->parent; 02335 02336 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02337 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02338 02339 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02340 02341 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02342 if (!(x & AST_FORMAT_AUDIO_MASK)) { 02343 /* No longer contiguous */ 02344 continue; 02345 } 02346 if (p->capability & x) { 02347 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02348 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02349 } 02350 } 02351 02352 if (sub->gate) { 02353 if(sub->gate->state == GATE_ALLOCATED) { 02354 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02355 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02356 } 02357 } 02358 sub->sdpsent = 1; 02359 reqprep(&resp, p, "CRCX"); 02360 add_header(&resp, "C", sub->callid); 02361 add_header(&resp, "L", local); 02362 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02363 /* X header should not be sent. kept for compatibility */ 02364 add_header(&resp, "X", sub->txident); 02365 /*add_header(&resp, "S", "");*/ 02366 add_sdp(&resp, sub, rtp); 02367 /* fill in new fields */ 02368 resp.cmd = MGCP_CMD_CRCX; 02369 resp.trid = oseq; 02370 return send_request(p, sub, &resp, oseq); 02371 }
static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2639 of file chan_mgcp.c.
References add_header(), ast_debug, 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().
02640 { 02641 struct mgcp_endpoint *p = sub->parent; 02642 struct mgcp_request resp; 02643 02644 ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 02645 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02646 reqprep(&resp, p, "DLCX"); 02647 /* check if call id is avail */ 02648 if (sub->callid[0]) 02649 add_header(&resp, "C", sub->callid); 02650 /* X header should not be sent. kept for compatibility */ 02651 add_header(&resp, "X", sub->txident); 02652 /* check if cxident is avail */ 02653 if (sub->cxident[0]) 02654 add_header(&resp, "I", sub->cxident); 02655 /* fill in new fields */ 02656 resp.cmd = MGCP_CMD_DLCX; 02657 resp.trid = oseq; 02658 return send_request(p, sub, &resp, oseq); 02659 }
static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, | |
char * | callid, | |||
char * | cxident | |||
) | [static] |
Definition at line 2661 of file chan_mgcp.c.
References add_header(), ast_debug, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, reqprep(), send_request(), and mgcp_endpoint::sub.
Referenced by handle_response().
02662 { 02663 struct mgcp_request resp; 02664 02665 ast_debug(3, "Delete connection %s %s@%s on callid: %s\n", 02666 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); 02667 reqprep(&resp, p, "DLCX"); 02668 /* check if call id is avail */ 02669 if (callid && *callid) 02670 add_header(&resp, "C", callid); 02671 /* check if cxident is avail */ 02672 if (cxident && *cxident) 02673 add_header(&resp, "I", cxident); 02674 /* fill in new fields */ 02675 resp.cmd = MGCP_CMD_DLCX; 02676 resp.trid = oseq; 02677 return send_request(p, p->sub, &resp, oseq); 02678 }
static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2527 of file chan_mgcp.c.
References ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype2(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::id, mgcp_cxmodes, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_endpoint::parent, mgcp_subchannel::parent, and mgcp_endpoint::sub.
Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), mgcp_call(), mgcp_hangup(), and mgcp_indicate().
02528 { 02529 struct mgcp_request resp; 02530 struct mgcp_endpoint *p = sub->parent; 02531 format_t x; 02532 int fc = 1; 02533 char local[256]; 02534 char tmp[80]; 02535 02536 if (ast_strlen_zero(sub->cxident)) { 02537 /* We don't have a CXident yet, store the destination and 02538 wait a bit */ 02539 return 0; 02540 } 02541 ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", 02542 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02543 02544 ast_copy_string(local, "", sizeof(local)); 02545 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02546 if (p->capability & x) { 02547 if (p->ncs && !fc) { 02548 p->capability = x; /* sb5120e bug */ 02549 break; 02550 } else { 02551 fc = 0; 02552 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02553 } 02554 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02555 } 02556 } 02557 02558 if (!sub->sdpsent) { 02559 if (sub->gate) { 02560 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { 02561 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02562 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02563 } else { 02564 /* we still don't have gateid wait */ 02565 return 0; 02566 } 02567 } 02568 } 02569 02570 reqprep(&resp, p, "MDCX"); 02571 add_header(&resp, "C", sub->callid); 02572 if (!sub->sdpsent) { 02573 add_header(&resp, "L", local); 02574 } 02575 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02576 /* X header should not be sent. kept for compatibility */ 02577 add_header(&resp, "X", sub->txident); 02578 add_header(&resp, "I", sub->cxident); 02579 switch (sub->parent->hookstate) { 02580 case MGCP_ONHOOK: 02581 add_header(&resp, "R", "L/hd(N)"); 02582 break; 02583 case MGCP_OFFHOOK: 02584 add_header_offhook(sub, &resp, ""); 02585 break; 02586 } 02587 if (!sub->sdpsent) { 02588 add_sdp(&resp, sub, NULL); 02589 sub->sdpsent = 1; 02590 } 02591 /* fill in new fields */ 02592 resp.cmd = MGCP_CMD_MDCX; 02593 resp.trid = oseq; 02594 return send_request(p, sub, &resp, oseq); 02595 }
static int transmit_modify_with_sdp | ( | struct mgcp_subchannel * | sub, | |
struct ast_rtp_instance * | rtp, | |||
format_t | codecs | |||
) | [static] |
Definition at line 2271 of file chan_mgcp.c.
References ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, ast_strlen_zero(), mgcp_endpoint::capability, mgcp_subchannel::cxident, mgcp_subchannel::parent, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest.
Referenced by handle_response(), mgcp_pktcgate_open(), mgcp_set_rtp_peer(), and mgcp_write().
02272 { 02273 struct mgcp_request resp; 02274 char local[256]; 02275 char tmp[80]; 02276 struct mgcp_endpoint *p = sub->parent; 02277 format_t x; 02278 struct ast_sockaddr sub_tmpdest_tmp; 02279 02280 if (ast_strlen_zero(sub->cxident) && rtp) { 02281 /* We don't have a CXident yet, store the destination and 02282 wait a bit */ 02283 ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp); 02284 ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest); 02285 return 0; 02286 } 02287 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02288 for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { 02289 if (!(x & AST_FORMAT_AUDIO_MASK)) { 02290 /* No longer contiguous */ 02291 continue; 02292 } 02293 if (p->capability & x) { 02294 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, x, 0)); 02295 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02296 } 02297 } 02298 02299 if (sub->gate) { 02300 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { 02301 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02302 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02303 sub->sdpsent = 1; 02304 } else { 02305 /* oops wait */ 02306 ast_debug(1, "Waiting for opened gate...\n"); 02307 sub->sdpsent = 0; 02308 return 0; 02309 } 02310 } 02311 02312 02313 reqprep(&resp, p, "MDCX"); 02314 add_header(&resp, "C", sub->callid); 02315 add_header(&resp, "L", local); 02316 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02317 /* X header should not be sent. kept for compatibility */ 02318 add_header(&resp, "X", sub->txident); 02319 add_header(&resp, "I", sub->cxident); 02320 /*add_header(&resp, "S", "");*/ 02321 add_sdp(&resp, sub, rtp); 02322 /* fill in new fields */ 02323 resp.cmd = MGCP_CMD_MDCX; 02324 resp.trid = oseq; 02325 return send_request(p, sub, &resp, oseq); 02326 }
static int transmit_notify_request | ( | struct mgcp_subchannel * | sub, | |
char * | tone | |||
) | [static] |
Definition at line 2456 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_strlen_zero(), 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().
02457 { 02458 struct mgcp_request resp; 02459 struct mgcp_endpoint *p = sub->parent; 02460 02461 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02462 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02463 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02464 reqprep(&resp, p, "RQNT"); 02465 add_header(&resp, "X", p->rqnt_ident); 02466 switch (p->hookstate) { 02467 case MGCP_ONHOOK: 02468 add_header(&resp, "R", "L/hd(N)"); 02469 break; 02470 case MGCP_OFFHOOK: 02471 add_header_offhook(sub, &resp, tone); 02472 break; 02473 } 02474 if (!ast_strlen_zero(tone)) { 02475 add_header(&resp, "S", tone); 02476 } 02477 /* fill in new fields */ 02478 resp.cmd = MGCP_CMD_RQNT; 02479 resp.trid = oseq; 02480 return send_request(p, NULL, &resp, oseq); 02481 }
static int transmit_notify_request_with_callerid | ( | struct mgcp_subchannel * | sub, | |
char * | tone, | |||
char * | callernum, | |||
char * | callername | |||
) | [static] |
Definition at line 2483 of file chan_mgcp.c.
References add_header(), add_header_offhook(), ast_copy_string(), ast_debug, ast_localtime(), ast_strlen_zero(), ast_tvnow(), 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().
02484 { 02485 struct mgcp_request resp; 02486 char tone2[256]; 02487 char *l, *n; 02488 struct timeval t = ast_tvnow(); 02489 struct ast_tm tm; 02490 struct mgcp_endpoint *p = sub->parent; 02491 02492 ast_localtime(&t, &tm, NULL); 02493 n = callername; 02494 l = callernum; 02495 if (!n) 02496 n = ""; 02497 if (!l) 02498 l = ""; 02499 02500 /* Keep track of last callerid for blacklist and callreturn */ 02501 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid)); 02502 02503 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 02504 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n); 02505 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02506 reqprep(&resp, p, "RQNT"); 02507 add_header(&resp, "X", p->rqnt_ident); 02508 switch (p->hookstate) { 02509 case MGCP_ONHOOK: 02510 add_header(&resp, "R", "L/hd(N)"); 02511 break; 02512 case MGCP_OFFHOOK: 02513 add_header_offhook(sub, &resp, tone); 02514 break; 02515 } 02516 if (!ast_strlen_zero(tone2)) { 02517 add_header(&resp, "S", tone2); 02518 } 02519 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02520 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02521 /* fill in new fields */ 02522 resp.cmd = MGCP_CMD_RQNT; 02523 resp.trid = oseq; 02524 return send_request(p, NULL, &resp, oseq); 02525 }
static int transmit_response | ( | struct mgcp_subchannel * | sub, | |
char * | msg, | |||
struct mgcp_request * | req, | |||
char * | msgrest | |||
) | [static] |
Definition at line 2149 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 cc_esc_publish_handler(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_invite_replaces(), handle_keep_alive_message(), handle_register_message(), handle_request(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_refer(), handle_request_subscribe(), handle_request_update(), handle_response(), handle_sip_publish_initial(), handle_sip_publish_modify(), handle_sip_publish_refresh(), handle_sip_publish_remove(), handle_skinny_reset(), receive_message(), register_verify(), send_provisional_keepalive_full(), sip_cc_agent_destructor(), sip_cc_agent_respond(), sip_indicate(), sip_sendhtml(), skinny_reload(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_fake_auth_response(), transmit_lamp_indication(), transmit_linestatres(), transmit_provisional_response(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speaker_mode(), transmit_speeddialstatres(), transmit_start_tone(), transmit_startmediatransmission(), transmit_stop_tone(), transmit_stopmediatransmission(), and transmit_versionres().
02150 { 02151 struct mgcp_request resp; 02152 struct mgcp_endpoint *p = sub->parent; 02153 struct mgcp_response *mgr; 02154 02155 if (!sub) { 02156 return -1; 02157 } 02158 02159 respprep(&resp, p, msg, req, msgrest); 02160 if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) { 02161 return send_response(sub, &resp); 02162 } 02163 /* Store MGCP response in case we have to retransmit */ 02164 sscanf(req->identifier, "%30d", &mgr->seqno); 02165 time(&mgr->whensent); 02166 mgr->len = resp.len; 02167 memcpy(mgr->buf, resp.data, resp.len); 02168 mgr->buf[resp.len] = '\0'; 02169 mgr->next = p->parent->responses; 02170 p->parent->responses = mgr; 02171 02172 return send_response(sub, &resp); 02173 }
static int unalloc_sub | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 516 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_instance_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().
00517 { 00518 struct mgcp_endpoint *p = sub->parent; 00519 if (p->sub == sub) { 00520 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name); 00521 return -1; 00522 } 00523 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name); 00524 00525 sub->owner = NULL; 00526 if (!ast_strlen_zero(sub->cxident)) { 00527 transmit_connection_del(sub); 00528 } 00529 sub->cxident[0] = '\0'; 00530 sub->callid[0] = '\0'; 00531 sub->cxmode = MGCP_CX_INACTIVE; 00532 sub->outgoing = 0; 00533 sub->alreadygone = 0; 00534 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 00535 if (sub->rtp) { 00536 ast_rtp_instance_destroy(sub->rtp); 00537 sub->rtp = NULL; 00538 } 00539 dump_cmd_queues(NULL, sub); 00540 return 0; 00541 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4852 of file chan_mgcp.c.
References ast_channel_register(), ast_channel_unregister(), ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, AST_PTHREADT_STOP, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, LOG_WARNING, mgcp_reload(), mgcp_reload_lock, mgcp_reloading, mgcp_tech, monitor_thread, monlock, mgcp_endpoint::next, mgcp_gateway::next, and prune_gateways().
04853 { 04854 struct mgcp_endpoint *e; 04855 struct mgcp_gateway *g; 04856 04857 /* Check to see if we're reloading */ 04858 if (ast_mutex_trylock(&mgcp_reload_lock)) { 04859 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n"); 04860 return -1; 04861 } else { 04862 mgcp_reloading = 1; 04863 ast_mutex_unlock(&mgcp_reload_lock); 04864 } 04865 04866 /* First, take us out of the channel loop */ 04867 ast_channel_unregister(&mgcp_tech); 04868 04869 /* Shut down the monitoring thread */ 04870 if (!ast_mutex_lock(&monlock)) { 04871 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { 04872 pthread_cancel(monitor_thread); 04873 pthread_kill(monitor_thread, SIGURG); 04874 pthread_join(monitor_thread, NULL); 04875 } 04876 monitor_thread = AST_PTHREADT_STOP; 04877 ast_mutex_unlock(&monlock); 04878 } else { 04879 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 04880 /* We always want to leave this in a consistent state */ 04881 ast_channel_register(&mgcp_tech); 04882 mgcp_reloading = 0; 04883 mgcp_reload(NULL, 0, NULL); 04884 return -1; 04885 } 04886 04887 if (!ast_mutex_lock(&gatelock)) { 04888 for (g = gateways; g; g = g->next) { 04889 g->delme = 1; 04890 for (e = g->endpoints; e; e = e->next) { 04891 e->delme = 1; 04892 } 04893 } 04894 04895 prune_gateways(); 04896 ast_mutex_unlock(&gatelock); 04897 } else { 04898 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n"); 04899 /* We always want to leave this in a consistent state */ 04900 ast_channel_register(&mgcp_tech); 04901 /* Allow the monitor to restart */ 04902 monitor_thread = AST_PTHREADT_NULL; 04903 mgcp_reloading = 0; 04904 mgcp_reload(NULL, 0, NULL); 04905 return -1; 04906 } 04907 04908 close(mgcpsock); 04909 ast_rtp_glue_unregister(&mgcp_rtp_glue); 04910 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04911 sched_context_destroy(sched); 04912 04913 return 0; 04914 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } [static] |
Definition at line 4922 of file chan_mgcp.c.
struct in_addr __ourip [static] |
Definition at line 231 of file chan_mgcp.c.
char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static] |
Definition at line 195 of file chan_mgcp.c.
int adsi = 0 [static] |
Definition at line 201 of file chan_mgcp.c.
int amaflags = 0 [static] |
Definition at line 199 of file chan_mgcp.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4922 of file chan_mgcp.c.
struct sockaddr_in bindaddr [static] |
Definition at line 426 of file chan_mgcp.c.
int callreturn = 0 [static] |
Definition at line 180 of file chan_mgcp.c.
int callwaiting = 0 [static] |
Definition at line 178 of file chan_mgcp.c.
int cancallforward = 0 [static] |
Definition at line 189 of file chan_mgcp.c.
format_t capability = AST_FORMAT_ULAW [static] |
Definition at line 227 of file chan_mgcp.c.
Referenced by add_sdp(), build_setup(), iax2_call(), mgcp_new(), mgcp_request(), parse_setup(), process_sdp(), set_config(), and set_local_capabilities().
char cid_name[AST_MAX_EXTENSION] = "" [static] |
Definition at line 158 of file chan_mgcp.c.
Referenced by __analog_handle_event(), __oh323_new(), action_originate(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), get_pai(), get_rpid(), misdn_new(), read_config(), set_peer_defaults(), set_pvt_defaults(), sip_call(), socket_process(), and store_callerid().
char cid_num[AST_MAX_EXTENSION] = "" [static] |
Definition at line 157 of file chan_mgcp.c.
Referenced by __analog_handle_event(), __oh323_new(), action_originate(), apply_outgoing(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), create_addr_from_peer(), dahdi_handle_event(), get_pai(), get_rpid(), misdn_new(), read_config(), set_peer_defaults(), set_pvt_defaults(), socket_process(), state_notify_build_xml(), and store_callerid().
struct ast_cli_entry cli_mgcp[] [static] |
const char config[] = "mgcp.conf" [static] |
Definition at line 110 of file chan_mgcp.c.
char context[AST_MAX_EXTENSION] = "default" [static] |
Definition at line 152 of file chan_mgcp.c.
unsigned int cos |
Definition at line 172 of file chan_mgcp.c.
unsigned int cos_audio |
Definition at line 173 of file chan_mgcp.c.
ast_group_t cur_callergroup = 0 [static] |
Definition at line 166 of file chan_mgcp.c.
ast_group_t cur_pickupgroup = 0 [static] |
Definition at line 167 of file chan_mgcp.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 99 of file chan_mgcp.c.
int directmedia = DIRECTMEDIA [static] |
int dtmfmode = 0 [static] |
Definition at line 160 of file chan_mgcp.c.
Referenced by reload_config(), and set_local_capabilities().
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic)
Definition at line 206 of file chan_mgcp.c.
ast_mutex_t gatelock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
gatelock: mutex for gateway/endpoint lists
Definition at line 422 of file chan_mgcp.c.
Referenced by do_monitor(), find_subchannel_and_lock(), handle_mgcp_audit_endpoint(), handle_mgcp_show_endpoints(), mgcp_devicestate(), prune_gateways(), and unload_module().
struct mgcp_gateway * gateways [static] |
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic)
Definition at line 209 of file chan_mgcp.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 107 of file chan_mgcp.c.
int hangupongateremove = 0 [static] |
Definition at line 164 of file chan_mgcp.c.
int immediate = 0 [static] |
Definition at line 176 of file chan_mgcp.c.
struct io_context* io [static] |
Definition at line 237 of file chan_mgcp.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 154 of file chan_mgcp.c.
char mailbox[AST_MAX_EXTENSION] [static] |
Definition at line 197 of file chan_mgcp.c.
Referenced by action_mailboxcount(), action_mailboxstatus(), add_peer_mailboxes(), add_peer_mwi_subs(), aji_mwi_cb(), append_mailbox_mapping(), ast_event_hash_mwi(), build_peer(), chanspy_exec(), clear_peer_mailboxes(), disa_exec(), extenspy_exec(), get_cached_mwi(), handle_request_notify(), has_voicemail(), minivm_mwi_exec(), notify_message(), peer_mailboxes_to_str(), peers_data_provider_get(), queue_mwi_event(), realtime_directory(), sip_subscribe_mwi(), 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 212 of file chan_mgcp.c.
const char* const mgcp_cxmodes[] [static] |
}
Definition at line 132 of file chan_mgcp.c.
Referenced by transmit_connect_with_sdp(), transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
ast_mutex_t mgcp_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 418 of file chan_mgcp.c.
Referenced by do_monitor(), mgcp_reload(), and unload_module().
int mgcp_reloading = 0 [static] |
Definition at line 419 of file chan_mgcp.c.
Referenced by do_monitor(), mgcp_reload(), and unload_module().
struct ast_rtp_glue mgcp_rtp_glue [static] |
struct ast_channel_tech mgcp_tech [static] |
Definition at line 463 of file chan_mgcp.c.
Referenced by acf_channel_read(), load_module(), mgcp_new(), and unload_module().
int mgcpdebug = 0 [static] |
Definition at line 234 of file chan_mgcp.c.
Referenced by handle_mgcp_audit_endpoint(), and handle_mgcp_set_debug().
int mgcpsock = -1 [static] |
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 223 of file chan_mgcp.c.
ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 218 of file chan_mgcp.c.
char musicclass[MAX_MUSICCLASS] = "" [static] |
Definition at line 155 of file chan_mgcp.c.
Referenced by ast_do_masquerade(), begin_dial_channel(), dial_exec_full(), findmeexec(), func_channel_write_real(), gtalk_new(), jingle_new(), local_call(), moh_handle_digit(), monitor_dial(), and set_moh_exec().
int nat = 0 [static] |
Definition at line 161 of file chan_mgcp.c.
int ncs = 0 [static] |
Definition at line 162 of file chan_mgcp.c.
ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [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 216 of file chan_mgcp.c.
Referenced by config_load(), do_monitor(), handle_request_do(), and unload_module().
int nonCodecCapability = AST_RTP_DTMF [static] |
unsigned int oseq [static] |
Definition at line 203 of file chan_mgcp.c.
Referenced by init_req(), reqprep(), transmit_audit_endpoint(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_notify_request(), and transmit_notify_request_with_callerid().
char ourhost[MAXHOSTNAMELEN] [static] |
int ourport [static] |
Definition at line 232 of file chan_mgcp.c.
Referenced by initreqprep(), and transmit_notify_with_mwi().
char parkinglot[AST_MAX_CONTEXT] [static] |
Definition at line 156 of file chan_mgcp.c.
Referenced by __find_callno(), ast_iax2_new(), build_parkinglot(), build_peer(), build_user(), check_access(), check_peer_ok(), copy_parkinglot(), create_addr_from_peer(), create_dynamic_parkinglot(), dahdi_new(), find_parkinglot(), func_channel_write_real(), gtalk_load_config(), gtalk_new(), iax_park(), park_space_abort(), park_space_reserve(), parked_call_exec(), parkinglot_activate(), parkinglot_activate_cb(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_is_marked_cb(), parkinglot_markall_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().
int pktcgatealloc = 0 [static] |
Definition at line 163 of file chan_mgcp.c.
struct { ... } qos [static] |
struct sched_context* sched [static] |
Definition at line 236 of file chan_mgcp.c.
int singlepath = 0 [static] |
Definition at line 191 of file chan_mgcp.c.
int slowsequence = 0 [static] |
Definition at line 182 of file chan_mgcp.c.
const char tdesc[] = "Media Gateway Control Protocol (MGCP)" [static] |
Definition at line 109 of file chan_mgcp.c.
int threewaycalling = 0 [static] |
Definition at line 184 of file chan_mgcp.c.
unsigned int tos |
Definition at line 170 of file chan_mgcp.c.
unsigned int tos_audio |
Definition at line 171 of file chan_mgcp.c.
int transfer = 0 [static] |
This is for flashhook transfers
Definition at line 187 of file chan_mgcp.c.