#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, const char *dest, int timeout) |
| static int | mgcp_devicestate (const char *data) |
| mgcp_devicestate: channel callback for device status monitoring | |
| static int | mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static void | mgcp_get_codec (struct ast_channel *chan, struct ast_format_cap *result) |
| 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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, 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, const struct ast_format_cap *cap, 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, const struct ast_format_cap *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 = AST_BUILDOPT_SUM, .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 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_MUTEX_INITIALIZER , NULL, 1 } |
| gatelock: mutex for gateway/endpoint lists | |
| static struct mgcp_gateway * | gateways |
| static int | gendigittimeout = 8000 |
| static struct ast_format_cap * | global_capability |
| 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_MUTEX_INITIALIZER , 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_MUTEX_INITIALIZER , NULL, 1 } |
| static char | musicclass [MAX_MUSICCLASS] = "" |
| static int | nat = 0 |
| static int | ncs = 0 |
| static ast_mutex_t | netlock = { PTHREAD_MUTEX_INITIALIZER , 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 ast_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 |
| #define DEFAULT_MGCP_GW_PORT 2427 |
| #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) |
| #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 build_gateway(), destroy_endpoint(), 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 |
Definition at line 129 of file chan_mgcp.c.
Referenced by build_gateway(), mgcp_hangup(), and unalloc_sub().
| #define MGCP_CX_MUTE 4 |
| #define MGCP_CX_RECVONLY 1 |
Definition at line 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(), build_gateway(), 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(), build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_senddigit_begin(), mgcp_senddigit_end(), and mgcp_ss().
| #define MGCP_DTMF_RFC2833 (1 << 0) |
Definition at line 112 of file chan_mgcp.c.
Referenced by build_gateway(), mgcp_rtp_read(), mgcp_senddigit_begin(), and mgcp_senddigit_end().
| #define MGCP_MAX_HEADERS 64 |
The private structures of the mgcp channels are linked for selecting outgoing channels
Definition at line 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_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
| #define MGCP_ONHOOK 1 |
Definition at line 318 of file chan_mgcp.c.
Referenced by build_gateway(), do_monitor(), handle_request(), handle_response(), mgcp_call(), mgcp_hangup(), mgcp_request(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
| #define MGCP_SUBCHANNEL_MAGIC "!978!" |
subchannel magic string. Needed to prove that any subchannel pointer passed by asterisk really points to a valid subchannel memory area. Ugly.. But serves the purpose for the time being.
Definition at line 294 of file chan_mgcp.c.
Referenced by build_gateway(), and 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 build_gateway(), config_line(), config_parse_variables(), do_monitor(), and mgcp_call().
| #define TYPE_TRUNK 1 |
| anonymous enum |
| MGCP_CMD_EPCF | |
| MGCP_CMD_CRCX | |
| MGCP_CMD_MDCX | |
| MGCP_CMD_DLCX | |
| MGCP_CMD_RQNT | |
| MGCP_CMD_NTFY | |
| MGCP_CMD_AUEP | |
| MGCP_CMD_AUCX | |
| MGCP_CMD_RSIP |
Definition at line 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(), parse_register_contact(), and sip_get_header().
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 543 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().
00544 { 00545 int res; 00546 if (gw->addr.sin_addr.s_addr) 00547 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); 00548 else 00549 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); 00550 if (res != len) { 00551 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); 00552 } 00553 return res; 00554 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 4953 of file chan_mgcp.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4953 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 4459 of file chan_mgcp.c.
References ast_log(), LOG_ERROR, mgcp_endpoint::ncs, mgcp_subchannel::parent, sub, ast_channel::tech, and ast_channel::tech_pvt.
04460 { 04461 struct mgcp_subchannel *sub = chan->tech_pvt; 04462 int res = 0; 04463 04464 /* Sanity check */ 04465 if (!chan || chan->tech != &mgcp_tech) { 04466 ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n"); 04467 return -1; 04468 } 04469 04470 if (!strcasecmp(args, "ncs")) { 04471 snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no"); 04472 } else { 04473 res = -1; 04474 } 04475 return res; 04476 }
| static int add_header | ( | struct mgcp_request * | req, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 2049 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_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_invite(), transmit_modify_request(), transmit_modify_with_sdp(), 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().
02050 { 02051 if (req->len >= sizeof(req->data) - 4) { 02052 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02053 return -1; 02054 } 02055 if (req->lines) { 02056 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 02057 return -1; 02058 } 02059 req->header[req->headers] = req->data + req->len; 02060 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); 02061 req->len += strlen(req->header[req->headers]); 02062 if (req->headers < MGCP_MAX_HEADERS) { 02063 req->headers++; 02064 } else { 02065 ast_log(LOG_WARNING, "Out of header space\n"); 02066 return -1; 02067 } 02068 return 0; 02069 }
| static void add_header_offhook | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | resp, | |||
| char * | tone | |||
| ) | [static] |
Definition at line 2614 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_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
02615 { 02616 struct mgcp_endpoint *p = sub->parent; 02617 char tone_indicate_end = 0; 02618 02619 /* We also should check the tone to indicate, because it have no sense 02620 to request notify D/[0-9#*] (dtmf keys) if we are sending congestion 02621 tone for example G/cg */ 02622 if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) { 02623 tone_indicate_end = 1; 02624 } 02625 02626 if (p && p->sub && p->sub->owner && 02627 p->sub->owner->_state >= AST_STATE_RINGING && 02628 (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) { 02629 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02630 02631 } else if (!tone_indicate_end){ 02632 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)")); 02633 } else { 02634 ast_debug(1, "We don't want more digits if we will end the call\n"); 02635 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02636 } 02637 }
| static int add_line | ( | struct mgcp_request * | req, | |
| char * | line | |||
| ) | [static] |
Definition at line 2071 of file chan_mgcp.c.
References ast_copy_string(), ast_log(), mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES.
Referenced by add_sdp().
02072 { 02073 if (req->len >= sizeof(req->data) - 4) { 02074 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02075 return -1; 02076 } 02077 if (!req->lines) { 02078 /* Add extra empty return */ 02079 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); 02080 req->len += strlen(req->data + req->len); 02081 } 02082 req->line[req->lines] = req->data + req->len; 02083 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 02084 req->len += strlen(req->line[req->lines]); 02085 if (req->lines < MGCP_MAX_LINES) { 02086 req->lines++; 02087 } else { 02088 ast_log(LOG_WARNING, "Out of line space\n"); 02089 return -1; 02090 } 02091 return 0; 02092 }
| static int add_sdp | ( | struct mgcp_request * | resp, | |
| struct mgcp_subchannel * | sub, | |||
| struct ast_rtp_instance * | rtp | |||
| ) | [static] |
Definition at line 2181 of file chan_mgcp.c.
References add_line(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_AUDIO, ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_codecs_payload_code(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), AST_RTP_MAX, ast_sockaddr_to_sin, mgcp_endpoint::cap, ast_format::id, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, and mgcp_subchannel::tmpdest.
Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and update_connectedline().
02182 { 02183 int len; 02184 int codec; 02185 char costr[80]; 02186 struct sockaddr_in sin; 02187 struct ast_sockaddr sin_tmp; 02188 char v[256]; 02189 char s[256]; 02190 char o[256]; 02191 char c[256]; 02192 char t[256]; 02193 char m[256] = ""; 02194 char a[1024] = ""; 02195 int x; 02196 struct ast_format tmpfmt; 02197 struct sockaddr_in dest = { 0, }; 02198 struct ast_sockaddr dest_tmp; 02199 struct mgcp_endpoint *p = sub->parent; 02200 /* XXX We break with the "recommendation" and send our IP, in order that our 02201 peer doesn't have to ast_gethostbyname() us XXX */ 02202 len = 0; 02203 if (!sub->rtp) { 02204 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02205 return -1; 02206 } 02207 ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp); 02208 ast_sockaddr_to_sin(&sin_tmp, &sin); 02209 if (rtp) { 02210 ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp); 02211 ast_sockaddr_to_sin(&dest_tmp, &dest); 02212 } else { 02213 if (sub->tmpdest.sin_addr.s_addr) { 02214 dest.sin_addr = sub->tmpdest.sin_addr; 02215 dest.sin_port = sub->tmpdest.sin_port; 02216 /* Reset temporary destination */ 02217 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02218 } else { 02219 dest.sin_addr = p->parent->ourip; 02220 dest.sin_port = sin.sin_port; 02221 } 02222 } 02223 ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02224 ast_copy_string(v, "v=0\r\n", sizeof(v)); 02225 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); 02226 ast_copy_string(s, "s=session\r\n", sizeof(s)); 02227 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02228 ast_copy_string(t, "t=0 0\r\n", sizeof(t)); 02229 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02230 02231 ast_format_cap_iter_start(p->cap); 02232 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02233 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { 02234 /* Audio is now discontiguous */ 02235 continue; 02236 } 02237 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02238 ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt)); 02239 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0); 02240 if (codec > -1) { 02241 snprintf(costr, sizeof(costr), " %d", codec); 02242 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02243 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02244 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02245 } 02246 } 02247 } 02248 ast_format_cap_iter_end(p->cap); 02249 02250 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { 02251 if (p->nonCodecCapability & x) { 02252 ast_debug(1, "Answering with non-codec capability %d\n", (int) x); 02253 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, NULL, x); 02254 if (codec > -1) { 02255 snprintf(costr, sizeof(costr), " %d", codec); 02256 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02257 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0)); 02258 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02259 if (x == AST_RTP_DTMF) { 02260 /* Indicate we support DTMF... Not sure about 16, 02261 but MSN supports it so dang it, we will too... */ 02262 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02263 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02264 } 02265 } 02266 } 02267 } 02268 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02269 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02270 snprintf(costr, sizeof(costr), "%d", len); 02271 add_line(resp, v); 02272 add_line(resp, o); 02273 add_line(resp, s); 02274 add_line(resp, c); 02275 add_line(resp, t); 02276 add_line(resp, m); 02277 add_line(resp, a); 02278 return 0; 02279 }
| static struct ast_variable * add_var | ( | const char * | buf, | |
| struct ast_variable * | list | |||
| ) | [static, read] |
Definition at line 4590 of file chan_mgcp.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
Referenced by build_gateway(), build_peer(), and config_parse_variables().
04591 { 04592 struct ast_variable *tmpvar = NULL; 04593 char *varname = ast_strdupa(buf), *varval = NULL; 04594 04595 if ((varval = strchr(varname, '='))) { 04596 *varval++ = '\0'; 04597 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 04598 tmpvar->next = list; 04599 list = tmpvar; 04600 } 04601 } 04602 return list; 04603 }
| static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 3216 of file chan_mgcp.c.
References ast_channel::_softhangup, ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_name(), 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, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, and unalloc_sub().
03217 { 03218 /* ************************* 03219 * I hope this works. 03220 * Copied out of chan_zap 03221 * Cross your fingers 03222 * *************************/ 03223 03224 /* In order to transfer, we need at least one of the channels to 03225 actually be in a call bridge. We can't conference two applications 03226 together (but then, why would we want to?) */ 03227 if (ast_bridged_channel(p->sub->owner)) { 03228 /* The three-way person we're about to transfer to could still be in MOH, so 03229 stop if now if appropriate */ 03230 if (ast_bridged_channel(p->sub->next->owner)) 03231 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03232 if (p->sub->owner->_state == AST_STATE_RINGING) { 03233 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03234 } 03235 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 03236 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03237 ast_channel_name(ast_bridged_channel(p->sub->owner)), ast_channel_name(p->sub->next->owner)); 03238 return -1; 03239 } 03240 /* Orphan the channel */ 03241 unalloc_sub(p->sub->next); 03242 } else if (ast_bridged_channel(p->sub->next->owner)) { 03243 if (p->sub->owner->_state == AST_STATE_RINGING) { 03244 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03245 } 03246 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03247 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 03248 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03249 ast_channel_name(ast_bridged_channel(p->sub->next->owner)), ast_channel_name(p->sub->owner)); 03250 return -1; 03251 } 03252 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 03253 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03254 p->sub = p->sub->next; 03255 unalloc_sub(p->sub->next); 03256 /* Tell the caller not to hangup */ 03257 return 1; 03258 } else { 03259 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03260 ast_channel_name(p->sub->owner), ast_channel_name(p->sub->next->owner)); 03261 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03262 if (p->sub->next->owner) { 03263 p->sub->next->alreadygone = 1; 03264 mgcp_queue_hangup(p->sub->next); 03265 } 03266 } 03267 return 0; 03268 }
| static struct mgcp_gateway * build_gateway | ( | char * | cat, | |
| struct ast_variable * | v | |||
| ) | [static, read] |
build_gateway: parse mgcp.conf and create gateway/endpoint structures
Definition at line 3972 of file chan_mgcp.c.
References __ourip, mgcp_endpoint::accountcode, add_var(), mgcp_gateway::addr, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_format_cap_alloc_nolock(), ast_format_cap_copy(), ast_free, ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy, ast_mutex_init, ast_ouraddrfor(), ast_random(), AST_SCHED_DEL, ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variables_destroy(), ast_verb, mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, copy_vars(), mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::directmedia, DIRECTMEDIA, mgcp_endpoint::dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, mgcp_subchannel::gate, gateways, mgcp_gateway::ha, mgcp_endpoint::hangupongateremove, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, INADDR_NONE, mgcp_gateway::isnamedottedip, mgcp_endpoint::language, ast_variable::lineno, mgcp_subchannel::lock, mgcp_endpoint::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, MAX_SUBS, mbox(), MGCP_CX_INACTIVE, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, mgcp_gateway::msgs_lock, mgcp_endpoint::msgstate, mgcp_endpoint::musicclass, mwi_event_cb(), mgcp_endpoint::mwi_event_sub, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, mgcp_endpoint::ncs, mgcp_endpoint::needaudit, mgcp_subchannel::next, mgcp_endpoint::next, ast_variable::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_gateway::ourip, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::parkinglot, mgcp_endpoint::pickupgroup, mgcp_endpoint::pktcgatealloc, mgcp_gateway::realtime, mgcp_gateway::retransid, mgcp_endpoint::rqnt_ident, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, mgcp_endpoint::slowsequence, strsep(), mgcp_endpoint::sub, sub, mgcp_endpoint::threewaycalling, mgcp_endpoint::transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and mgcp_gateway::wcardep.
Referenced by find_realtime_gw(), and reload_config().
03973 { 03974 struct mgcp_gateway *gw; 03975 struct mgcp_endpoint *e; 03976 struct mgcp_subchannel *sub; 03977 struct ast_variable *chanvars = NULL; 03978 03979 /*char txident[80];*/ 03980 int i=0, y=0; 03981 int gw_reload = 0; 03982 int ep_reload = 0; 03983 directmedia = DIRECTMEDIA; 03984 03985 /* locate existing gateway */ 03986 for (gw = gateways; gw; gw = gw->next) { 03987 if (!strcasecmp(cat, gw->name)) { 03988 /* gateway already exists */ 03989 gw->delme = 0; 03990 gw_reload = 1; 03991 break; 03992 } 03993 } 03994 03995 if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) { 03996 return NULL; 03997 } 03998 03999 if (!gw_reload) { 04000 gw->expire = -1; 04001 gw->realtime = 0; 04002 gw->retransid = -1; 04003 ast_mutex_init(&gw->msgs_lock); 04004 ast_copy_string(gw->name, cat, sizeof(gw->name)); 04005 /* check if the name is numeric ip */ 04006 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 04007 gw->isnamedottedip = 1; 04008 } 04009 for (; v; v = v->next) { 04010 if (!strcasecmp(v->name, "host")) { 04011 if (!strcasecmp(v->value, "dynamic")) { 04012 /* They'll register with us */ 04013 gw->dynamic = 1; 04014 memset(&gw->addr.sin_addr, 0, 4); 04015 if (gw->addr.sin_port) { 04016 /* If we've already got a port, make it the default rather than absolute */ 04017 gw->defaddr.sin_port = gw->addr.sin_port; 04018 gw->addr.sin_port = 0; 04019 } 04020 } else { 04021 /* Non-dynamic. Make sure we become that way if we're not */ 04022 AST_SCHED_DEL(sched, gw->expire); 04023 gw->dynamic = 0; 04024 { 04025 struct ast_sockaddr tmp; 04026 04027 ast_sockaddr_from_sin(&tmp, &gw->addr); 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->addr); 04036 } 04037 } 04038 } else if (!strcasecmp(v->name, "defaultip")) { 04039 struct ast_sockaddr tmp; 04040 04041 ast_sockaddr_from_sin(&tmp, &gw->defaddr); 04042 if (ast_get_ip(&tmp, v->value)) { 04043 if (!gw_reload) { 04044 ast_mutex_destroy(&gw->msgs_lock); 04045 ast_free(gw); 04046 } 04047 return NULL; 04048 } 04049 ast_sockaddr_to_sin(&tmp, &gw->defaddr); 04050 } else if (!strcasecmp(v->name, "permit") || 04051 !strcasecmp(v->name, "deny")) { 04052 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 04053 } else if (!strcasecmp(v->name, "port")) { 04054 gw->addr.sin_port = htons(atoi(v->value)); 04055 } else if (!strcasecmp(v->name, "context")) { 04056 ast_copy_string(context, v->value, sizeof(context)); 04057 } else if (!strcasecmp(v->name, "dtmfmode")) { 04058 if (!strcasecmp(v->value, "inband")) 04059 dtmfmode = MGCP_DTMF_INBAND; 04060 else if (!strcasecmp(v->value, "rfc2833")) 04061 dtmfmode = MGCP_DTMF_RFC2833; 04062 else if (!strcasecmp(v->value, "hybrid")) 04063 dtmfmode = MGCP_DTMF_HYBRID; 04064 else if (!strcasecmp(v->value, "none")) 04065 dtmfmode = 0; 04066 else 04067 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 04068 } else if (!strcasecmp(v->name, "nat")) { 04069 nat = ast_true(v->value); 04070 } else if (!strcasecmp(v->name, "ncs")) { 04071 ncs = ast_true(v->value); 04072 } else if (!strcasecmp(v->name, "hangupongateremove")) { 04073 hangupongateremove = ast_true(v->value); 04074 } else if (!strcasecmp(v->name, "pktcgatealloc")) { 04075 pktcgatealloc = ast_true(v->value); 04076 } else if (!strcasecmp(v->name, "callerid")) { 04077 if (!strcasecmp(v->value, "asreceived")) { 04078 cid_num[0] = '\0'; 04079 cid_name[0] = '\0'; 04080 } else { 04081 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 04082 } 04083 } else if (!strcasecmp(v->name, "language")) { 04084 ast_copy_string(language, v->value, sizeof(language)); 04085 } else if (!strcasecmp(v->name, "accountcode")) { 04086 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 04087 } else if (!strcasecmp(v->name, "amaflags")) { 04088 y = ast_cdr_amaflags2int(v->value); 04089 if (y < 0) { 04090 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 04091 } else { 04092 amaflags = y; 04093 } 04094 } else if (!strcasecmp(v->name, "setvar")) { 04095 chanvars = add_var(v->value, chanvars); 04096 } else if (!strcasecmp(v->name, "clearvars")) { 04097 if (chanvars) { 04098 ast_variables_destroy(chanvars); 04099 chanvars = NULL; 04100 } 04101 } else if (!strcasecmp(v->name, "musiconhold")) { 04102 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 04103 } else if (!strcasecmp(v->name, "parkinglot")) { 04104 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 04105 } else if (!strcasecmp(v->name, "callgroup")) { 04106 cur_callergroup = ast_get_group(v->value); 04107 } else if (!strcasecmp(v->name, "pickupgroup")) { 04108 cur_pickupgroup = ast_get_group(v->value); 04109 } else if (!strcasecmp(v->name, "immediate")) { 04110 immediate = ast_true(v->value); 04111 } else if (!strcasecmp(v->name, "cancallforward")) { 04112 cancallforward = ast_true(v->value); 04113 } else if (!strcasecmp(v->name, "singlepath")) { 04114 singlepath = ast_true(v->value); 04115 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 04116 directmedia = ast_true(v->value); 04117 } else if (!strcasecmp(v->name, "mailbox")) { 04118 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 04119 } else if (!strcasecmp(v->name, "hasvoicemail")) { 04120 if (ast_true(v->value) && ast_strlen_zero(mailbox)) { 04121 ast_copy_string(mailbox, gw->name, sizeof(mailbox)); 04122 } 04123 } else if (!strcasecmp(v->name, "adsi")) { 04124 adsi = ast_true(v->value); 04125 } else if (!strcasecmp(v->name, "callreturn")) { 04126 callreturn = ast_true(v->value); 04127 } else if (!strcasecmp(v->name, "callwaiting")) { 04128 callwaiting = ast_true(v->value); 04129 } else if (!strcasecmp(v->name, "slowsequence")) { 04130 slowsequence = ast_true(v->value); 04131 } else if (!strcasecmp(v->name, "transfer")) { 04132 transfer = ast_true(v->value); 04133 } else if (!strcasecmp(v->name, "threewaycalling")) { 04134 threewaycalling = ast_true(v->value); 04135 } else if (!strcasecmp(v->name, "wcardep")) { 04136 /* locate existing endpoint */ 04137 for (e = gw->endpoints; e; e = e->next) { 04138 if (!strcasecmp(v->value, e->name)) { 04139 /* endpoint already exists */ 04140 e->delme = 0; 04141 ep_reload = 1; 04142 break; 04143 } 04144 } 04145 04146 if (!e) { 04147 /* Allocate wildcard endpoint */ 04148 e = ast_calloc(1, sizeof(*e)); 04149 ep_reload = 0; 04150 } 04151 04152 if (e) { 04153 if (!ep_reload) { 04154 memset(e, 0, sizeof(struct mgcp_endpoint)); 04155 ast_mutex_init(&e->lock); 04156 ast_mutex_init(&e->rqnt_queue_lock); 04157 ast_mutex_init(&e->cmd_queue_lock); 04158 e->cap = ast_format_cap_alloc_nolock(); 04159 ast_copy_string(e->name, v->value, sizeof(e->name)); 04160 e->needaudit = 1; 04161 } 04162 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 04163 /* XXX Should we really check for uniqueness?? XXX */ 04164 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04165 ast_copy_string(e->context, context, sizeof(e->context)); 04166 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04167 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04168 ast_copy_string(e->language, language, sizeof(e->language)); 04169 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04170 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04171 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04172 if (!ast_strlen_zero(e->mailbox)) { 04173 char *mbox, *cntx; 04174 cntx = mbox = ast_strdupa(e->mailbox); 04175 strsep(&cntx, "@"); 04176 if (ast_strlen_zero(cntx)) { 04177 cntx = "default"; 04178 } 04179 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL, 04180 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 04181 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 04182 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 04183 AST_EVENT_IE_END); 04184 } 04185 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04186 e->msgstate = -1; 04187 e->amaflags = amaflags; 04188 ast_format_cap_copy(e->cap, global_capability); 04189 e->parent = gw; 04190 e->ncs = ncs; 04191 e->dtmfmode = dtmfmode; 04192 if (!ep_reload && e->sub && e->sub->rtp) { 04193 e->dtmfmode |= MGCP_DTMF_INBAND; 04194 } 04195 e->adsi = adsi; 04196 e->type = TYPE_LINE; 04197 e->immediate = immediate; 04198 e->callgroup=cur_callergroup; 04199 e->pickupgroup=cur_pickupgroup; 04200 e->callreturn = callreturn; 04201 e->cancallforward = cancallforward; 04202 e->singlepath = singlepath; 04203 e->directmedia = directmedia; 04204 e->callwaiting = callwaiting; 04205 e->hascallwaiting = callwaiting; 04206 e->slowsequence = slowsequence; 04207 e->transfer = transfer; 04208 e->threewaycalling = threewaycalling; 04209 e->onhooktime = time(NULL); 04210 /* ASSUME we're onhook */ 04211 e->hookstate = MGCP_ONHOOK; 04212 e->chanvars = copy_vars(chanvars); 04213 if (!ep_reload) { 04214 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 04215 for (i = 0; i < MAX_SUBS; i++) { 04216 sub = ast_calloc(1, sizeof(*sub)); 04217 if (sub) { 04218 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04219 ast_mutex_init(&sub->lock); 04220 ast_mutex_init(&sub->cx_queue_lock); 04221 sub->parent = e; 04222 sub->id = i; 04223 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04224 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 04225 sub->cxmode = MGCP_CX_INACTIVE; 04226 sub->nat = nat; 04227 sub->gate = NULL; 04228 sub->sdpsent = 0; 04229 sub->next = e->sub; 04230 e->sub = sub; 04231 } else { 04232 /* XXX Should find a way to clean up our memory */ 04233 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04234 return NULL; 04235 } 04236 } 04237 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04238 /* find the end of the list */ 04239 for (sub = e->sub; sub && sub->next; sub = sub->next); 04240 /* set the last sub->next to the first sub */ 04241 sub->next = e->sub; 04242 04243 e->next = gw->endpoints; 04244 gw->endpoints = e; 04245 } 04246 } 04247 } else if (!strcasecmp(v->name, "trunk") || 04248 !strcasecmp(v->name, "line")) { 04249 04250 /* locate existing endpoint */ 04251 for (e = gw->endpoints; e; e = e->next) { 04252 if (!strcasecmp(v->value, e->name)) { 04253 /* endpoint already exists */ 04254 e->delme = 0; 04255 ep_reload = 1; 04256 break; 04257 } 04258 } 04259 04260 if (!e) { 04261 e = ast_calloc(1, sizeof(*e)); 04262 ep_reload = 0; 04263 } 04264 04265 if (e) { 04266 if (!ep_reload) { 04267 ast_mutex_init(&e->lock); 04268 ast_mutex_init(&e->rqnt_queue_lock); 04269 ast_mutex_init(&e->cmd_queue_lock); 04270 e->cap = ast_format_cap_alloc_nolock(); 04271 ast_copy_string(e->name, v->value, sizeof(e->name)); 04272 e->needaudit = 1; 04273 } 04274 /* XXX Should we really check for uniqueness?? XXX */ 04275 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04276 ast_copy_string(e->context, context, sizeof(e->context)); 04277 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04278 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04279 ast_copy_string(e->language, language, sizeof(e->language)); 04280 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04281 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04282 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04283 if (!ast_strlen_zero(mailbox)) { 04284 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 04285 } 04286 if (!ep_reload) { 04287 /* XXX potential issue due to reload */ 04288 e->msgstate = -1; 04289 e->parent = gw; 04290 } 04291 e->amaflags = amaflags; 04292 ast_format_cap_copy(e->cap, global_capability); 04293 e->dtmfmode = dtmfmode; 04294 e->ncs = ncs; 04295 e->pktcgatealloc = pktcgatealloc; 04296 e->hangupongateremove = hangupongateremove; 04297 e->adsi = adsi; 04298 e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE; 04299 e->immediate = immediate; 04300 e->callgroup=cur_callergroup; 04301 e->pickupgroup=cur_pickupgroup; 04302 e->callreturn = callreturn; 04303 e->cancallforward = cancallforward; 04304 e->directmedia = directmedia; 04305 e->singlepath = singlepath; 04306 e->callwaiting = callwaiting; 04307 e->hascallwaiting = callwaiting; 04308 e->slowsequence = slowsequence; 04309 e->transfer = transfer; 04310 e->threewaycalling = threewaycalling; 04311 04312 /* If we already have a valid chanvars, it's not a new endpoint (it's a reload), 04313 so first, free previous mem 04314 */ 04315 if (e->chanvars) { 04316 ast_variables_destroy(e->chanvars); 04317 e->chanvars = NULL; 04318 } 04319 e->chanvars = copy_vars(chanvars); 04320 04321 if (!ep_reload) { 04322 e->onhooktime = time(NULL); 04323 /* ASSUME we're onhook */ 04324 e->hookstate = MGCP_ONHOOK; 04325 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04326 } 04327 04328 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 04329 if (!ep_reload) { 04330 sub = ast_calloc(1, sizeof(*sub)); 04331 } else { 04332 if (!sub) { 04333 sub = e->sub; 04334 } else { 04335 sub = sub->next; 04336 } 04337 } 04338 04339 if (sub) { 04340 if (!ep_reload) { 04341 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04342 ast_mutex_init(&sub->lock); 04343 ast_mutex_init(&sub->cx_queue_lock); 04344 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 04345 sub->parent = e; 04346 sub->id = i; 04347 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04348 sub->cxmode = MGCP_CX_INACTIVE; 04349 sub->next = e->sub; 04350 e->sub = sub; 04351 } 04352 sub->nat = nat; 04353 } else { 04354 /* XXX Should find a way to clean up our memory */ 04355 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04356 return NULL; 04357 } 04358 } 04359 if (!ep_reload) { 04360 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04361 /* find the end of the list */ 04362 for (sub = e->sub; sub && sub->next; sub = sub->next); 04363 /* set the last sub->next to the first sub */ 04364 sub->next = e->sub; 04365 04366 e->next = gw->endpoints; 04367 gw->endpoints = e; 04368 } 04369 } 04370 } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) { 04371 /* just eliminate realtime warnings */ 04372 } else { 04373 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 04374 } 04375 } 04376 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 04377 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 04378 if (!gw_reload) { 04379 ast_mutex_destroy(&gw->msgs_lock); 04380 ast_free(gw); 04381 } 04382 04383 /* Return NULL */ 04384 gw_reload = 1; 04385 } else { 04386 gw->defaddr.sin_family = AF_INET; 04387 gw->addr.sin_family = AF_INET; 04388 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) { 04389 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04390 } 04391 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) { 04392 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04393 } 04394 { 04395 struct ast_sockaddr tmp1, tmp2; 04396 struct sockaddr_in tmp3 = {0,}; 04397 04398 tmp3.sin_addr = gw->ourip; 04399 ast_sockaddr_from_sin(&tmp1, &gw->addr); 04400 ast_sockaddr_from_sin(&tmp2, &tmp3); 04401 if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) { 04402 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 04403 } else { 04404 ast_sockaddr_to_sin(&tmp2, &tmp3); 04405 gw->ourip = tmp3.sin_addr; 04406 } 04407 } 04408 } 04409 04410 if (chanvars) { 04411 ast_variables_destroy(chanvars); 04412 chanvars = NULL; 04413 } 04414 return (gw_reload ? NULL : gw); 04415 }
| static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1406 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().
01406 { 01407 switch (ind) { 01408 case AST_CONTROL_HANGUP: 01409 return "Other end has hungup"; 01410 case AST_CONTROL_RING: 01411 return "Local ring"; 01412 case AST_CONTROL_RINGING: 01413 return "Remote end is ringing"; 01414 case AST_CONTROL_ANSWER: 01415 return "Remote end has answered"; 01416 case AST_CONTROL_BUSY: 01417 return "Remote end is busy"; 01418 case AST_CONTROL_TAKEOFFHOOK: 01419 return "Make it go off hook"; 01420 case AST_CONTROL_OFFHOOK: 01421 return "Line is off hook"; 01422 case AST_CONTROL_CONGESTION: 01423 return "Congestion (circuits busy)"; 01424 case AST_CONTROL_FLASH: 01425 return "Flash hook"; 01426 case AST_CONTROL_WINK: 01427 return "Wink"; 01428 case AST_CONTROL_OPTION: 01429 return "Set a low-level option"; 01430 case AST_CONTROL_RADIO_KEY: 01431 return "Key Radio"; 01432 case AST_CONTROL_RADIO_UNKEY: 01433 return "Un-Key Radio"; 01434 } 01435 return "UNKNOWN"; 01436 }
| static struct ast_variable * copy_vars | ( | struct ast_variable * | src | ) | [static, read] |
duplicate a list of channel variables,
Definition at line 4608 of file chan_mgcp.c.
References ast_variable_new(), and ast_variable::next.
Referenced by build_gateway(), check_peer_ok(), and create_addr_from_peer().
04609 { 04610 struct ast_variable *res = NULL, *tmp, *v = NULL; 04611 04612 for (v = src ; v ; v = v->next) { 04613 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 04614 tmp->next = res; 04615 res = tmp; 04616 } 04617 } 04618 return res; 04619 }
| static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 4479 of file chan_mgcp.c.
References ast_dsp_free(), ast_event_unsubscribe(), ast_format_cap_destroy(), ast_free, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_destroy(), ast_strlen_zero(), ast_variables_destroy(), mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cxident, mgcp_endpoint::dsp, dump_cmd_queues(), dump_queue(), mgcp_subchannel::gate, cops_gate::gate_open, cops_gate::gate_remove, cops_gate::got_dq_gi, mgcp_endpoint::lock, mgcp_subchannel::lock, mgcp_subchannel::magic, MAX_SUBS, mgcp_queue_hangup(), mgcp_endpoint::mwi_event_sub, mgcp_subchannel::next, mgcp_endpoint::parent, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::sub, sub, cops_gate::tech_pvt, and transmit_connection_del().
Referenced by prune_gateways().
04480 { 04481 struct mgcp_subchannel *sub = e->sub->next, *s; 04482 int i; 04483 04484 for (i = 0; i < MAX_SUBS; i++) { 04485 ast_mutex_lock(&sub->lock); 04486 if (!ast_strlen_zero(sub->cxident)) { 04487 transmit_connection_del(sub); 04488 } 04489 if (sub->rtp) { 04490 ast_rtp_instance_destroy(sub->rtp); 04491 sub->rtp = NULL; 04492 } 04493 memset(sub->magic, 0, sizeof(sub->magic)); 04494 mgcp_queue_hangup(sub); 04495 dump_cmd_queues(NULL, sub); 04496 if(sub->gate) { 04497 sub->gate->tech_pvt = NULL; 04498 sub->gate->got_dq_gi = NULL; 04499 sub->gate->gate_remove = NULL; 04500 sub->gate->gate_open = NULL; 04501 } 04502 ast_mutex_unlock(&sub->lock); 04503 sub = sub->next; 04504 } 04505 04506 if (e->dsp) { 04507 ast_dsp_free(e->dsp); 04508 } 04509 04510 dump_queue(e->parent, e); 04511 dump_cmd_queues(e, NULL); 04512 04513 sub = e->sub; 04514 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04515 s = sub; 04516 sub = sub->next; 04517 ast_mutex_destroy(&s->lock); 04518 ast_mutex_destroy(&s->cx_queue_lock); 04519 ast_free(s); 04520 } 04521 04522 if (e->mwi_event_sub) 04523 ast_event_unsubscribe(e->mwi_event_sub); 04524 04525 if (e->chanvars) { 04526 ast_variables_destroy(e->chanvars); 04527 e->chanvars = NULL; 04528 } 04529 04530 ast_mutex_destroy(&e->lock); 04531 ast_mutex_destroy(&e->rqnt_queue_lock); 04532 ast_mutex_destroy(&e->cmd_queue_lock); 04533 e->cap = ast_format_cap_destroy(e->cap); 04534 ast_free(e); 04535 }
| static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4537 of file chan_mgcp.c.
References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.
Referenced by fax_gateway_new(), and prune_gateways().
04538 { 04539 if (g->ha) 04540 ast_free_ha(g->ha); 04541 04542 dump_queue(g, NULL); 04543 04544 ast_free(g); 04545 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3776 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(), MGCP_ONHOOK, mgcp_prune_realtime_gateway(), mgcp_reload_lock, mgcpsock_read(), monlock, mgcp_gateway::msgs_lock, netlock, mgcp_gateway::next, mgcp_gateway::realtime, reload_config(), transmit_notify_request(), and TYPE_LINE.
03777 { 03778 int res; 03779 int reloading; 03780 struct mgcp_gateway *g, *gprev; 03781 /*struct mgcp_gateway *g;*/ 03782 /*struct mgcp_endpoint *e;*/ 03783 /*time_t thispass = 0, lastpass = 0;*/ 03784 time_t lastrun = 0; 03785 03786 /* Add an I/O event to our UDP socket */ 03787 if (mgcpsock > -1) { 03788 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03789 } 03790 /* This thread monitors all the frame relay interfaces which are not yet in use 03791 (and thus do not have a separate thread) indefinitely */ 03792 /* From here on out, we die whenever asked */ 03793 for (;;) { 03794 /* Check for a reload request */ 03795 ast_mutex_lock(&mgcp_reload_lock); 03796 reloading = mgcp_reloading; 03797 mgcp_reloading = 0; 03798 ast_mutex_unlock(&mgcp_reload_lock); 03799 if (reloading) { 03800 ast_verb(1, "Reloading MGCP\n"); 03801 reload_config(1); 03802 /* Add an I/O event to our UDP socket */ 03803 if (mgcpsock > -1 && !mgcpsock_read_id) { 03804 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03805 } 03806 } 03807 03808 /* Check for interfaces needing to be killed */ 03809 /* Don't let anybody kill us right away. Nobody should lock the interface list 03810 and wait for the monitor list, but the other way around is okay. */ 03811 ast_mutex_lock(&monlock); 03812 /* Lock the network interface */ 03813 ast_mutex_lock(&netlock); 03814 03815 #if 0 03816 /* XXX THIS IS COMPLETELY HOSED */ 03817 /* The gateway goes into a state of panic */ 03818 /* If the vmwi indicator is sent while it is reseting interfaces */ 03819 lastpass = thispass; 03820 thispass = time(NULL); 03821 g = gateways; 03822 while(g) { 03823 if (thispass != lastpass) { 03824 e = g->endpoints; 03825 while(e) { 03826 if (e->type == TYPE_LINE) { 03827 res = has_voicemail(e); 03828 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03829 if (res) { 03830 transmit_notify_request(e, "L/vmwi(+)"); 03831 } else { 03832 transmit_notify_request(e, "L/vmwi(-)"); 03833 } 03834 e->msgstate = res; 03835 e->onhooktime = thispass; 03836 } 03837 } 03838 e = e->next; 03839 } 03840 } 03841 g = g->next; 03842 } 03843 #endif 03844 /* pruning unused realtime gateways, running in every 60 seconds*/ 03845 if(time(NULL) > (lastrun + 60)) { 03846 ast_mutex_lock(&gatelock); 03847 g = gateways; 03848 gprev = NULL; 03849 while(g) { 03850 if(g->realtime) { 03851 if(mgcp_prune_realtime_gateway(g)) { 03852 if(gprev) { 03853 gprev->next = g->next; 03854 } else { 03855 gateways = g->next; 03856 } 03857 ast_mutex_unlock(&g->msgs_lock); 03858 ast_mutex_destroy(&g->msgs_lock); 03859 free(g); 03860 } else { 03861 ast_mutex_unlock(&g->msgs_lock); 03862 gprev = g; 03863 } 03864 } else { 03865 gprev = g; 03866 } 03867 g = g->next; 03868 } 03869 ast_mutex_unlock(&gatelock); 03870 lastrun = time(NULL); 03871 } 03872 /* Okay, now that we know what to do, release the network lock */ 03873 ast_mutex_unlock(&netlock); 03874 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03875 ast_mutex_unlock(&monlock); 03876 pthread_testcancel(); 03877 /* Wait for sched or io */ 03878 res = ast_sched_wait(sched); 03879 /* copied from chan_sip.c */ 03880 if ((res < 0) || (res > 1000)) { 03881 res = 1000; 03882 } 03883 res = ast_io_wait(io, res); 03884 ast_mutex_lock(&monlock); 03885 if (res >= 0) { 03886 ast_sched_runq(sched); 03887 } 03888 ast_mutex_unlock(&monlock); 03889 } 03890 /* Never reached */ 03891 return NULL; 03892 }
| static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub | |||
| ) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2697 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 destroy_endpoint(), handle_request(), handle_response(), and unalloc_sub().
02698 { 02699 struct mgcp_request *t, *q; 02700 02701 if (p) { 02702 ast_mutex_lock(&p->rqnt_queue_lock); 02703 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); 02704 p->rqnt_queue = NULL; 02705 ast_mutex_unlock(&p->rqnt_queue_lock); 02706 02707 ast_mutex_lock(&p->cmd_queue_lock); 02708 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); 02709 p->cmd_queue = NULL; 02710 ast_mutex_unlock(&p->cmd_queue_lock); 02711 02712 ast_mutex_lock(&p->sub->cx_queue_lock); 02713 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02714 p->sub->cx_queue = NULL; 02715 ast_mutex_unlock(&p->sub->cx_queue_lock); 02716 02717 ast_mutex_lock(&p->sub->next->cx_queue_lock); 02718 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); 02719 p->sub->next->cx_queue = NULL; 02720 ast_mutex_unlock(&p->sub->next->cx_queue_lock); 02721 } else if (sub) { 02722 ast_mutex_lock(&sub->cx_queue_lock); 02723 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02724 sub->cx_queue = NULL; 02725 ast_mutex_unlock(&sub->cx_queue_lock); 02726 } 02727 }
| static void dump_queue | ( | struct mgcp_gateway * | gw, | |
| struct mgcp_endpoint * | p | |||
| ) | [static] |
Definition at line 579 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_endpoint(), destroy_gateway(), and handle_request().
00580 { 00581 struct mgcp_message *cur, *q = NULL, *w, *prev; 00582 00583 ast_mutex_lock(&gw->msgs_lock); 00584 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00585 if (!p || cur->owner_ep == p) { 00586 if (prev) { 00587 prev->next = cur->next; 00588 } else { 00589 gw->msgs = cur->next; 00590 } 00591 00592 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 00593 gw->name, cur->seqno); 00594 00595 w = cur; 00596 if (q) { 00597 w->next = q; 00598 } else { 00599 w->next = NULL; 00600 } 00601 q = w; 00602 } 00603 } 00604 ast_mutex_unlock(&gw->msgs_lock); 00605 00606 while (q) { 00607 cur = q; 00608 q = q->next; 00609 ast_free(cur); 00610 } 00611 }
| static int find_and_retrans | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 3597 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().
03598 { 03599 int seqno=0; 03600 time_t now; 03601 struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL; 03602 time(&now); 03603 if (sscanf(req->identifier, "%30d", &seqno) != 1) { 03604 seqno = 0; 03605 } 03606 for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) { 03607 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03608 /* Delete this entry */ 03609 if (prev) 03610 prev->next = next; 03611 else 03612 sub->parent->parent->responses = next; 03613 ast_free(cur); 03614 } else { 03615 if (seqno == cur->seqno) 03616 answer = cur; 03617 prev = cur; 03618 } 03619 } 03620 if (answer) { 03621 resend_response(sub, answer); 03622 return 1; 03623 } 03624 return 0; 03625 }
| 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, read] |
find_command: (SC:) remove command transaction from queue
Definition at line 2731 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_debug, ast_inet_ntoa(), ast_mutex_lock, ast_mutex_unlock, mgcp_postrequest(), mgcp_request::next, and mgcp_endpoint::parent.
Referenced by agi_handle_command(), ast_agi_register(), handle_cli_agi_show(), and handle_response().
02733 { 02734 struct mgcp_request *prev, *req; 02735 02736 ast_mutex_lock(l); 02737 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02738 if (req->trid == ident) { 02739 /* remove from queue */ 02740 if (!prev) 02741 *queue = req->next; 02742 else 02743 prev->next = req->next; 02744 02745 /* send next pending command */ 02746 if (*queue) { 02747 ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02748 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02749 02750 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02751 } 02752 break; 02753 } 02754 } 02755 ast_mutex_unlock(l); 02756 return req; 02757 }
| static struct mgcp_gateway* find_realtime_gw | ( | char * | name, | |
| char * | at, | |||
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 1666 of file chan_mgcp.c.
References args, AST_APP_ARG, ast_check_realtime(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_load_realtime(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_variables_destroy(), build_gateway(), mgcp_gateway::endpoints, gateways, ast_variable::name, mgcp_endpoint::needaudit, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, mgcp_gateway::realtime, transmit_audit_endpoint(), 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, read] |
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, mgcp_endpoint::sub, and 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 handle_request(), and handle_response().
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 3270 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(), transmit_modify_request(), and transmit_notify_request().
Referenced by handle_request().
03271 { 03272 struct mgcp_endpoint *p = sub->parent; 03273 struct ast_channel *c; 03274 pthread_t t; 03275 03276 /* Off hook / answer */ 03277 if (sub->outgoing) { 03278 /* Answered */ 03279 if (sub->owner) { 03280 if (ast_bridged_channel(sub->owner)) 03281 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03282 sub->cxmode = MGCP_CX_SENDRECV; 03283 if (!sub->rtp) { 03284 start_rtp(sub); 03285 } else { 03286 transmit_modify_request(sub); 03287 } 03288 /*transmit_notify_request(sub, "aw");*/ 03289 transmit_notify_request(sub, ""); 03290 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 03291 } 03292 } else { 03293 /* Start switch */ 03294 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 03295 if (!sub->owner) { 03296 if (!sub->rtp) { 03297 start_rtp(sub); 03298 } else { 03299 transmit_modify_request(sub); 03300 } 03301 if (p->immediate) { 03302 /* The channel is immediately up. Start right away */ 03303 #ifdef DLINK_BUGGY_FIRMWARE 03304 transmit_notify_request(sub, "rt"); 03305 #else 03306 transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt"); 03307 #endif 03308 c = mgcp_new(sub, AST_STATE_RING, NULL); 03309 if (!c) { 03310 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 03311 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03312 ast_hangup(c); 03313 } 03314 } else { 03315 if (has_voicemail(p)) { 03316 transmit_notify_request(sub, "L/sl"); 03317 } else { 03318 transmit_notify_request(sub, "L/dl"); 03319 } 03320 c = mgcp_new(sub, AST_STATE_DOWN, NULL); 03321 if (c) { 03322 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { 03323 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 03324 ast_hangup(c); 03325 } 03326 } else { 03327 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 03328 } 03329 } 03330 } else { 03331 if (p->hookstate == MGCP_OFFHOOK) { 03332 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03333 } else { 03334 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03335 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 03336 } 03337 if (ast_bridged_channel(sub->owner)) 03338 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03339 sub->cxmode = MGCP_CX_SENDRECV; 03340 if (!sub->rtp) { 03341 start_rtp(sub); 03342 } else { 03343 transmit_modify_request(sub); 03344 } 03345 /*transmit_notify_request(sub, "aw");*/ 03346 transmit_notify_request(sub, ""); 03347 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03348 } 03349 } 03350 }
| static char* handle_mgcp_audit_endpoint | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1079 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock, ast_mutex_unlock, ast_strdupa, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_gateway::next, transmit_audit_endpoint(), and ast_cli_entry::usage.
01080 { 01081 struct mgcp_gateway *mg; 01082 struct mgcp_endpoint *me; 01083 int found = 0; 01084 char *ename,*gname, *c; 01085 01086 switch (cmd) { 01087 case CLI_INIT: 01088 e->command = "mgcp audit endpoint"; 01089 e->usage = 01090 "Usage: mgcp audit endpoint <endpointid>\n" 01091 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n" 01092 " mgcp debug MUST be on to see the results of this command.\n"; 01093 return NULL; 01094 case CLI_GENERATE: 01095 return NULL; 01096 } 01097 01098 if (!mgcpdebug) { 01099 return CLI_SHOWUSAGE; 01100 } 01101 if (a->argc != 4) 01102 return CLI_SHOWUSAGE; 01103 /* split the name into parts by null */ 01104 ename = ast_strdupa(a->argv[3]); 01105 for (gname = ename; *gname; gname++) { 01106 if (*gname == '@') { 01107 *gname = 0; 01108 gname++; 01109 break; 01110 } 01111 } 01112 if (gname[0] == '[') { 01113 gname++; 01114 } 01115 if ((c = strrchr(gname, ']'))) { 01116 *c = '\0'; 01117 } 01118 ast_mutex_lock(&gatelock); 01119 for (mg = gateways; mg; mg = mg->next) { 01120 if (!strcasecmp(mg->name, gname)) { 01121 for (me = mg->endpoints; me; me = me->next) { 01122 if (!strcasecmp(me->name, ename)) { 01123 found = 1; 01124 transmit_audit_endpoint(me); 01125 break; 01126 } 01127 } 01128 if (found) { 01129 break; 01130 } 01131 } 01132 } 01133 if (!found) { 01134 ast_cli(a->fd, " << Could not find endpoint >> "); 01135 } 01136 ast_mutex_unlock(&gatelock); 01137 return CLI_SUCCESS; 01138 }
| static char* handle_mgcp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1140 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, and ast_cli_entry::usage.
01141 { 01142 switch (cmd) { 01143 case CLI_INIT: 01144 e->command = "mgcp set debug {on|off}"; 01145 e->usage = 01146 "Usage: mgcp set debug {on|off}\n" 01147 " Enables/Disables dumping of MGCP packets for debugging purposes\n"; 01148 return NULL; 01149 case CLI_GENERATE: 01150 return NULL; 01151 } 01152 01153 if (a->argc != e->args) 01154 return CLI_SHOWUSAGE; 01155 01156 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 01157 mgcpdebug = 1; 01158 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01159 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01160 mgcpdebug = 0; 01161 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01162 } else { 01163 return CLI_SHOWUSAGE; 01164 } 01165 return CLI_SUCCESS; 01166 }
| static char* handle_mgcp_show_endpoints | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1037 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock, ast_mutex_unlock, mgcp_endpoint::chanvars, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, 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.
01038 { 01039 struct mgcp_gateway *mg; 01040 struct mgcp_endpoint *me; 01041 int hasendpoints = 0; 01042 struct ast_variable * v = NULL; 01043 01044 switch (cmd) { 01045 case CLI_INIT: 01046 e->command = "mgcp show endpoints"; 01047 e->usage = 01048 "Usage: mgcp show endpoints\n" 01049 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n"; 01050 return NULL; 01051 case CLI_GENERATE: 01052 return NULL; 01053 } 01054 01055 if (a->argc != 3) { 01056 return CLI_SHOWUSAGE; 01057 } 01058 ast_mutex_lock(&gatelock); 01059 for (mg = gateways; mg; mg = mg->next) { 01060 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"); 01061 for (me = mg->endpoints; me; me = me->next) { 01062 ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle"); 01063 if (me->chanvars) { 01064 ast_cli(a->fd, " Variables:\n"); 01065 for (v = me->chanvars ; v ; v = v->next) { 01066 ast_cli(a->fd, " %s = '%s'\n", v->name, v->value); 01067 } 01068 } 01069 hasendpoints = 1; 01070 } 01071 if (!hasendpoints) { 01072 ast_cli(a->fd, " << No Endpoints Defined >> "); 01073 } 01074 } 01075 ast_mutex_unlock(&gatelock); 01076 return CLI_SUCCESS; 01077 }
| static int handle_request | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req, | |||
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 3352 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, ast_frame::frametype, get_header(), handle_hd_hf(), has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::id, ast_frame_subclass::integer, 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, ast_frame::src, mgcp_endpoint::sub, ast_frame::subclass, 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().
03353 { 03354 char *ev, *s; 03355 struct ast_frame f = { 0, }; 03356 struct mgcp_endpoint *p = sub->parent; 03357 struct mgcp_gateway *g = NULL; 03358 int res; 03359 03360 ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03361 /* Clear out potential response */ 03362 if (!strcasecmp(req->verb, "RSIP")) { 03363 /* Test if this RSIP request is just a keepalive */ 03364 if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03365 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03366 transmit_response(sub, "200", req, "OK"); 03367 } else { 03368 dump_queue(p->parent, p); 03369 dump_cmd_queues(p, NULL); 03370 03371 if ((strcmp(p->name, p->parent->wcardep) != 0)) { 03372 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); 03373 } 03374 /* For RSIP on wildcard we reset all endpoints */ 03375 if (!strcmp(p->name, p->parent->wcardep)) { 03376 /* Reset all endpoints */ 03377 struct mgcp_endpoint *tmp_ep; 03378 03379 g = p->parent; 03380 for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) { 03381 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03382 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03383 struct mgcp_subchannel *tmp_sub, *first_sub; 03384 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03385 03386 first_sub = tmp_ep->sub; 03387 tmp_sub = tmp_ep->sub; 03388 while (tmp_sub) { 03389 mgcp_queue_hangup(tmp_sub); 03390 tmp_sub = tmp_sub->next; 03391 if (tmp_sub == first_sub) 03392 break; 03393 } 03394 } 03395 } 03396 } else if (sub->owner) { 03397 mgcp_queue_hangup(sub); 03398 } 03399 transmit_response(sub, "200", req, "OK"); 03400 /* We don't send NTFY or AUEP to wildcard ep */ 03401 if (strcmp(p->name, p->parent->wcardep) != 0) { 03402 transmit_notify_request(sub, ""); 03403 /* Audit endpoint. 03404 Idea is to prevent lost lines due to race conditions 03405 */ 03406 transmit_audit_endpoint(p); 03407 } 03408 } 03409 } else if (!strcasecmp(req->verb, "NTFY")) { 03410 /* Acknowledge and be sure we keep looking for the same things */ 03411 transmit_response(sub, "200", req, "OK"); 03412 /* Notified of an event */ 03413 ev = get_header(req, "O"); 03414 s = strchr(ev, '/'); 03415 if (s) ev = s + 1; 03416 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03417 /* Keep looking for events unless this was a hangup */ 03418 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03419 transmit_notify_request(sub, p->curtone); 03420 } 03421 if (!strcasecmp(ev, "hd")) { 03422 p->hookstate = MGCP_OFFHOOK; 03423 sub->cxmode = MGCP_CX_SENDRECV; 03424 03425 if (p) { 03426 /* When the endpoint have a Off hook transition we allways 03427 starts without any previous dtmfs */ 03428 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03429 } 03430 03431 handle_hd_hf(sub, ev); 03432 } else if (!strcasecmp(ev, "hf")) { 03433 /* We can assume we are offhook if we received a hookflash */ 03434 /* First let's just do call wait and ignore threeway */ 03435 /* We're currently in charge */ 03436 if (p->hookstate != MGCP_OFFHOOK) { 03437 /* Cisco c7940 sends hf even if the phone is onhook */ 03438 /* Thanks to point on IRC for pointing this out */ 03439 return -1; 03440 } 03441 /* do not let * conference two down channels */ 03442 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) 03443 return -1; 03444 03445 if (p->callwaiting || p->transfer || p->threewaycalling) { 03446 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03447 p->sub = p->sub->next; 03448 03449 /* transfer control to our next subchannel */ 03450 if (!sub->next->owner) { 03451 /* plave the first call on hold and start up a new call */ 03452 sub->cxmode = MGCP_CX_MUTE; 03453 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03454 transmit_modify_request(sub); 03455 if (sub->owner && ast_bridged_channel(sub->owner)) 03456 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03457 sub->next->cxmode = MGCP_CX_RECVONLY; 03458 handle_hd_hf(sub->next, ev); 03459 } else if (sub->owner && sub->next->owner) { 03460 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03461 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03462 /* We made both calls lets conferenct */ 03463 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", 03464 sub->id, sub->next->id, p->name, p->parent->name); 03465 sub->cxmode = MGCP_CX_CONF; 03466 sub->next->cxmode = MGCP_CX_CONF; 03467 if (ast_bridged_channel(sub->next->owner)) 03468 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03469 transmit_modify_request(sub); 03470 transmit_modify_request(sub->next); 03471 } else { 03472 /* Let's flipflop between calls */ 03473 /* XXX Need to check for state up ??? */ 03474 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03475 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03476 sub->id, sub->next->id, p->name, p->parent->name); 03477 sub->cxmode = MGCP_CX_MUTE; 03478 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03479 transmit_modify_request(sub); 03480 if (ast_bridged_channel(sub->owner)) 03481 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03482 03483 if (ast_bridged_channel(sub->next->owner)) 03484 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03485 03486 handle_hd_hf(sub->next, ev); 03487 } 03488 } else { 03489 /* We've most likely lost one of our calls find an active call and bring it up */ 03490 if (sub->owner) { 03491 p->sub = sub; 03492 } else if (sub->next->owner) { 03493 p->sub = sub->next; 03494 } else { 03495 /* We seem to have lost both our calls */ 03496 /* XXX - What do we do now? */ 03497 return -1; 03498 } 03499 if (ast_bridged_channel(p->sub->owner)) 03500 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03501 p->sub->cxmode = MGCP_CX_SENDRECV; 03502 transmit_modify_request(p->sub); 03503 } 03504 } else { 03505 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03506 p->name, p->parent->name); 03507 } 03508 } else if (!strcasecmp(ev, "hu")) { 03509 p->hookstate = MGCP_ONHOOK; 03510 sub->cxmode = MGCP_CX_RECVONLY; 03511 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03512 /* Do we need to send MDCX before a DLCX ? 03513 if (sub->rtp) { 03514 transmit_modify_request(sub); 03515 } 03516 */ 03517 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03518 /* We're allowed to transfer, we have two avtive calls and */ 03519 /* we made at least one of the calls. Let's try and transfer */ 03520 ast_mutex_lock(&p->sub->next->lock); 03521 res = attempt_transfer(p); 03522 if (res < 0) { 03523 if (p->sub->next->owner) { 03524 sub->next->alreadygone = 1; 03525 mgcp_queue_hangup(sub->next); 03526 } 03527 } else if (res) { 03528 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03529 ast_mutex_unlock(&p->sub->next->lock); 03530 return -1; 03531 } 03532 ast_mutex_unlock(&p->sub->next->lock); 03533 } else { 03534 /* Hangup the current call */ 03535 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03536 if (sub->owner) { 03537 sub->alreadygone = 1; 03538 mgcp_queue_hangup(sub); 03539 } else { 03540 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03541 p->name, p->parent->name, sub->id); 03542 /* Instruct the other side to remove the connection since it apparently * 03543 * still thinks the channel is active. * 03544 * For Cisco IAD2421 /BAK/ */ 03545 transmit_connection_del(sub); 03546 } 03547 } 03548 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03549 p->hidecallerid = 0; 03550 if (p->hascallwaiting && !p->callwaiting) { 03551 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03552 p->callwaiting = -1; 03553 } 03554 if (has_voicemail(p)) { 03555 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03556 transmit_notify_request(sub, "L/vmwi(+)"); 03557 } else { 03558 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03559 transmit_notify_request(sub, "L/vmwi(-)"); 03560 } 03561 } 03562 } else if ((strlen(ev) == 1) && 03563 (((ev[0] >= '0') && (ev[0] <= '9')) || 03564 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03565 (ev[0] == '*') || (ev[0] == '#'))) { 03566 if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) { 03567 f.frametype = AST_FRAME_DTMF; 03568 f.subclass.integer = ev[0]; 03569 f.src = "mgcp"; 03570 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03571 mgcp_queue_frame(sub, &f); 03572 ast_mutex_lock(&sub->next->lock); 03573 if (sub->next->owner) 03574 mgcp_queue_frame(sub->next, &f); 03575 ast_mutex_unlock(&sub->next->lock); 03576 if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) { 03577 memset(p->curtone, 0, sizeof(p->curtone)); 03578 } 03579 } else { 03580 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; 03581 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; 03582 } 03583 } else if (!strcasecmp(ev, "T")) { 03584 /* Digit timeout -- unimportant */ 03585 } else if (!strcasecmp(ev, "ping")) { 03586 /* ping -- unimportant */ 03587 } else { 03588 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03589 } 03590 } else { 03591 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03592 transmit_response(sub, "510", req, "Unknown verb"); 03593 } 03594 return 0; 03595 }
| 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 2760 of file chan_mgcp.c.
References ast_channel::_state, 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().
02762 { 02763 char *c; 02764 struct mgcp_request *req; 02765 struct mgcp_gateway *gw = p->parent; 02766 02767 if (result < 200) { 02768 /* provisional response */ 02769 return; 02770 } 02771 02772 if (p->slowsequence) 02773 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02774 else if (sub) 02775 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02776 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02777 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02778 02779 if (!req) { 02780 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", 02781 gw->name, ident); 02782 return; 02783 } 02784 02785 if (p && (result >= 400) && (result <= 599)) { 02786 switch (result) { 02787 case 401: 02788 p->hookstate = MGCP_OFFHOOK; 02789 break; 02790 case 402: 02791 p->hookstate = MGCP_ONHOOK; 02792 break; 02793 case 406: 02794 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02795 break; 02796 case 407: 02797 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02798 break; 02799 } 02800 if (sub) { 02801 if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) { 02802 ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result); 02803 transmit_connection_del(sub); 02804 } 02805 if (sub->owner) { 02806 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02807 result, p->name, p->parent->name, sub ? sub->id:-1); 02808 mgcp_queue_hangup(sub); 02809 } 02810 } else { 02811 if (p->sub->next->owner) { 02812 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02813 result, p->name, p->parent->name, sub ? sub->id:-1); 02814 mgcp_queue_hangup(p->sub); 02815 } 02816 02817 if (p->sub->owner) { 02818 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02819 result, p->name, p->parent->name, sub ? sub->id:-1); 02820 mgcp_queue_hangup(p->sub); 02821 } 02822 02823 dump_cmd_queues(p, NULL); 02824 } 02825 } 02826 02827 if (resp) { 02828 /* responseAck: */ 02829 if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) { 02830 if (sub) { 02831 transmit_response(sub, "000", resp, "OK"); 02832 if (sub->owner && sub->owner->_state == AST_STATE_RINGING) { 02833 ast_queue_control(sub->owner, AST_CONTROL_RINGING); 02834 } 02835 } 02836 } 02837 if (req->cmd == MGCP_CMD_CRCX) { 02838 if ((c = get_header(resp, "I"))) { 02839 if (!ast_strlen_zero(c) && sub) { 02840 /* if we are hanging up do not process this conn. */ 02841 if (sub->owner) { 02842 if (!ast_strlen_zero(sub->cxident)) { 02843 if (strcasecmp(c, sub->cxident)) { 02844 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02845 } 02846 } 02847 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02848 if (sub->tmpdest.sin_addr.s_addr) { 02849 transmit_modify_with_sdp(sub, NULL, 0); 02850 } 02851 } else { 02852 /* XXX delete this one 02853 callid and conn id may already be lost. 02854 so the following del conn may have a side effect of 02855 cleaning up the next subchannel */ 02856 transmit_connection_del(sub); 02857 } 02858 } 02859 } 02860 } 02861 02862 if (req->cmd == MGCP_CMD_AUEP) { 02863 /* check stale connection ids */ 02864 if ((c = get_header(resp, "I"))) { 02865 char *v, *n; 02866 int len; 02867 while ((v = get_csv(c, &len, &n))) { 02868 if (len) { 02869 if (strncasecmp(v, p->sub->cxident, len) && 02870 strncasecmp(v, p->sub->next->cxident, len)) { 02871 /* connection id not found. delete it */ 02872 char cxident[80] = ""; 02873 02874 if (len > (sizeof(cxident) - 1)) 02875 len = sizeof(cxident) - 1; 02876 ast_copy_string(cxident, v, len); 02877 ast_verb(3, "Non existing connection id %s on %s@%s \n", 02878 cxident, p->name, gw->name); 02879 transmit_connection_del_w_params(p, NULL, cxident); 02880 } 02881 } 02882 c = n; 02883 } 02884 } 02885 02886 /* Try to determine the hookstate returned from an audit endpoint command */ 02887 if ((c = get_header(resp, "ES"))) { 02888 if (!ast_strlen_zero(c)) { 02889 if (strstr(c, "hu")) { 02890 if (p->hookstate != MGCP_ONHOOK) { 02891 /* XXX cleanup if we think we are offhook XXX */ 02892 if ((p->sub->owner || p->sub->next->owner ) && 02893 p->hookstate == MGCP_OFFHOOK) 02894 mgcp_queue_hangup(sub); 02895 p->hookstate = MGCP_ONHOOK; 02896 02897 /* update the requested events according to the new hookstate */ 02898 transmit_notify_request(p->sub, ""); 02899 02900 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02901 } 02902 } else if (strstr(c, "hd")) { 02903 if (p->hookstate != MGCP_OFFHOOK) { 02904 p->hookstate = MGCP_OFFHOOK; 02905 02906 /* update the requested events according to the new hookstate */ 02907 transmit_notify_request(p->sub, ""); 02908 02909 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02910 } 02911 } 02912 } 02913 } 02914 } 02915 02916 if (resp && resp->lines) { 02917 /* do not process sdp if we are hanging up. this may be a late response */ 02918 if (sub && sub->owner) { 02919 if (!sub->rtp) 02920 start_rtp(sub); 02921 if (sub->rtp) 02922 process_sdp(sub, resp); 02923 } 02924 } 02925 } 02926 02927 ast_free(req); 02928 }
| static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 490 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().
00491 { 00492 int new_msgs; 00493 struct ast_event *event; 00494 char *mbox, *cntx; 00495 00496 cntx = mbox = ast_strdupa(p->mailbox); 00497 strsep(&cntx, "@"); 00498 if (ast_strlen_zero(cntx)) 00499 cntx = "default"; 00500 00501 event = ast_event_get_cached(AST_EVENT_MWI, 00502 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 00503 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 00504 AST_EVENT_IE_END); 00505 00506 if (event) { 00507 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 00508 ast_event_destroy(event); 00509 } else 00510 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 00511 00512 return new_msgs; 00513 }
| static int init_req | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_request * | req, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2112 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, and mgcp_endpoint::parent.
Referenced by initreqprep(), reqprep(), and transmit_register().
02113 { 02114 /* Initialize a response */ 02115 if (req->headers || req->len) { 02116 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02117 return -1; 02118 } 02119 req->header[req->headers] = req->data + req->len; 02120 /* check if we need brackets around the gw name */ 02121 if (p->parent->isnamedottedip) { 02122 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" : ""); 02123 } else { 02124 + 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" : ""); 02125 } 02126 req->len += strlen(req->header[req->headers]); 02127 if (req->headers < MGCP_MAX_HEADERS) { 02128 req->headers++; 02129 } else { 02130 ast_log(LOG_WARNING, "Out of header space\n"); 02131 } 02132 return 0; 02133 }
| static int init_resp | ( | struct mgcp_request * | req, | |
| char * | resp, | |||
| struct mgcp_request * | orig, | |||
| char * | resprest | |||
| ) | [static] |
Definition at line 2094 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().
02095 { 02096 /* Initialize a response */ 02097 if (req->headers || req->len) { 02098 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02099 return -1; 02100 } 02101 req->header[req->headers] = req->data + req->len; 02102 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 02103 req->len += strlen(req->header[req->headers]); 02104 if (req->headers < MGCP_MAX_HEADERS) { 02105 req->headers++; 02106 } else { 02107 ast_log(LOG_WARNING, "Out of header space\n"); 02108 } 02109 return 0; 02110 }
| static int load_module | ( | void | ) | [static] |
load_module: PBX load module - initialization ---
Definition at line 4797 of file chan_mgcp.c.
References ast_channel_register(), ast_cli_register_multiple(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_alloc(), ast_format_set(), AST_FORMAT_ULAW, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_sched_context_create(), ast_sched_context_destroy(), ast_channel_tech::capabilities, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, reload_config(), and restart_monitor().
04798 { 04799 struct ast_format tmpfmt; 04800 04801 if (!(global_capability = ast_format_cap_alloc())) { 04802 return AST_MODULE_LOAD_FAILURE; 04803 } 04804 if (!(mgcp_tech.capabilities = ast_format_cap_alloc())) { 04805 return AST_MODULE_LOAD_FAILURE; 04806 } 04807 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 04808 ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 04809 ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); 04810 if (!(sched = ast_sched_context_create())) { 04811 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 04812 return AST_MODULE_LOAD_FAILURE; 04813 } 04814 04815 if (!(io = io_context_create())) { 04816 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 04817 ast_sched_context_destroy(sched); 04818 return AST_MODULE_LOAD_FAILURE; 04819 } 04820 04821 if (reload_config(0)) 04822 return AST_MODULE_LOAD_DECLINE; 04823 04824 /* Make sure we can register our mgcp channel type */ 04825 if (ast_channel_register(&mgcp_tech)) { 04826 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); 04827 io_context_destroy(io); 04828 ast_sched_context_destroy(sched); 04829 return AST_MODULE_LOAD_FAILURE; 04830 } 04831 04832 ast_rtp_glue_register(&mgcp_rtp_glue); 04833 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04834 04835 /* And start the monitor for the first time */ 04836 restart_monitor(); 04837 04838 return AST_MODULE_LOAD_SUCCESS; 04839 }
| static int mgcp_alloc_pktcgate | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2423 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, and cops_gate::tech_pvt.
Referenced by start_rtp().
02424 { 02425 struct mgcp_endpoint *p = sub->parent; 02426 sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr), 02427 8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove); 02428 02429 if (!sub->gate) { 02430 return 0; 02431 } 02432 sub->gate->tech_pvt = sub; 02433 sub->gate->gate_open = &mgcp_pktcgate_open; 02434 return 1; 02435 }
| static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1175 of file chan_mgcp.c.
References ast_channel::_state, ast_channel_name(), 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, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), sub, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01176 { 01177 int res = 0; 01178 struct mgcp_subchannel *sub = ast->tech_pvt; 01179 struct mgcp_endpoint *p = sub->parent; 01180 01181 ast_mutex_lock(&sub->lock); 01182 sub->cxmode = MGCP_CX_SENDRECV; 01183 if (!sub->rtp) { 01184 start_rtp(sub); 01185 } else { 01186 transmit_modify_request(sub); 01187 } 01188 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", 01189 ast_channel_name(ast), p->name, p->parent->name, sub->id); 01190 if (ast->_state != AST_STATE_UP) { 01191 ast_setstate(ast, AST_STATE_UP); 01192 ast_debug(1, "mgcp_answer(%s)\n", ast_channel_name(ast)); 01193 transmit_notify_request(sub, ""); 01194 transmit_modify_request(sub); 01195 } 01196 ast_mutex_unlock(&sub->lock); 01197 return res; 01198 }
| static int mgcp_call | ( | struct ast_channel * | ast, | |
| const char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 835 of file chan_mgcp.c.
References ast_channel::_state, ast_channel_name(), 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, 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, sub, 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.
00836 { 00837 int res; 00838 struct mgcp_endpoint *p; 00839 struct mgcp_subchannel *sub; 00840 char tone[50] = ""; 00841 const char *distinctive_ring = NULL; 00842 struct varshead *headp; 00843 struct ast_var_t *current; 00844 00845 ast_debug(3, "MGCP mgcp_call(%s)\n", ast_channel_name(ast)); 00846 sub = ast->tech_pvt; 00847 p = sub->parent; 00848 headp = &ast->varshead; 00849 AST_LIST_TRAVERSE(headp,current,entries) { 00850 /* Check whether there is an ALERT_INFO variable */ 00851 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { 00852 distinctive_ring = ast_var_value(current); 00853 } 00854 } 00855 00856 ast_mutex_lock(&sub->lock); 00857 switch (p->hookstate) { 00858 case MGCP_OFFHOOK: 00859 if (!ast_strlen_zero(distinctive_ring)) { 00860 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); 00861 ast_debug(3, "MGCP distinctive callwait %s\n", tone); 00862 } else { 00863 ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone)); 00864 ast_debug(3, "MGCP normal callwait %s\n", tone); 00865 } 00866 break; 00867 case MGCP_ONHOOK: 00868 default: 00869 if (!ast_strlen_zero(distinctive_ring)) { 00870 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); 00871 ast_debug(3, "MGCP distinctive ring %s\n", tone); 00872 } else { 00873 ast_copy_string(tone, "L/rg", sizeof(tone)); 00874 ast_debug(3, "MGCP default ring\n"); 00875 } 00876 break; 00877 } 00878 00879 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00880 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast_channel_name(ast)); 00881 ast_mutex_unlock(&sub->lock); 00882 return -1; 00883 } 00884 00885 res = 0; 00886 sub->outgoing = 1; 00887 sub->cxmode = MGCP_CX_RECVONLY; 00888 ast_setstate(ast, AST_STATE_RINGING); 00889 if (p->type == TYPE_LINE) { 00890 if (!sub->rtp) { 00891 start_rtp(sub); 00892 } else { 00893 transmit_modify_request(sub); 00894 } 00895 00896 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00897 /* try to prevent a callwait from disturbing the other connection */ 00898 sub->next->cxmode = MGCP_CX_RECVONLY; 00899 transmit_modify_request(sub->next); 00900 } 00901 00902 transmit_notify_request_with_callerid(sub, tone, 00903 S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""), 00904 S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, "")); 00905 ast_setstate(ast, AST_STATE_RINGING); 00906 00907 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00908 /* Put the connection back in sendrecv */ 00909 sub->next->cxmode = MGCP_CX_SENDRECV; 00910 transmit_modify_request(sub->next); 00911 } 00912 } else { 00913 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); 00914 res = -1; 00915 } 00916 ast_mutex_unlock(&sub->lock); 00917 return res; 00918 }
| static int mgcp_devicestate | ( | const char * | data | ) | [static] |
mgcp_devicestate: channel callback for device status monitoring
| data | tech/resource name of MGCP device to query |
Definition at line 1360 of file chan_mgcp.c.
References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, mgcp_gateway::endpoints, gatelock, gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, and mgcp_gateway::next.
01361 { 01362 struct mgcp_gateway *g; 01363 struct mgcp_endpoint *e = NULL; 01364 char *tmp, *endpt, *gw; 01365 int ret = AST_DEVICE_INVALID; 01366 01367 endpt = ast_strdupa(data); 01368 if ((tmp = strchr(endpt, '@'))) { 01369 *tmp++ = '\0'; 01370 gw = tmp; 01371 } else 01372 goto error; 01373 01374 ast_mutex_lock(&gatelock); 01375 for (g = gateways; g; g = g->next) { 01376 if (strcasecmp(g->name, gw) == 0) { 01377 e = g->endpoints; 01378 break; 01379 } 01380 } 01381 01382 if (!e) 01383 goto error; 01384 01385 for (; e; e = e->next) { 01386 if (strcasecmp(e->name, endpt) == 0) { 01387 break; 01388 } 01389 } 01390 01391 if (!e) 01392 goto error; 01393 01394 /* 01395 * As long as the gateway/endpoint is valid, we'll 01396 * assume that the device is available and its state 01397 * can be tracked. 01398 */ 01399 ret = AST_DEVICE_UNKNOWN; 01400 01401 error: 01402 ast_mutex_unlock(&gatelock); 01403 return ret; 01404 }
| static int mgcp_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 1282 of file chan_mgcp.c.
References ast_channel_name(), ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_subchannel::owner, sub, and ast_channel::tech_pvt.
01283 { 01284 struct mgcp_subchannel *sub = newchan->tech_pvt; 01285 01286 ast_mutex_lock(&sub->lock); 01287 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan)); 01288 if (sub->owner != oldchan) { 01289 ast_mutex_unlock(&sub->lock); 01290 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01291 return -1; 01292 } 01293 sub->owner = newchan; 01294 ast_mutex_unlock(&sub->lock); 01295 return 0; 01296 }
| static void mgcp_get_codec | ( | struct ast_channel * | chan, | |
| struct ast_format_cap * | result | |||
| ) | [static] |
Definition at line 4444 of file chan_mgcp.c.
References ast_format_cap_copy(), mgcp_endpoint::cap, mgcp_subchannel::parent, sub, and ast_channel::tech_pvt.
04445 { 04446 struct mgcp_subchannel *sub = chan->tech_pvt; 04447 struct mgcp_endpoint *p = sub->parent; 04448 ast_format_cap_copy(result, p->cap); 04449 }
| static enum ast_rtp_glue_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp_instance ** | instance | |||
| ) | [static] |
Definition at line 4417 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, sub, and ast_channel::tech_pvt.
04418 { 04419 struct mgcp_subchannel *sub = NULL; 04420 04421 if (!(sub = chan->tech_pvt) || !(sub->rtp)) 04422 return AST_RTP_GLUE_RESULT_FORBID; 04423 04424 *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL; 04425 04426 if (sub->parent->directmedia) 04427 return AST_RTP_GLUE_RESULT_REMOTE; 04428 else 04429 return AST_RTP_GLUE_RESULT_LOCAL; 04430 }
| static int mgcp_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 920 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_name(), 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, 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, 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.
00921 { 00922 struct mgcp_subchannel *sub = ast->tech_pvt; 00923 struct mgcp_endpoint *p = sub->parent; 00924 struct ast_channel *bridged; 00925 00926 ast_debug(1, "mgcp_hangup(%s)\n", ast_channel_name(ast)); 00927 if (!ast->tech_pvt) { 00928 ast_debug(1, "Asked to hangup channel not connected\n"); 00929 return 0; 00930 } 00931 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) { 00932 ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n"); 00933 return 0; 00934 } 00935 ast_mutex_lock(&sub->lock); 00936 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast_channel_name(ast), p->name, p->parent->name); 00937 00938 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) { 00939 /* check whether other channel is active. */ 00940 if (!sub->next->owner) { 00941 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 00942 p->dtmfmode &= ~MGCP_DTMF_INBAND; 00943 } 00944 ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name); 00945 ast_dsp_free(p->dsp); 00946 p->dsp = NULL; 00947 } 00948 } 00949 00950 sub->owner = NULL; 00951 00952 /* for deleting gate */ 00953 if (p->pktcgatealloc && sub->gate) { 00954 sub->gate->gate_open = NULL; 00955 sub->gate->gate_remove = NULL; 00956 sub->gate->got_dq_gi = NULL; 00957 sub->gate->tech_pvt = NULL; 00958 if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) { 00959 ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL); 00960 } else { 00961 sub->gate->deltimer = time(NULL) + 5; 00962 } 00963 sub->gate = NULL; 00964 } 00965 00966 if (!ast_strlen_zero(sub->cxident)) { 00967 transmit_connection_del(sub); 00968 } 00969 sub->cxident[0] = '\0'; 00970 if ((sub == p->sub) && sub->next->owner) { 00971 if (p->hookstate == MGCP_OFFHOOK) { 00972 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00973 /* ncs fix! */ 00974 bridged = ast_bridged_channel(sub->next->owner); 00975 transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"), 00976 S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""), 00977 S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, "")); 00978 } 00979 } else { 00980 /* set our other connection as the primary and swith over to it */ 00981 p->sub = sub->next; 00982 p->sub->cxmode = MGCP_CX_RECVONLY; 00983 transmit_modify_request(p->sub); 00984 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00985 bridged = ast_bridged_channel(sub->next->owner); 00986 transmit_notify_request_with_callerid(p->sub, "L/rg", 00987 S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""), 00988 S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, "")); 00989 } 00990 } 00991 00992 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) { 00993 transmit_notify_request(sub, p->ncs ? "" : "L/v"); 00994 } else if (p->hookstate == MGCP_OFFHOOK) { 00995 transmit_notify_request(sub, "L/ro"); 00996 } else { 00997 transmit_notify_request(sub, ""); 00998 } 00999 01000 ast->tech_pvt = NULL; 01001 sub->alreadygone = 0; 01002 sub->outgoing = 0; 01003 sub->cxmode = MGCP_CX_INACTIVE; 01004 sub->callid[0] = '\0'; 01005 if (p) { 01006 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 01007 } 01008 /* Reset temporary destination */ 01009 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 01010 if (sub->rtp) { 01011 ast_rtp_instance_destroy(sub->rtp); 01012 sub->rtp = NULL; 01013 } 01014 01015 ast_module_unref(ast_module_info->self); 01016 01017 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) { 01018 p->hidecallerid = 0; 01019 if (p->hascallwaiting && !p->callwaiting) { 01020 ast_verb(3, "Enabling call waiting on %s\n", ast_channel_name(ast)); 01021 p->callwaiting = -1; 01022 } 01023 if (has_voicemail(p)) { 01024 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 01025 ast_channel_name(ast), p->name, p->parent->name); 01026 transmit_notify_request(sub, "L/vmwi(+)"); 01027 } else { 01028 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 01029 ast_channel_name(ast), p->name, p->parent->name); 01030 transmit_notify_request(sub, "L/vmwi(-)"); 01031 } 01032 } 01033 ast_mutex_unlock(&sub->lock); 01034 return 0; 01035 }
| static int mgcp_indicate | ( | struct ast_channel * | ast, | |
| int | ind, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 1438 of file chan_mgcp.c.
References ast_channel_name(), 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, mgcp_endpoint::ncs, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, sub, ast_channel::tech_pvt, transmit_modify_request(), and transmit_notify_request().
01439 { 01440 struct mgcp_subchannel *sub = ast->tech_pvt; 01441 int res = 0; 01442 01443 ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", 01444 ind, control2str(ind), ast_channel_name(ast)); 01445 ast_mutex_lock(&sub->lock); 01446 switch(ind) { 01447 case AST_CONTROL_RINGING: 01448 #ifdef DLINK_BUGGY_FIRMWARE 01449 transmit_notify_request(sub, "rt"); 01450 #else 01451 if (!sub->sdpsent) { /* will hide the inband progress!!! */ 01452 transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt"); 01453 } 01454 #endif 01455 break; 01456 case AST_CONTROL_BUSY: 01457 transmit_notify_request(sub, "L/bz"); 01458 break; 01459 case AST_CONTROL_INCOMPLETE: 01460 /* We do not currently support resetting of the Interdigit Timer, so treat 01461 * Incomplete control frames as a congestion response 01462 */ 01463 case AST_CONTROL_CONGESTION: 01464 transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg"); 01465 break; 01466 case AST_CONTROL_HOLD: 01467 ast_moh_start(ast, data, NULL); 01468 break; 01469 case AST_CONTROL_UNHOLD: 01470 ast_moh_stop(ast); 01471 break; 01472 case AST_CONTROL_SRCUPDATE: 01473 ast_rtp_instance_update_source(sub->rtp); 01474 break; 01475 case AST_CONTROL_SRCCHANGE: 01476 ast_rtp_instance_change_source(sub->rtp); 01477 break; 01478 case AST_CONTROL_PROGRESS: 01479 case AST_CONTROL_PROCEEDING: 01480 transmit_modify_request(sub); 01481 case -1: 01482 transmit_notify_request(sub, ""); 01483 break; 01484 default: 01485 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); 01486 res = -1; 01487 } 01488 ast_mutex_unlock(&sub->lock); 01489 return res; 01490 }
| static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, | |
| int | state, | |||
| const char * | linkedid | |||
| ) | [static, read] |
Definition at line 1492 of file chan_mgcp.c.
References mgcp_endpoint::accountcode, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc, ast_channel_name(), ast_channel_set_fd(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), ast_format_cap_copy(), ast_format_cap_is_empty(), ast_format_copy(), 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_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, mgcp_endpoint::cap, mgcp_endpoint::chanvars, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_variable::name, mgcp_gateway::name, mgcp_endpoint::name, ast_variable::next, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, mgcp_subchannel::rtp, and ast_variable::value.
Referenced by handle_hd_hf(), and mgcp_request().
01493 { 01494 struct ast_channel *tmp; 01495 struct ast_variable *v = NULL; 01496 struct mgcp_endpoint *i = sub->parent; 01497 struct ast_format tmpfmt; 01498 01499 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); 01500 if (tmp) { 01501 tmp->tech = &mgcp_tech; 01502 ast_format_cap_copy(tmp->nativeformats, i->cap); 01503 if (ast_format_cap_is_empty(tmp->nativeformats)) { 01504 ast_format_cap_copy(tmp->nativeformats, global_capability); 01505 } 01506 if (sub->rtp) { 01507 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); 01508 } 01509 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { 01510 i->dsp = ast_dsp_new(); 01511 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); 01512 /* this is to prevent clipping of dtmf tones during dsp processing */ 01513 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); 01514 } else { 01515 i->dsp = NULL; 01516 } 01517 if (state == AST_STATE_RING) 01518 tmp->rings = 1; 01519 01520 ast_best_codec(tmp->nativeformats, &tmpfmt); 01521 ast_format_copy(&tmp->writeformat, &tmpfmt); 01522 ast_format_copy(&tmp->rawwriteformat, &tmpfmt); 01523 ast_format_copy(&tmp->readformat, &tmpfmt); 01524 ast_format_copy(&tmp->rawreadformat, &tmpfmt); 01525 tmp->tech_pvt = sub; 01526 if (!ast_strlen_zero(i->language)) 01527 ast_channel_language_set(tmp, i->language); 01528 if (!ast_strlen_zero(i->accountcode)) 01529 ast_channel_accountcode_set(tmp, 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_channel_call_forward_set(tmp, 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", ast_channel_name(tmp)); 01564 ast_hangup(tmp); 01565 tmp = NULL; 01566 } 01567 } 01568 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", 01569 ast_channel_name(tmp), 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 2410 of file chan_mgcp.c.
References ast_debug, ast_mutex_lock, ast_mutex_unlock, cops_gate::gateid, mgcp_subchannel::lock, mgcp_subchannel::sdpsent, sub, cops_gate::tech_pvt, and transmit_modify_with_sdp().
Referenced by mgcp_alloc_pktcgate().
02411 { 02412 struct mgcp_subchannel *sub = gate->tech_pvt; 02413 if (!sub) { 02414 return 1; 02415 } 02416 ast_mutex_lock(&sub->lock); 02417 ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid); 02418 if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0); 02419 ast_mutex_unlock(&sub->lock); 02420 return 1; 02421 }
| static int mgcp_pktcgate_remove | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2387 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, sub, and cops_gate::tech_pvt.
Referenced by mgcp_alloc_pktcgate().
02388 { 02389 struct mgcp_subchannel *sub = gate->tech_pvt; 02390 02391 if (!sub) { 02392 return 1; 02393 } 02394 02395 ast_mutex_lock(&sub->lock); 02396 ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid); 02397 if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) { 02398 sub->gate = NULL; 02399 if (sub->owner) { 02400 ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL); 02401 ast_channel_unlock(sub->owner); 02402 } 02403 } else { 02404 sub->gate = NULL; 02405 } 02406 ast_mutex_unlock(&sub->lock); 02407 return 1; 02408 }
| static int mgcp_postrequest | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub, | |||
| char * | data, | |||
| int | len, | |||
| unsigned int | seqno | |||
| ) | [static] |
Definition at line 708 of file chan_mgcp.c.
References __mgcp_xmit(), ast_free, ast_malloc, ast_mutex_lock, ast_mutex_unlock, ast_sched_add(), ast_tvnow(), mgcp_message::buf, DEFAULT_RETRANS, mgcp_message::expire, mgcp_message::len, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_message::next, mgcp_message::owner_ep, mgcp_message::owner_sub, mgcp_endpoint::parent, mgcp_message::retrans, retrans_pkt(), mgcp_gateway::retransid, and mgcp_message::seqno.
Referenced by find_command(), and send_request().
00710 { 00711 struct mgcp_message *msg; 00712 struct mgcp_message *cur; 00713 struct mgcp_gateway *gw; 00714 struct timeval now; 00715 00716 if (!(msg = ast_malloc(sizeof(*msg) + len))) { 00717 return -1; 00718 } 00719 if (!(gw = ((p && p->parent) ? p->parent : NULL))) { 00720 ast_free(msg); 00721 return -1; 00722 } 00723 00724 msg->owner_sub = sub; 00725 msg->owner_ep = p; 00726 msg->seqno = seqno; 00727 msg->next = NULL; 00728 msg->len = len; 00729 msg->retrans = 0; 00730 memcpy(msg->buf, data, msg->len); 00731 00732 ast_mutex_lock(&gw->msgs_lock); 00733 for (cur = gw->msgs; cur && cur->next; cur = cur->next); 00734 if (cur) { 00735 cur->next = msg; 00736 } else { 00737 gw->msgs = msg; 00738 } 00739 00740 now = ast_tvnow(); 00741 msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS; 00742 00743 if (gw->retransid == -1) 00744 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw); 00745 ast_mutex_unlock(&gw->msgs_lock); 00746 __mgcp_xmit(gw, msg->buf, msg->len); 00747 /* XXX Should schedule retransmission XXX */ 00748 return 0; 00749 }
| static int mgcp_prune_realtime_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 3718 of file chan_mgcp.c.
References ast_debug, ast_mutex_destroy, 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, free, mgcp_subchannel::gate, mgcp_gateway::ha, mgcp_subchannel::lock, mgcp_endpoint::lock, MAX_SUBS, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::realtime, mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::sub, and sub.
Referenced by do_monitor().
03719 { 03720 struct mgcp_endpoint *enext, *e; 03721 struct mgcp_subchannel *s, *sub; 03722 int i, prune = 1; 03723 03724 if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) { 03725 ast_mutex_unlock(&g->msgs_lock); 03726 return 0; 03727 } 03728 03729 for (e = g->endpoints; e; e = e->next) { 03730 ast_mutex_lock(&e->lock); 03731 if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) { 03732 prune = 0; 03733 } else if (e->rqnt_queue || e->cmd_queue) { 03734 prune = 0; 03735 } 03736 s = e->sub; 03737 for (i = 0; (i < MAX_SUBS) && s; i++) { 03738 ast_mutex_lock(&s->lock); 03739 if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) { 03740 prune = 0; 03741 } else if (s->cx_queue) { 03742 prune = 0; 03743 } 03744 s = s->next; 03745 } 03746 } 03747 03748 for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) { 03749 for (i = 0; (i < MAX_SUBS) && sub; i++) { 03750 s = sub; 03751 sub = sub->next; 03752 ast_mutex_unlock(&s->lock); 03753 ast_mutex_unlock(&s->cx_queue_lock); 03754 if (prune) { 03755 ast_mutex_destroy(&s->lock); 03756 ast_mutex_destroy(&s->cx_queue_lock); 03757 free(s); 03758 } 03759 } 03760 ast_mutex_unlock(&e->lock); 03761 ast_mutex_unlock(&e->rqnt_queue_lock); 03762 ast_mutex_unlock(&e->cmd_queue_lock); 03763 if (prune) { 03764 ast_mutex_destroy(&e->lock); 03765 ast_mutex_destroy(&e->rqnt_queue_lock); 03766 ast_mutex_destroy(&e->cmd_queue_lock); 03767 free(e); 03768 } 03769 } 03770 if (prune) { 03771 ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name); 03772 } 03773 return prune; 03774 }
| static void mgcp_queue_control | ( | struct mgcp_subchannel * | sub, | |
| int | control | |||
| ) | [static] |
Definition at line 647 of file chan_mgcp.c.
References AST_FRAME_CONTROL, and mgcp_queue_frame().
Referenced by handle_hd_hf().
00648 { 00649 struct ast_frame f = { AST_FRAME_CONTROL, { control } }; 00650 return mgcp_queue_frame(sub, &f); 00651 }
| static void mgcp_queue_frame | ( | struct mgcp_subchannel * | sub, | |
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 613 of file chan_mgcp.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, mgcp_subchannel::lock, and mgcp_subchannel::owner.
Referenced by handle_request(), and mgcp_queue_control().
00614 { 00615 for (;;) { 00616 if (sub->owner) { 00617 if (!ast_channel_trylock(sub->owner)) { 00618 ast_queue_frame(sub->owner, f); 00619 ast_channel_unlock(sub->owner); 00620 break; 00621 } else { 00622 DEADLOCK_AVOIDANCE(&sub->lock); 00623 } 00624 } else { 00625 break; 00626 } 00627 } 00628 }
| static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 630 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(), destroy_endpoint(), handle_request(), handle_response(), and start_rtp().
00631 { 00632 for (;;) { 00633 if (sub->owner) { 00634 if (!ast_channel_trylock(sub->owner)) { 00635 ast_queue_hangup(sub->owner); 00636 ast_channel_unlock(sub->owner); 00637 break; 00638 } else { 00639 DEADLOCK_AVOIDANCE(&sub->lock); 00640 } 00641 } else { 00642 break; 00643 } 00644 } 00645 }
| static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1231 of file chan_mgcp.c.
References ast_mutex_lock, ast_mutex_unlock, f, mgcp_subchannel::lock, mgcp_rtp_read(), sub, and ast_channel::tech_pvt.
01232 { 01233 struct ast_frame *f; 01234 struct mgcp_subchannel *sub = ast->tech_pvt; 01235 ast_mutex_lock(&sub->lock); 01236 f = mgcp_rtp_read(sub); 01237 ast_mutex_unlock(&sub->lock); 01238 return f; 01239 }
| static char * mgcp_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4841 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, restart_monitor(), and ast_cli_entry::usage.
Referenced by reload(), and unload_module().
04842 { 04843 static int deprecated = 0; 04844 04845 if (e) { 04846 switch (cmd) { 04847 case CLI_INIT: 04848 e->command = "mgcp reload"; 04849 e->usage = 04850 "Usage: mgcp reload\n" 04851 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; 04852 return NULL; 04853 case CLI_GENERATE: 04854 return NULL; 04855 } 04856 } 04857 04858 if (!deprecated && a && a->argc > 0) { 04859 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); 04860 deprecated = 1; 04861 } 04862 04863 ast_mutex_lock(&mgcp_reload_lock); 04864 if (mgcp_reloading) { 04865 ast_verbose("Previous mgcp reload not yet done\n"); 04866 } else { 04867 mgcp_reloading = 1; 04868 } 04869 ast_mutex_unlock(&mgcp_reload_lock); 04870 restart_monitor(); 04871 return CLI_SUCCESS; 04872 }
| static struct ast_channel * mgcp_request | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const struct ast_channel * | requestor, | |||
| const char * | dest, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 3923 of file chan_mgcp.c.
References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_channel_linkedid(), ast_copy_string(), ast_format_cap_has_joint(), ast_getformatname_multiple(), ast_log(), ast_mutex_unlock, AST_STATE_DOWN, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, mgcp_endpoint::dnd, find_subchannel_and_lock(), has_voicemail(), mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), MGCP_ONHOOK, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), sub, and transmit_notify_request().
03924 { 03925 struct mgcp_subchannel *sub; 03926 struct ast_channel *tmpc = NULL; 03927 char tmp[256]; 03928 03929 if (!(ast_format_cap_has_joint(cap, global_capability))) { 03930 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); 03931 /*return NULL;*/ 03932 } 03933 ast_copy_string(tmp, dest, sizeof(tmp)); 03934 if (ast_strlen_zero(tmp)) { 03935 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); 03936 return NULL; 03937 } 03938 if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) { 03939 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); 03940 *cause = AST_CAUSE_UNREGISTERED; 03941 return NULL; 03942 } 03943 03944 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); 03945 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 03946 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); 03947 /* Must be busy */ 03948 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || 03949 ((!sub->parent->callwaiting) && (sub->owner)) || 03950 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { 03951 if (sub->parent->hookstate == MGCP_ONHOOK) { 03952 if (has_voicemail(sub->parent)) { 03953 transmit_notify_request(sub,"L/vmwi(+)"); 03954 } else { 03955 transmit_notify_request(sub,"L/vmwi(-)"); 03956 } 03957 } 03958 *cause = AST_CAUSE_BUSY; 03959 ast_mutex_unlock(&sub->lock); 03960 return NULL; 03961 } 03962 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL); 03963 ast_mutex_unlock(&sub->lock); 03964 if (!tmpc) 03965 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); 03966 restart_monitor(); 03967 return tmpc; 03968 }
| static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static, read] |
Definition at line 1200 of file chan_mgcp.c.
References ast_debug, ast_dsp_process(), ast_format_cap_iscompatible(), ast_format_cap_set(), 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, ast_frame_subclass::format, ast_frame::frametype, LOG_NOTICE, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, ast_frame::subclass, and ast_channel::writeformat.
Referenced by mgcp_read().
01201 { 01202 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ 01203 struct ast_frame *f; 01204 01205 f = ast_rtp_instance_read(sub->rtp, 0); 01206 /* Don't send RFC2833 if we're not supposed to */ 01207 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) 01208 return &ast_null_frame; 01209 if (sub->owner) { 01210 /* We already hold the channel lock */ 01211 if (f->frametype == AST_FRAME_VOICE) { 01212 if (!ast_format_cap_iscompatible(sub->owner->nativeformats, &f->subclass.format)) { 01213 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); 01214 ast_format_cap_set(sub->owner->nativeformats, &f->subclass.format); 01215 ast_set_read_format(sub->owner, &sub->owner->readformat); 01216 ast_set_write_format(sub->owner, &sub->owner->writeformat); 01217 } 01218 /* Courtesy fearnor aka alex@pilosoft.com */ 01219 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { 01220 #if 0 01221 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); 01222 #endif 01223 f = ast_dsp_process(sub->owner, sub->parent->dsp, f); 01224 } 01225 } 01226 } 01227 return f; 01228 }
| static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1298 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, sub, and ast_channel::tech_pvt.
01299 { 01300 struct mgcp_subchannel *sub = ast->tech_pvt; 01301 struct mgcp_endpoint *p = sub->parent; 01302 int res = 0; 01303 01304 ast_mutex_lock(&sub->lock); 01305 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01306 ast_debug(1, "Sending DTMF using inband/hybrid\n"); 01307 res = -1; /* Let asterisk play inband indications */ 01308 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01309 ast_debug(1, "Sending DTMF using RFC2833"); 01310 ast_rtp_instance_dtmf_begin(sub->rtp, digit); 01311 } else { 01312 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01313 } 01314 ast_mutex_unlock(&sub->lock); 01315 01316 return res; 01317 }
| static int mgcp_senddigit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1319 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, sub, ast_channel::tech_pvt, and transmit_notify_request().
01320 { 01321 struct mgcp_subchannel *sub = ast->tech_pvt; 01322 struct mgcp_endpoint *p = sub->parent; 01323 int res = 0; 01324 char tmp[4]; 01325 01326 ast_mutex_lock(&sub->lock); 01327 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01328 ast_debug(1, "Stopping DTMF using inband/hybrid\n"); 01329 res = -1; /* Tell Asterisk to stop inband indications */ 01330 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01331 ast_debug(1, "Stopping DTMF using RFC2833\n"); 01332 if (sub->parent->ncs) { 01333 tmp[0] = digit; 01334 tmp[1] = '\0'; 01335 } else { 01336 tmp[0] = 'D'; 01337 tmp[1] = '/'; 01338 tmp[2] = digit; 01339 tmp[3] = '\0'; 01340 } 01341 transmit_notify_request(sub, tmp); 01342 ast_rtp_instance_dtmf_end(sub->rtp, digit); 01343 } else { 01344 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01345 } 01346 ast_mutex_unlock(&sub->lock); 01347 01348 return res; 01349 }
| 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, | |||
| const struct ast_format_cap * | cap, | |||
| int | nat_active | |||
| ) | [static] |
Definition at line 4432 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, sub, ast_channel::tech_pvt, and transmit_modify_with_sdp().
04433 { 04434 /* XXX Is there such thing as video support with MGCP? XXX */ 04435 struct mgcp_subchannel *sub; 04436 sub = chan->tech_pvt; 04437 if (sub && !sub->alreadygone) { 04438 transmit_modify_with_sdp(sub, rtp, cap); 04439 return 0; 04440 } 04441 return -1; 04442 }
| static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2963 of file chan_mgcp.c.
References ast_party_caller::ani, ast_bridged_channel(), ast_canmatch_extension(), ast_channel_language(), ast_channel_name(), 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, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_party_caller::id, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, 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, sub, ast_channel::tech_pvt, transmit_notify_request(), and ast_party_number::valid.
Referenced by handle_hd_hf().
02964 { 02965 struct ast_channel *chan = data; 02966 struct mgcp_subchannel *sub = chan->tech_pvt; 02967 struct mgcp_endpoint *p = sub->parent; 02968 /* char exten[AST_MAX_EXTENSION] = ""; */ 02969 int len = 0; 02970 int timeout = firstdigittimeout; 02971 int res= 0; 02972 int getforward = 0; 02973 int loop_pause = 100; 02974 02975 len = strlen(p->dtmf_buf); 02976 02977 while (len < AST_MAX_EXTENSION - 1) { 02978 ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name); 02979 res = 1; /* Assume that we will get a digit */ 02980 while (strlen(p->dtmf_buf) == len) { 02981 ast_safe_sleep(chan, loop_pause); 02982 timeout -= loop_pause; 02983 if (timeout <= 0){ 02984 res = 0; 02985 break; 02986 } 02987 res = 1; 02988 } 02989 02990 timeout = 0; 02991 len = strlen(p->dtmf_buf); 02992 02993 if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) { 02994 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 02995 ast_indicate(chan, -1); 02996 } else { 02997 /* XXX Redundant? We should already be playing dialtone */ 02998 /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 02999 transmit_notify_request(sub, "L/dl"); 03000 } 03001 if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 03002 if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { 03003 if (getforward) { 03004 /* Record this as the forwarding extension */ 03005 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 03006 ast_verb(3, "Setting call forward to '%s' on channel %s\n", 03007 p->call_forward, ast_channel_name(chan)); 03008 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03009 transmit_notify_request(sub, "L/sl"); 03010 if (res) 03011 break; 03012 usleep(500000); 03013 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03014 ast_indicate(chan, -1); 03015 sleep(1); 03016 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03017 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 03018 transmit_notify_request(sub, "L/dl"); 03019 len = 0; 03020 getforward = 0; 03021 } else { 03022 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03023 ast_indicate(chan, -1); 03024 ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten)); 03025 chan->dialed.number.str = ast_strdup(p->dtmf_buf); 03026 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03027 ast_set_callerid(chan, 03028 p->hidecallerid ? "" : p->cid_num, 03029 p->hidecallerid ? "" : p->cid_name, 03030 chan->caller.ani.number.valid ? NULL : p->cid_num); 03031 ast_setstate(chan, AST_STATE_RING); 03032 /*dahdi_enable_ec(p);*/ 03033 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 03034 p->dtmfmode |= MGCP_DTMF_INBAND; 03035 ast_indicate(chan, -1); 03036 } 03037 res = ast_pbx_run(chan); 03038 if (res) { 03039 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 03040 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03041 /*transmit_notify_request(p, "nbz", 1);*/ 03042 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03043 } 03044 return NULL; 03045 } 03046 } else { 03047 /* It's a match, but they just typed a digit, and there is an ambiguous match, 03048 so just set the timeout to matchdigittimeout and wait some more */ 03049 timeout = matchdigittimeout; 03050 } 03051 } else if (res == 0) { 03052 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 03053 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03054 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03055 /*dahdi_wait_event(p->subs[index].zfd);*/ 03056 ast_hangup(chan); 03057 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03058 return NULL; 03059 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { 03060 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan)); 03061 /* Disable call waiting if enabled */ 03062 p->callwaiting = 0; 03063 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03064 transmit_notify_request(sub, "L/sl"); 03065 len = 0; 03066 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03067 timeout = firstdigittimeout; 03068 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { 03069 /* Scan all channels and see if any there 03070 * ringing channqels with that have call groups 03071 * that equal this channels pickup group 03072 */ 03073 if (ast_pickup_call(chan)) { 03074 ast_log(LOG_WARNING, "No call pickup possible...\n"); 03075 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03076 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03077 } 03078 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03079 ast_hangup(chan); 03080 return NULL; 03081 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { 03082 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan)); 03083 /* Disable Caller*ID if enabled */ 03084 p->hidecallerid = 1; 03085 ast_set_callerid(chan, "", "", NULL); 03086 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03087 transmit_notify_request(sub, "L/sl"); 03088 len = 0; 03089 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03090 timeout = firstdigittimeout; 03091 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { 03092 res = 0; 03093 if (!ast_strlen_zero(p->lastcallerid)) { 03094 res = ast_say_digit_str(chan, p->lastcallerid, "", ast_channel_language(chan)); 03095 } 03096 if (!res) 03097 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03098 transmit_notify_request(sub, "L/sl"); 03099 break; 03100 } else if (!strcmp(p->dtmf_buf, "*78")) { 03101 /* Do not disturb */ 03102 ast_verb(3, "Enabled DND on channel %s\n", ast_channel_name(chan)); 03103 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03104 transmit_notify_request(sub, "L/sl"); 03105 p->dnd = 1; 03106 getforward = 0; 03107 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03108 len = 0; 03109 } else if (!strcmp(p->dtmf_buf, "*79")) { 03110 /* Do not disturb */ 03111 ast_verb(3, "Disabled DND on channel %s\n", ast_channel_name(chan)); 03112 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03113 transmit_notify_request(sub, "L/sl"); 03114 p->dnd = 0; 03115 getforward = 0; 03116 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03117 len = 0; 03118 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { 03119 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03120 transmit_notify_request(sub, "L/sl"); 03121 getforward = 1; 03122 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03123 len = 0; 03124 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { 03125 ast_verb(3, "Cancelling call forwarding on channel %s\n", ast_channel_name(chan)); 03126 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03127 transmit_notify_request(sub, "L/sl"); 03128 memset(p->call_forward, 0, sizeof(p->call_forward)); 03129 getforward = 0; 03130 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03131 len = 0; 03132 } else if (ast_parking_ext_valid(p->dtmf_buf, chan, chan->context) && 03133 sub->next->owner && ast_bridged_channel(sub->next->owner)) { 03134 /* This is a three way call, the main call being a real channel, 03135 and we're parking the first call. */ 03136 ast_masq_park_call_exten(ast_bridged_channel(sub->next->owner), chan, 03137 p->dtmf_buf, chan->context, 0, NULL); 03138 ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan)); 03139 break; 03140 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { 03141 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); 03142 res = ast_db_put("blacklist", p->lastcallerid, "1"); 03143 if (!res) { 03144 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03145 transmit_notify_request(sub, "L/sl"); 03146 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03147 len = 0; 03148 } 03149 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { 03150 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan)); 03151 /* Enable Caller*ID if enabled */ 03152 p->hidecallerid = 0; 03153 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 03154 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03155 transmit_notify_request(sub, "L/sl"); 03156 len = 0; 03157 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03158 timeout = firstdigittimeout; 03159 } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, 03160 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) 03161 && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 03162 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, 03163 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"), 03164 chan->context); 03165 break; 03166 } 03167 if (!timeout) 03168 timeout = gendigittimeout; 03169 if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf)) 03170 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03171 ast_indicate(chan, -1); 03172 } 03173 #if 0 03174 for (;;) { 03175 res = ast_waitfordigit(chan, to); 03176 if (!res) { 03177 ast_debug(1, "Timeout...\n"); 03178 break; 03179 } 03180 if (res < 0) { 03181 ast_debug(1, "Got hangup...\n"); 03182 ast_hangup(chan); 03183 break; 03184 } 03185 exten[pos++] = res; 03186 if (!ast_ignore_pattern(chan->context, exten)) 03187 ast_indicate(chan, -1); 03188 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { 03189 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 03190 to = 3000; 03191 else 03192 to = 8000; 03193 } else 03194 break; 03195 } 03196 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { 03197 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); 03198 if (!p->rtp) { 03199 start_rtp(p); 03200 } 03201 ast_setstate(chan, AST_STATE_RING); 03202 chan->rings = 1; 03203 if (ast_pbx_run(chan)) { 03204 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); 03205 } else { 03206 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03207 return NULL; 03208 } 03209 } 03210 #endif 03211 ast_hangup(chan); 03212 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03213 return NULL; 03214 }
| static int mgcp_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 1241 of file chan_mgcp.c.
References ast_debug, ast_format_cap_iscompatible(), 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::format, 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, sub, ast_frame::subclass, ast_channel::tech_pvt, transmit_modify_with_sdp(), and ast_channel::writeformat.
01242 { 01243 struct mgcp_subchannel *sub = ast->tech_pvt; 01244 int res = 0; 01245 char buf[256]; 01246 01247 if (frame->frametype != AST_FRAME_VOICE) { 01248 if (frame->frametype == AST_FRAME_IMAGE) 01249 return 0; 01250 else { 01251 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); 01252 return 0; 01253 } 01254 } else { 01255 if (!(ast_format_cap_iscompatible(ast->nativeformats, &frame->subclass.format))) { 01256 ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01257 ast_getformatname(&frame->subclass.format), 01258 ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats), 01259 ast_getformatname(&ast->readformat), 01260 ast_getformatname(&ast->writeformat)); 01261 /* return -1; */ 01262 } 01263 } 01264 if (sub) { 01265 ast_mutex_lock(&sub->lock); 01266 if (!sub->sdpsent && sub->gate) { 01267 if (sub->gate->state == GATE_ALLOCATED) { 01268 ast_debug(1, "GATE ALLOCATED, sending sdp\n"); 01269 transmit_modify_with_sdp(sub, NULL, 0); 01270 } 01271 } 01272 if ((sub->parent->sub == sub) || !sub->parent->singlepath) { 01273 if (sub->rtp) { 01274 res = ast_rtp_instance_write(sub->rtp, frame); 01275 } 01276 } 01277 ast_mutex_unlock(&sub->lock); 01278 } 01279 return res; 01280 }
| static int mgcpsock_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | ignore | |||
| ) | [static] |
Definition at line 3627 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(), mgcp_request::data, mgcp_request::endpoint, errno, find_and_retrans(), find_subchannel_and_lock(), handle_request(), handle_response(), mgcp_request::headers, mgcp_request::identifier, mgcp_request::len, len(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, 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, mgcp_message::seqno, sub, mgcp_request::verb, and mgcp_request::version.
Referenced by do_monitor().
03628 { 03629 struct mgcp_request req; 03630 struct sockaddr_in sin; 03631 struct mgcp_subchannel *sub; 03632 int res; 03633 socklen_t len; 03634 int result; 03635 int ident; 03636 len = sizeof(sin); 03637 memset(&req, 0, sizeof(req)); 03638 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 03639 if (res < 0) { 03640 if (errno != ECONNREFUSED) 03641 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 03642 return 1; 03643 } 03644 req.data[res] = '\0'; 03645 req.len = res; 03646 ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 03647 parse(&req); 03648 if (req.headers < 1) { 03649 /* Must have at least one header */ 03650 return 1; 03651 } 03652 if (ast_strlen_zero(req.identifier)) { 03653 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); 03654 return 1; 03655 } 03656 03657 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { 03658 if (result < 200) { 03659 ast_debug(1, "Ignoring provisional response on transaction %d\n", ident); 03660 return 1; 03661 } 03662 /* Try to find who this message is for, if it's important */ 03663 sub = find_subchannel_and_lock(NULL, ident, &sin); 03664 if (sub) { 03665 struct mgcp_gateway *gw = sub->parent->parent; 03666 struct mgcp_message *cur, *prev; 03667 03668 ast_mutex_unlock(&sub->lock); 03669 ast_mutex_lock(&gw->msgs_lock); 03670 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 03671 if (cur->seqno == ident) { 03672 ast_debug(1, "Got response back on transaction %d\n", ident); 03673 if (prev) 03674 prev->next = cur->next; 03675 else 03676 gw->msgs = cur->next; 03677 break; 03678 } 03679 } 03680 03681 /* stop retrans timer if the queue is empty */ 03682 if (!gw->msgs) { 03683 AST_SCHED_DEL(sched, gw->retransid); 03684 } 03685 03686 ast_mutex_unlock(&gw->msgs_lock); 03687 if (cur) { 03688 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); 03689 ast_free(cur); 03690 return 1; 03691 } 03692 03693 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 03694 gw->name, ident); 03695 } 03696 } else { 03697 if (ast_strlen_zero(req.endpoint) || 03698 ast_strlen_zero(req.version) || 03699 ast_strlen_zero(req.verb)) { 03700 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); 03701 return 1; 03702 } 03703 /* Process request, with iflock held */ 03704 sub = find_subchannel_and_lock(req.endpoint, 0, &sin); 03705 if (sub) { 03706 /* look first to find a matching response in the queue */ 03707 if (!find_and_retrans(sub, &req)) 03708 /* pass the request off to the currently mastering subchannel */ 03709 handle_request(sub, &req, &sin); 03710 ast_mutex_unlock(&sub->lock); 03711 } 03712 } 03713 return 1; 03714 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 482 of file chan_mgcp.c.
00483 { 00484 /* This module does not handle MWI in an event-based manner. However, it 00485 * subscribes to MWI for each mailbox that is configured so that the core 00486 * knows that we care about it. Then, chan_mgcp will get the MWI from the 00487 * event cache instead of checking the mailbox directly. */ 00488 }
| 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(), acf_vm_info(), add_agent(), add_hintdevice(), 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(), 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(), func_confbridge_info(), function_agent(), get_comma(), get_in_brackets_full(), iconv_read(), isAnsweringMachine(), isexten_function_read(), jb_framedata_init(), log_exec(), login_exec(), man_do_variable_value(), mgcpsock_read(), mixmonitor_exec(), msg_send_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(), 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(), sip_parse_nat_option(), 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(), stop_mixmonitor_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 ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_is_empty(), ast_format_cap_joint_copy(), 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(), mgcp_endpoint::cap, get_sdp(), get_sdp_iterate(), hp, len(), LOG_WARNING, mgcp_endpoint::nonCodecCapability, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sdpLineNum_iterator_init().
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 struct ast_format_cap *peercap; 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 if (!(peercap = ast_format_cap_alloc_nolock())) { 02030 return -1; 02031 } 02032 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability); 02033 ast_format_cap_joint_copy(global_capability, peercap, p->cap); 02034 ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n", 02035 ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability), 02036 ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap), 02037 ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap)); 02038 peercap = ast_format_cap_destroy(peercap); 02039 02040 ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n", 02041 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); 02042 if (ast_format_cap_is_empty(p->cap)) { 02043 ast_log(LOG_WARNING, "No compatible codecs!\n"); 02044 return -1; 02045 } 02046 return 0; 02047 }
| static void prune_gateways | ( | void | ) | [static] |
Definition at line 4547 of file chan_mgcp.c.
References ast_mutex_lock, ast_mutex_unlock, mgcp_gateway::delme, mgcp_endpoint::delme, destroy_endpoint(), destroy_gateway(), mgcp_gateway::endpoints, gatelock, gateways, mgcp_gateway::next, mgcp_endpoint::next, and mgcp_gateway::realtime.
Referenced by reload_config(), and unload_module().
04548 { 04549 struct mgcp_gateway *g, *z, *r; 04550 struct mgcp_endpoint *e, *p, *t; 04551 04552 ast_mutex_lock(&gatelock); 04553 04554 /* prune gateways */ 04555 for (z = NULL, g = gateways; g;) { 04556 /* prune endpoints */ 04557 for (p = NULL, e = g->endpoints; e; ) { 04558 if (!g->realtime && (e->delme || g->delme)) { 04559 t = e; 04560 e = e->next; 04561 if (!p) 04562 g->endpoints = e; 04563 else 04564 p->next = e; 04565 destroy_endpoint(t); 04566 } else { 04567 p = e; 04568 e = e->next; 04569 } 04570 } 04571 04572 if (g->delme) { 04573 r = g; 04574 g = g->next; 04575 if (!z) 04576 gateways = g; 04577 else 04578 z->next = g; 04579 04580 destroy_gateway(r); 04581 } else { 04582 z = g; 04583 g = g->next; 04584 } 04585 } 04586 04587 ast_mutex_unlock(&gatelock); 04588 }
| static int reload | ( | void | ) | [static] |
Definition at line 4874 of file chan_mgcp.c.
References mgcp_reload().
04875 { 04876 mgcp_reload(NULL, 0, NULL); 04877 return 0; 04878 }
| static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4622 of file chan_mgcp.c.
References __ourip, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_format_cap_add(), ast_format_cap_remove(), ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_io_remove(), ast_io_wait(), ast_jb_read_conf(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_netsock_set_qos(), ast_sched_runq(), ast_str2cos(), ast_str2tos(), ast_variable_browse(), ast_verb, bindaddr, build_gateway(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MGCP_CA_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, errno, gatelock, gateways, global_jbconf, hp, ast_format::id, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mgcp_endpoint::name, mgcp_gateway::name, ast_variable::name, mgcp_endpoint::needaudit, netlock, mgcp_endpoint::next, mgcp_gateway::next, ast_variable::next, prune_gateways(), qos, transmit_audit_endpoint(), and ast_variable::value.
04623 { 04624 struct ast_config *cfg; 04625 struct ast_variable *v; 04626 struct mgcp_gateway *g; 04627 struct mgcp_endpoint *e; 04628 char *cat; 04629 struct ast_hostent ahp; 04630 struct hostent *hp; 04631 struct ast_format format; 04632 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04633 04634 if (gethostname(ourhost, sizeof(ourhost)-1)) { 04635 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); 04636 return 0; 04637 } 04638 cfg = ast_config_load(config, config_flags); 04639 04640 /* We *must* have a config file otherwise stop immediately */ 04641 if (!cfg) { 04642 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); 04643 return 0; 04644 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 04645 return 0; 04646 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04647 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 04648 return 0; 04649 } 04650 04651 memset(&bindaddr, 0, sizeof(bindaddr)); 04652 dtmfmode = 0; 04653 04654 /* Copy the default jb config over global_jbconf */ 04655 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 04656 04657 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 04658 /* handle jb conf */ 04659 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { 04660 continue; 04661 } 04662 04663 /* Create the interface list */ 04664 if (!strcasecmp(v->name, "bindaddr")) { 04665 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 04666 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 04667 } else { 04668 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 04669 } 04670 } else if (!strcasecmp(v->name, "allow")) { 04671 ast_getformatbyname(v->value, &format); 04672 if (!format.id) { 04673 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04674 } else { 04675 ast_format_cap_add(global_capability, &format); 04676 } 04677 } else if (!strcasecmp(v->name, "disallow")) { 04678 ast_getformatbyname(v->value, &format); 04679 if (!format.id) { 04680 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04681 } else { 04682 ast_format_cap_remove(global_capability, &format); 04683 } 04684 } else if (!strcasecmp(v->name, "tos")) { 04685 if (ast_str2tos(v->value, &qos.tos)) { 04686 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04687 } 04688 } else if (!strcasecmp(v->name, "tos_audio")) { 04689 if (ast_str2tos(v->value, &qos.tos_audio)) 04690 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04691 } else if (!strcasecmp(v->name, "cos")) { 04692 if (ast_str2cos(v->value, &qos.cos)) 04693 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 04694 } else if (!strcasecmp(v->name, "cos_audio")) { 04695 if (ast_str2cos(v->value, &qos.cos_audio)) 04696 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04697 } else if (!strcasecmp(v->name, "port")) { 04698 if (sscanf(v->value, "%5d", &ourport) == 1) { 04699 bindaddr.sin_port = htons(ourport); 04700 } else { 04701 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 04702 } 04703 } else if (!strcasecmp(v->name, "firstdigittimeout")) { 04704 firstdigittimeout = atoi(v->value); 04705 } else if (!strcasecmp(v->name, "gendigittimeout")) { 04706 gendigittimeout = atoi(v->value); 04707 } else if (!strcasecmp(v->name, "matchdigittimeout")) { 04708 matchdigittimeout = atoi(v->value); 04709 } 04710 } 04711 04712 /* mark existing entries for deletion */ 04713 ast_mutex_lock(&gatelock); 04714 for (g = gateways; g; g = g->next) { 04715 g->delme = 1; 04716 for (e = g->endpoints; e; e = e->next) { 04717 e->delme = 1; 04718 } 04719 } 04720 ast_mutex_unlock(&gatelock); 04721 04722 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) { 04723 if (strcasecmp(cat, "general")) { 04724 ast_mutex_lock(&gatelock); 04725 if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) { 04726 ast_verb(3, "Added gateway '%s'\n", g->name); 04727 g->next = gateways; 04728 gateways = g; 04729 } 04730 ast_mutex_unlock(&gatelock); 04731 04732 /* FS: process queue and IO */ 04733 if (monitor_thread == pthread_self()) { 04734 if (sched) ast_sched_runq(sched); 04735 if (io) ast_io_wait(io, 10); 04736 } 04737 } 04738 } 04739 04740 /* prune deleted entries etc. */ 04741 prune_gateways(); 04742 04743 if (ntohl(bindaddr.sin_addr.s_addr)) { 04744 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); 04745 } else { 04746 hp = ast_gethostbyname(ourhost, &ahp); 04747 if (!hp) { 04748 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); 04749 ast_config_destroy(cfg); 04750 return 0; 04751 } 04752 memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); 04753 } 04754 if (!ntohs(bindaddr.sin_port)) 04755 bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT); 04756 bindaddr.sin_family = AF_INET; 04757 ast_mutex_lock(&netlock); 04758 if (mgcpsock > -1) 04759 close(mgcpsock); 04760 04761 if (mgcpsock_read_id != NULL) 04762 ast_io_remove(io, mgcpsock_read_id); 04763 mgcpsock_read_id = NULL; 04764 04765 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); 04766 if (mgcpsock < 0) { 04767 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); 04768 } else { 04769 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 04770 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 04771 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 04772 strerror(errno)); 04773 close(mgcpsock); 04774 mgcpsock = -1; 04775 } else { 04776 ast_verb(2, "MGCP Listening on %s:%d\n", 04777 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 04778 ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); 04779 } 04780 } 04781 ast_mutex_unlock(&netlock); 04782 ast_config_destroy(cfg); 04783 04784 /* send audit only to the new endpoints */ 04785 for (g = gateways; g; g = g->next) { 04786 for (e = g->endpoints; e && e->needaudit; e = e->next) { 04787 e->needaudit = 0; 04788 transmit_audit_endpoint(e); 04789 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); 04790 } 04791 } 04792 04793 return 0; 04794 }
| static int reqprep | ( | struct mgcp_request * | req, | |
| struct mgcp_endpoint * | p, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2143 of file chan_mgcp.c.
References init_req().
Referenced by transmit_audit_endpoint(), transmit_cc_notify(), transmit_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message(), transmit_modify_request(), transmit_modify_with_sdp(), 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().
02144 { 02145 memset(req, 0, sizeof(struct mgcp_request)); 02146 oseq++; 02147 if (oseq > 999999999) { 02148 oseq = 1; 02149 } 02150 init_req(p, req, verb); 02151 return 0; 02152 }
| static int resend_response | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_response * | resp | |||
| ) | [static] |
Definition at line 556 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, and mgcp_subchannel::parent.
Referenced by find_and_retrans().
00557 { 00558 struct mgcp_endpoint *p = sub->parent; 00559 int res; 00560 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)); 00561 res = __mgcp_xmit(p->parent, resp->buf, resp->len); 00562 if (res > 0) 00563 res = 0; 00564 return res; 00565 }
| static int respprep | ( | struct mgcp_request * | resp, | |
| struct mgcp_endpoint * | p, | |||
| char * | msg, | |||
| struct mgcp_request * | req, | |||
| char * | msgrest | |||
| ) | [static] |
Definition at line 2136 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().
02137 { 02138 memset(resp, 0, sizeof(*resp)); 02139 init_resp(resp, msg, req, msgrest); 02140 return 0; 02141 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 3894 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, and monlock.
03895 { 03896 /* If we're supposed to be stopped -- stay stopped */ 03897 if (monitor_thread == AST_PTHREADT_STOP) 03898 return 0; 03899 if (ast_mutex_lock(&monlock)) { 03900 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 03901 return -1; 03902 } 03903 if (monitor_thread == pthread_self()) { 03904 ast_mutex_unlock(&monlock); 03905 ast_log(LOG_WARNING, "Cannot kill myself\n"); 03906 return -1; 03907 } 03908 if (monitor_thread != AST_PTHREADT_NULL) { 03909 /* Wake up the thread */ 03910 pthread_kill(monitor_thread, SIGURG); 03911 } else { 03912 /* Start a new monitor */ 03913 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 03914 ast_mutex_unlock(&monlock); 03915 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 03916 return -1; 03917 } 03918 } 03919 ast_mutex_unlock(&monlock); 03920 return 0; 03921 }
| static int retrans_pkt | ( | const void * | data | ) | [static] |
Definition at line 653 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().
00654 { 00655 struct mgcp_gateway *gw = (struct mgcp_gateway *)data; 00656 struct mgcp_message *cur, *exq = NULL, *w, *prev; 00657 int res = 0; 00658 00659 /* find out expired msgs */ 00660 ast_mutex_lock(&gw->msgs_lock); 00661 00662 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00663 if (cur->retrans < MAX_RETRANS) { 00664 cur->retrans++; 00665 ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n", 00666 cur->retrans, cur->seqno, gw->name); 00667 __mgcp_xmit(gw, cur->buf, cur->len); 00668 } else { 00669 if (prev) 00670 prev->next = cur->next; 00671 else 00672 gw->msgs = cur->next; 00673 00674 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", 00675 cur->seqno, gw->name); 00676 00677 w = cur; 00678 00679 if (exq) { 00680 w->next = exq; 00681 } else { 00682 w->next = NULL; 00683 } 00684 exq = w; 00685 } 00686 } 00687 00688 if (!gw->msgs) { 00689 gw->retransid = -1; 00690 res = 0; 00691 } else { 00692 res = 1; 00693 } 00694 ast_mutex_unlock(&gw->msgs_lock); 00695 00696 while (exq) { 00697 cur = exq; 00698 /* time-out transaction */ 00699 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 00700 exq = exq->next; 00701 ast_free(cur); 00702 } 00703 00704 return res; 00705 }
| 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 752 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_connect(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_info_with_aoc(), transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message(), transmit_modify_request(), transmit_modify_with_sdp(), 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().
00754 { 00755 int res = 0; 00756 struct mgcp_request **queue, *q, *r, *t; 00757 ast_mutex_t *l; 00758 00759 ast_debug(1, "Slow sequence is %d\n", p->slowsequence); 00760 if (p->slowsequence) { 00761 queue = &p->cmd_queue; 00762 l = &p->cmd_queue_lock; 00763 ast_mutex_lock(l); 00764 } else { 00765 switch (req->cmd) { 00766 case MGCP_CMD_DLCX: 00767 queue = &sub->cx_queue; 00768 l = &sub->cx_queue_lock; 00769 ast_mutex_lock(l); 00770 q = sub->cx_queue; 00771 /* delete pending cx cmds */ 00772 /* buggy sb5120 */ 00773 if (!sub->parent->ncs) { 00774 while (q) { 00775 r = q->next; 00776 ast_free(q); 00777 q = r; 00778 } 00779 *queue = NULL; 00780 } 00781 break; 00782 00783 case MGCP_CMD_CRCX: 00784 case MGCP_CMD_MDCX: 00785 queue = &sub->cx_queue; 00786 l = &sub->cx_queue_lock; 00787 ast_mutex_lock(l); 00788 break; 00789 00790 case MGCP_CMD_RQNT: 00791 queue = &p->rqnt_queue; 00792 l = &p->rqnt_queue_lock; 00793 ast_mutex_lock(l); 00794 break; 00795 00796 default: 00797 queue = &p->cmd_queue; 00798 l = &p->cmd_queue_lock; 00799 ast_mutex_lock(l); 00800 break; 00801 } 00802 } 00803 00804 if (!(r = ast_malloc(sizeof(*r)))) { 00805 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n"); 00806 ast_mutex_unlock(l); 00807 return -1; 00808 } 00809 memcpy(r, req, sizeof(*r)); 00810 00811 if (!(*queue)) { 00812 ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data, 00813 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00814 00815 res = mgcp_postrequest(p, sub, req->data, req->len, seqno); 00816 } else { 00817 ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data, 00818 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00819 } 00820 00821 /* XXX find tail. We could also keep tail in the data struct for faster access */ 00822 for (t = *queue; t && t->next; t = t->next); 00823 00824 r->next = NULL; 00825 if (t) 00826 t->next = r; 00827 else 00828 *queue = r; 00829 00830 ast_mutex_unlock(l); 00831 00832 return res; 00833 }
| static int send_response | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 567 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, and mgcp_subchannel::parent.
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().
00568 { 00569 struct mgcp_endpoint *p = sub->parent; 00570 int res; 00571 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)); 00572 res = __mgcp_xmit(p->parent, req->data, req->len); 00573 if (res > 0) 00574 res = 0; 00575 return res; 00576 }
| static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2930 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_response(), HandleCallIncoming(), HandleCallOutgoing(), mgcp_answer(), mgcp_call(), mgcp_ss(), setsubstate(), skinny_newcall(), and unistim_answer().
02931 { 02932 struct ast_sockaddr bindaddr_tmp; 02933 02934 ast_mutex_lock(&sub->lock); 02935 /* check again to be on the safe side */ 02936 if (sub->rtp) { 02937 ast_rtp_instance_destroy(sub->rtp); 02938 sub->rtp = NULL; 02939 } 02940 /* Allocate the RTP now */ 02941 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 02942 sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); 02943 if (sub->rtp && sub->owner) 02944 ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0)); 02945 if (sub->rtp) { 02946 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); 02947 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat); 02948 } 02949 /* Make a call*ID */ 02950 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); 02951 /* Transmit the connection create */ 02952 if(!sub->parent->pktcgatealloc) { 02953 transmit_connect_with_sdp(sub, NULL); 02954 } else { 02955 transmit_connect(sub); 02956 sub->gate = NULL; 02957 if(!mgcp_alloc_pktcgate(sub)) 02958 mgcp_queue_hangup(sub); 02959 } 02960 ast_mutex_unlock(&sub->lock); 02961 }
| static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2642 of file chan_mgcp.c.
References add_header(), mgcp_request::cmd, MGCP_CMD_AUEP, reqprep(), send_request(), and mgcp_request::trid.
Referenced by find_realtime_gw(), handle_mgcp_audit_endpoint(), handle_request(), and reload_config().
02643 { 02644 struct mgcp_request resp; 02645 reqprep(&resp, p, "AUEP"); 02646 /* removed unknown param VS */ 02647 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ 02648 add_header(&resp, "F", "A"); 02649 /* fill in new fields */ 02650 resp.cmd = MGCP_CMD_AUEP; 02651 resp.trid = oseq; 02652 return send_request(p, NULL, &resp, oseq); 02653 }
| static int transmit_connect | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2437 of file chan_mgcp.c.
References add_header(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by setsubstate(), and start_rtp().
02438 { 02439 struct mgcp_request resp; 02440 char local[256]; 02441 char tmp[80]; 02442 struct ast_format tmpfmt; 02443 struct mgcp_endpoint *p = sub->parent; 02444 02445 ast_copy_string(local, "p:20, s:off, e:on", sizeof(local)); 02446 02447 ast_format_cap_iter_start(p->cap); 02448 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02449 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02450 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02451 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02452 } 02453 } 02454 ast_format_cap_iter_end(p->cap); 02455 02456 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02457 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02458 sub->sdpsent = 0; 02459 reqprep(&resp, p, "CRCX"); 02460 add_header(&resp, "C", sub->callid); 02461 add_header(&resp, "L", local); 02462 add_header(&resp, "M", "inactive"); 02463 /* X header should not be sent. kept for compatibility */ 02464 add_header(&resp, "X", sub->txident); 02465 /*add_header(&resp, "S", "");*/ 02466 /* fill in new fields */ 02467 resp.cmd = MGCP_CMD_CRCX; 02468 resp.trid = oseq; 02469 return send_request(p, sub, &resp, oseq); 02470 }
| static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp_instance * | rtp | |||
| ) | [static] |
Definition at line 2340 of file chan_mgcp.c.
References add_header(), add_sdp(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_AUDIO, ast_rtp_lookup_mime_subtype2(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxmode, mgcp_subchannel::gate, GATE_ALLOCATED, cops_gate::gateid, ast_format::id, mgcp_subchannel::id, MGCP_CMD_CRCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by start_rtp().
02341 { 02342 struct mgcp_request resp; 02343 char local[256]; 02344 char tmp[80]; 02345 struct ast_format tmpfmt; 02346 struct mgcp_endpoint *p = sub->parent; 02347 02348 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02349 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02350 02351 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02352 02353 ast_format_cap_iter_start(p->cap); 02354 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02355 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { 02356 /* Audio is now discontiguous */ 02357 continue; 02358 } 02359 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02360 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02361 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02362 } 02363 } 02364 ast_format_cap_iter_end(p->cap); 02365 02366 if (sub->gate) { 02367 if(sub->gate->state == GATE_ALLOCATED) { 02368 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02369 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02370 } 02371 } 02372 sub->sdpsent = 1; 02373 reqprep(&resp, p, "CRCX"); 02374 add_header(&resp, "C", sub->callid); 02375 add_header(&resp, "L", local); 02376 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02377 /* X header should not be sent. kept for compatibility */ 02378 add_header(&resp, "X", sub->txident); 02379 /*add_header(&resp, "S", "");*/ 02380 add_sdp(&resp, sub, rtp); 02381 /* fill in new fields */ 02382 resp.cmd = MGCP_CMD_CRCX; 02383 resp.trid = oseq; 02384 return send_request(p, sub, &resp, oseq); 02385 }
| static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2655 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_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by destroy_endpoint(), handle_request(), handle_response(), mgcp_hangup(), and unalloc_sub().
02656 { 02657 struct mgcp_endpoint *p = sub->parent; 02658 struct mgcp_request resp; 02659 02660 ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 02661 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02662 reqprep(&resp, p, "DLCX"); 02663 /* check if call id is avail */ 02664 if (sub->callid[0]) 02665 add_header(&resp, "C", sub->callid); 02666 /* X header should not be sent. kept for compatibility */ 02667 add_header(&resp, "X", sub->txident); 02668 /* check if cxident is avail */ 02669 if (sub->cxident[0]) 02670 add_header(&resp, "I", sub->cxident); 02671 /* fill in new fields */ 02672 resp.cmd = MGCP_CMD_DLCX; 02673 resp.trid = oseq; 02674 return send_request(p, sub, &resp, oseq); 02675 }
| static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, | |
| char * | callid, | |||
| char * | cxident | |||
| ) | [static] |
Definition at line 2677 of file chan_mgcp.c.
References add_header(), ast_debug, mgcp_request::cmd, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, reqprep(), send_request(), mgcp_endpoint::sub, and mgcp_request::trid.
Referenced by handle_response().
02678 { 02679 struct mgcp_request resp; 02680 02681 ast_debug(3, "Delete connection %s %s@%s on callid: %s\n", 02682 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); 02683 reqprep(&resp, p, "DLCX"); 02684 /* check if call id is avail */ 02685 if (callid && *callid) 02686 add_header(&resp, "C", callid); 02687 /* check if cxident is avail */ 02688 if (cxident && *cxident) 02689 add_header(&resp, "I", cxident); 02690 /* fill in new fields */ 02691 resp.cmd = MGCP_CMD_DLCX; 02692 resp.trid = oseq; 02693 return send_request(p, p->sub, &resp, oseq); 02694 }
| static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2543 of file chan_mgcp.c.
References add_header(), add_header_offhook(), add_sdp(), ast_copy_string(), ast_debug, ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_cap_set(), ast_rtp_lookup_mime_subtype2(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::gate, GATE_ALLOCATED, GATE_OPEN, cops_gate::gateid, mgcp_endpoint::hookstate, mgcp_subchannel::id, MGCP_CMD_MDCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), mgcp_call(), mgcp_hangup(), and mgcp_indicate().
02544 { 02545 struct mgcp_request resp; 02546 struct mgcp_endpoint *p = sub->parent; 02547 struct ast_format tmpfmt; 02548 int fc = 1; 02549 char local[256]; 02550 char tmp[80]; 02551 02552 if (ast_strlen_zero(sub->cxident)) { 02553 /* We don't have a CXident yet, store the destination and 02554 wait a bit */ 02555 return 0; 02556 } 02557 ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", 02558 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02559 02560 ast_copy_string(local, "", sizeof(local)); 02561 ast_format_cap_iter_start(p->cap); 02562 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02563 if (p->ncs && !fc) { 02564 ast_format_cap_set(p->cap, &tmpfmt); /* sb5120e bug */ 02565 break; 02566 } else { 02567 fc = 0; 02568 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02569 } 02570 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02571 } 02572 ast_format_cap_iter_end(p->cap); 02573 02574 if (!sub->sdpsent) { 02575 if (sub->gate) { 02576 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { 02577 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02578 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02579 } else { 02580 /* we still don't have gateid wait */ 02581 return 0; 02582 } 02583 } 02584 } 02585 02586 reqprep(&resp, p, "MDCX"); 02587 add_header(&resp, "C", sub->callid); 02588 if (!sub->sdpsent) { 02589 add_header(&resp, "L", local); 02590 } 02591 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02592 /* X header should not be sent. kept for compatibility */ 02593 add_header(&resp, "X", sub->txident); 02594 add_header(&resp, "I", sub->cxident); 02595 switch (sub->parent->hookstate) { 02596 case MGCP_ONHOOK: 02597 add_header(&resp, "R", "L/hd(N)"); 02598 break; 02599 case MGCP_OFFHOOK: 02600 add_header_offhook(sub, &resp, ""); 02601 break; 02602 } 02603 if (!sub->sdpsent) { 02604 add_sdp(&resp, sub, NULL); 02605 sub->sdpsent = 1; 02606 } 02607 /* fill in new fields */ 02608 resp.cmd = MGCP_CMD_MDCX; 02609 resp.trid = oseq; 02610 return send_request(p, sub, &resp, oseq); 02611 }
| static int transmit_modify_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp_instance * | rtp, | |||
| const struct ast_format_cap * | codecs | |||
| ) | [static] |
Definition at line 2281 of file chan_mgcp.c.
References add_header(), add_sdp(), ast_copy_string(), ast_debug, ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_AUDIO, ast_rtp_instance_get_remote_address(), ast_rtp_lookup_mime_subtype2(), ast_sockaddr_to_sin, ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::cap, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_subchannel::gate, GATE_ALLOCATED, GATE_OPEN, cops_gate::gateid, ast_format::id, MGCP_CMD_MDCX, mgcp_subchannel::parent, reqprep(), mgcp_subchannel::sdpsent, send_request(), cops_gate::state, mgcp_subchannel::tmpdest, mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by handle_response(), mgcp_pktcgate_open(), mgcp_set_rtp_peer(), and mgcp_write().
02282 { 02283 struct mgcp_request resp; 02284 char local[256]; 02285 char tmp[80]; 02286 struct mgcp_endpoint *p = sub->parent; 02287 struct ast_format tmpfmt; 02288 struct ast_sockaddr sub_tmpdest_tmp; 02289 02290 if (ast_strlen_zero(sub->cxident) && rtp) { 02291 /* We don't have a CXident yet, store the destination and 02292 wait a bit */ 02293 ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp); 02294 ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest); 02295 return 0; 02296 } 02297 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02298 ast_format_cap_iter_start(p->cap); 02299 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02300 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { 02301 /* Audio is now discontiguous */ 02302 continue; 02303 } 02304 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02305 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02306 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02307 } 02308 } 02309 ast_format_cap_iter_end(p->cap); 02310 02311 if (sub->gate) { 02312 if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) { 02313 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02314 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02315 sub->sdpsent = 1; 02316 } else { 02317 /* oops wait */ 02318 ast_debug(1, "Waiting for opened gate...\n"); 02319 sub->sdpsent = 0; 02320 return 0; 02321 } 02322 } 02323 02324 02325 reqprep(&resp, p, "MDCX"); 02326 add_header(&resp, "C", sub->callid); 02327 add_header(&resp, "L", local); 02328 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02329 /* X header should not be sent. kept for compatibility */ 02330 add_header(&resp, "X", sub->txident); 02331 add_header(&resp, "I", sub->cxident); 02332 /*add_header(&resp, "S", "");*/ 02333 add_sdp(&resp, sub, rtp); 02334 /* fill in new fields */ 02335 resp.cmd = MGCP_CMD_MDCX; 02336 resp.trid = oseq; 02337 return send_request(p, sub, &resp, oseq); 02338 }
| static int transmit_notify_request | ( | struct mgcp_subchannel * | sub, | |
| char * | tone | |||
| ) | [static] |
Definition at line 2472 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_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), 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().
02473 { 02474 struct mgcp_request resp; 02475 struct mgcp_endpoint *p = sub->parent; 02476 02477 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02478 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02479 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02480 reqprep(&resp, p, "RQNT"); 02481 add_header(&resp, "X", p->rqnt_ident); 02482 switch (p->hookstate) { 02483 case MGCP_ONHOOK: 02484 add_header(&resp, "R", "L/hd(N)"); 02485 break; 02486 case MGCP_OFFHOOK: 02487 add_header_offhook(sub, &resp, tone); 02488 break; 02489 } 02490 if (!ast_strlen_zero(tone)) { 02491 add_header(&resp, "S", tone); 02492 } 02493 /* fill in new fields */ 02494 resp.cmd = MGCP_CMD_RQNT; 02495 resp.trid = oseq; 02496 return send_request(p, NULL, &resp, oseq); 02497 }
| static int transmit_notify_request_with_callerid | ( | struct mgcp_subchannel * | sub, | |
| char * | tone, | |||
| char * | callernum, | |||
| char * | callername | |||
| ) | [static] |
Definition at line 2499 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_OFFHOOK, MGCP_ONHOOK, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), mgcp_endpoint::rqnt_ident, send_request(), 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().
02500 { 02501 struct mgcp_request resp; 02502 char tone2[256]; 02503 char *l, *n; 02504 struct timeval t = ast_tvnow(); 02505 struct ast_tm tm; 02506 struct mgcp_endpoint *p = sub->parent; 02507 02508 ast_localtime(&t, &tm, NULL); 02509 n = callername; 02510 l = callernum; 02511 if (!n) 02512 n = ""; 02513 if (!l) 02514 l = ""; 02515 02516 /* Keep track of last callerid for blacklist and callreturn */ 02517 ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid)); 02518 02519 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 02520 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n); 02521 ast_copy_string(p->curtone, tone, sizeof(p->curtone)); 02522 reqprep(&resp, p, "RQNT"); 02523 add_header(&resp, "X", p->rqnt_ident); 02524 switch (p->hookstate) { 02525 case MGCP_ONHOOK: 02526 add_header(&resp, "R", "L/hd(N)"); 02527 break; 02528 case MGCP_OFFHOOK: 02529 add_header_offhook(sub, &resp, tone); 02530 break; 02531 } 02532 if (!ast_strlen_zero(tone2)) { 02533 add_header(&resp, "S", tone2); 02534 } 02535 ast_debug(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", 02536 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); 02537 /* fill in new fields */ 02538 resp.cmd = MGCP_CMD_RQNT; 02539 resp.trid = oseq; 02540 return send_request(p, NULL, &resp, oseq); 02541 }
| static int transmit_response | ( | struct mgcp_subchannel * | sub, | |
| char * | msg, | |||
| struct mgcp_request * | req, | |||
| char * | msgrest | |||
| ) | [static] |
Definition at line 2154 of file chan_mgcp.c.
References ast_calloc, mgcp_response::buf, mgcp_request::data, mgcp_request::identifier, mgcp_response::len, mgcp_request::len, mgcp_response::next, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_gateway::responses, respprep(), send_response(), mgcp_response::seqno, and mgcp_response::whensent.
Referenced by handle_button_template_req_message(), handle_cc_notify(), handle_cc_subscribe(), handle_incoming(), handle_invite_replaces(), 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(), 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_capabilitiesreq(), 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_keepaliveack(), transmit_lamp_indication(), transmit_linestatres(), transmit_microphone_mode(), transmit_provisional_response(), transmit_registerack(), transmit_reset(), 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().
02155 { 02156 struct mgcp_request resp; 02157 struct mgcp_endpoint *p = sub->parent; 02158 struct mgcp_response *mgr; 02159 02160 if (!sub) { 02161 return -1; 02162 } 02163 02164 respprep(&resp, p, msg, req, msgrest); 02165 if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) { 02166 return send_response(sub, &resp); 02167 } 02168 /* Store MGCP response in case we have to retransmit */ 02169 sscanf(req->identifier, "%30d", &mgr->seqno); 02170 time(&mgr->whensent); 02171 mgr->len = resp.len; 02172 memcpy(mgr->buf, resp.data, resp.len); 02173 mgr->buf[resp.len] = '\0'; 02174 mgr->next = p->parent->responses; 02175 p->parent->responses = mgr; 02176 02177 return send_response(sub, &resp); 02178 }
| static int unalloc_sub | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 515 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().
00516 { 00517 struct mgcp_endpoint *p = sub->parent; 00518 if (p->sub == sub) { 00519 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name); 00520 return -1; 00521 } 00522 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name); 00523 00524 sub->owner = NULL; 00525 if (!ast_strlen_zero(sub->cxident)) { 00526 transmit_connection_del(sub); 00527 } 00528 sub->cxident[0] = '\0'; 00529 sub->callid[0] = '\0'; 00530 sub->cxmode = MGCP_CX_INACTIVE; 00531 sub->outgoing = 0; 00532 sub->alreadygone = 0; 00533 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 00534 if (sub->rtp) { 00535 ast_rtp_instance_destroy(sub->rtp); 00536 sub->rtp = NULL; 00537 } 00538 dump_cmd_queues(NULL, sub); 00539 return 0; 00540 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 4880 of file chan_mgcp.c.
References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_sched_context_destroy(), ast_channel_tech::capabilities, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_gateway::endpoints, gatelock, gateways, LOG_WARNING, mgcp_reload(), mgcp_reload_lock, monlock, mgcp_endpoint::next, mgcp_gateway::next, and prune_gateways().
04881 { 04882 struct mgcp_endpoint *e; 04883 struct mgcp_gateway *g; 04884 04885 /* Check to see if we're reloading */ 04886 if (ast_mutex_trylock(&mgcp_reload_lock)) { 04887 ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n"); 04888 return -1; 04889 } else { 04890 mgcp_reloading = 1; 04891 ast_mutex_unlock(&mgcp_reload_lock); 04892 } 04893 04894 /* First, take us out of the channel loop */ 04895 ast_channel_unregister(&mgcp_tech); 04896 04897 /* Shut down the monitoring thread */ 04898 if (!ast_mutex_lock(&monlock)) { 04899 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { 04900 pthread_cancel(monitor_thread); 04901 pthread_kill(monitor_thread, SIGURG); 04902 pthread_join(monitor_thread, NULL); 04903 } 04904 monitor_thread = AST_PTHREADT_STOP; 04905 ast_mutex_unlock(&monlock); 04906 } else { 04907 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 04908 /* We always want to leave this in a consistent state */ 04909 ast_channel_register(&mgcp_tech); 04910 mgcp_reloading = 0; 04911 mgcp_reload(NULL, 0, NULL); 04912 return -1; 04913 } 04914 04915 if (!ast_mutex_lock(&gatelock)) { 04916 for (g = gateways; g; g = g->next) { 04917 g->delme = 1; 04918 for (e = g->endpoints; e; e = e->next) { 04919 e->delme = 1; 04920 } 04921 } 04922 04923 prune_gateways(); 04924 ast_mutex_unlock(&gatelock); 04925 } else { 04926 ast_log(LOG_WARNING, "Unable to lock the gateways list.\n"); 04927 /* We always want to leave this in a consistent state */ 04928 ast_channel_register(&mgcp_tech); 04929 /* Allow the monitor to restart */ 04930 monitor_thread = AST_PTHREADT_NULL; 04931 mgcp_reloading = 0; 04932 mgcp_reload(NULL, 0, NULL); 04933 return -1; 04934 } 04935 04936 close(mgcpsock); 04937 ast_rtp_glue_unregister(&mgcp_rtp_glue); 04938 ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04939 ast_sched_context_destroy(sched); 04940 04941 global_capability = ast_format_cap_destroy(global_capability); 04942 mgcp_tech.capabilities = ast_format_cap_destroy(mgcp_tech.capabilities); 04943 04944 return 0; 04945 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_pktccops", } [static] |
Definition at line 4953 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 4953 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.
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] |
Definition at line 1168 of file chan_mgcp.c.
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] |
Definition at line 193 of file chan_mgcp.c.
int dtmfmode = 0 [static] |
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_MUTEX_INITIALIZER , 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(), reload_config(), and unload_module().
struct mgcp_gateway * gateways [static] |
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic)
Definition at line 209 of file chan_mgcp.c.
struct ast_format_cap* global_capability [static] |
Definition at line 227 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(), conf_run(), disa_exec(), extenspy_exec(), get_cached_mwi(), handle_request_notify(), has_voicemail(), minivm_mwi_exec(), mkintf(), 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.
ast_mutex_t mgcp_reload_lock = { PTHREAD_MUTEX_INITIALIZER , 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.
struct ast_rtp_glue mgcp_rtp_glue [static] |
Definition at line 4451 of file chan_mgcp.c.
struct ast_channel_tech mgcp_tech [static] |
Definition at line 463 of file chan_mgcp.c.
int mgcpdebug = 0 [static] |
Definition at line 234 of file chan_mgcp.c.
int mgcpsock = -1 [static] |
Definition at line 424 of file chan_mgcp.c.
int* mgcpsock_read_id = NULL [static] |
Definition at line 3716 of file chan_mgcp.c.
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_MUTEX_INITIALIZER , NULL, 1 } [static] |
Definition at line 218 of file chan_mgcp.c.
char musicclass[MAX_MUSICCLASS] = "" [static] |
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_MUTEX_INITIALIZER , 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(), reload_config(), and unload_module().
int nonCodecCapability = AST_RTP_DTMF [static] |
Definition at line 228 of file chan_mgcp.c.
unsigned int oseq [static] |
Definition at line 203 of file chan_mgcp.c.
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(), build_peer(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), func_channel_write_real(), set_pvt_defaults(), sip_alloc(), and store_config_core().
int pktcgatealloc = 0 [static] |
Definition at line 163 of file chan_mgcp.c.
struct { ... } qos [static] |
struct ast_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.
Referenced by leave_voicemail(), and send_packet().
1.5.6