#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/netsock2.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 the module. | |
| 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 94 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 124 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 95 of file chan_mgcp.c.
| #define MAX_RETRANS 5 |
Try only 5 times for retransmissions
Definition at line 125 of file chan_mgcp.c.
Referenced by retrans_pkt().
| #define MAX_SUBS 2 |
Definition at line 288 of file chan_mgcp.c.
Referenced by build_gateway(), destroy_endpoint(), and mgcp_prune_realtime_gateway().
| #define MGCP_CX_CONF 3 |
| #define MGCP_CX_CONFERENCE 3 |
Definition at line 132 of file chan_mgcp.c.
| #define MGCP_CX_INACTIVE 4 |
Definition at line 134 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 129 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 128 of file chan_mgcp.c.
| #define MGCP_CX_SENDRECV 2 |
Definition at line 130 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 119 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 118 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 117 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 247 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 123 of file chan_mgcp.c.
| #define MGCP_OFFHOOK 2 |
Definition at line 324 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 323 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 299 of file chan_mgcp.c.
Referenced by build_gateway(), and mgcp_hangup().
| #define MGCPDUMPER |
Definition at line 93 of file chan_mgcp.c.
| #define RESPONSE_TIMEOUT 30 |
| #define SUB_ALT 1 |
Definition at line 291 of file chan_mgcp.c.
| #define SUB_REAL 0 |
Definition at line 290 of file chan_mgcp.c.
| #define TYPE_LINE 2 |
Definition at line 327 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 145 of file chan_mgcp.c.
00145 { 00146 MGCP_CMD_EPCF, 00147 MGCP_CMD_CRCX, 00148 MGCP_CMD_MDCX, 00149 MGCP_CMD_DLCX, 00150 MGCP_CMD_RQNT, 00151 MGCP_CMD_NTFY, 00152 MGCP_CMD_AUEP, 00153 MGCP_CMD_AUCX, 00154 MGCP_CMD_RSIP 00155 };
| static char* __get_header | ( | struct mgcp_request * | req, | |
| char * | name, | |||
| int * | start, | |||
| char * | def | |||
| ) | [static] |
Definition at line 1622 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().
01623 { 01624 int x; 01625 int len = strlen(name); 01626 char *r; 01627 for (x = *start; x < req->headers; x++) { 01628 if (!strncasecmp(req->header[x], name, len) && 01629 (req->header[x][len] == ':')) { 01630 r = req->header[x] + len + 1; 01631 while (*r && (*r < 33)) { 01632 r++; 01633 } 01634 *start = x + 1; 01635 return r; 01636 } 01637 } 01638 /* Don't return NULL, so get_header is always a valid pointer */ 01639 return def; 01640 }
| static int __mgcp_xmit | ( | struct mgcp_gateway * | gw, | |
| char * | data, | |||
| int | len | |||
| ) | [static] |
Definition at line 548 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().
00549 { 00550 int res; 00551 if (gw->addr.sin_addr.s_addr) 00552 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); 00553 else 00554 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); 00555 if (res != len) { 00556 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); 00557 } 00558 return res; 00559 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 4969 of file chan_mgcp.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4969 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 4466 of file chan_mgcp.c.
References ast_channel_tech(), ast_channel_tech_pvt(), ast_log(), LOG_ERROR, mgcp_endpoint::ncs, mgcp_subchannel::parent, and sub.
04467 { 04468 struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan); 04469 int res = 0; 04470 04471 /* Sanity check */ 04472 if (!chan || ast_channel_tech(chan) != &mgcp_tech) { 04473 ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n"); 04474 return -1; 04475 } 04476 04477 if (!strcasecmp(args, "ncs")) { 04478 snprintf(buf, buflen, "%s", sub->parent->ncs ? "yes":"no"); 04479 } else { 04480 res = -1; 04481 } 04482 return res; 04483 }
| static int add_header | ( | struct mgcp_request * | req, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Definition at line 2056 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_date(), add_digit(), add_diversion(), add_expires(), add_header_offhook(), add_max_forwards(), add_route(), add_rpid(), add_sdp(), add_supported(), add_text(), add_vidupdate(), ast_sipinfo_send(), 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_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().
02057 { 02058 if (req->len >= sizeof(req->data) - 4) { 02059 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02060 return -1; 02061 } 02062 if (req->lines) { 02063 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 02064 return -1; 02065 } 02066 req->header[req->headers] = req->data + req->len; 02067 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); 02068 req->len += strlen(req->header[req->headers]); 02069 if (req->headers < MGCP_MAX_HEADERS) { 02070 req->headers++; 02071 } else { 02072 ast_log(LOG_WARNING, "Out of header space\n"); 02073 return -1; 02074 } 02075 return 0; 02076 }
| static void add_header_offhook | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | resp, | |||
| char * | tone | |||
| ) | [static] |
Definition at line 2621 of file chan_mgcp.c.
References 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().
02622 { 02623 struct mgcp_endpoint *p = sub->parent; 02624 char tone_indicate_end = 0; 02625 02626 /* We also should check the tone to indicate, because it have no sense 02627 to request notify D/[0-9#*] (dtmf keys) if we are sending congestion 02628 tone for example G/cg */ 02629 if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) { 02630 tone_indicate_end = 1; 02631 } 02632 02633 if (p && p->sub && p->sub->owner && 02634 ast_channel_state(p->sub->owner) >= AST_STATE_RINGING && 02635 (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) { 02636 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02637 02638 } else if (!tone_indicate_end){ 02639 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)")); 02640 } else { 02641 ast_debug(1, "We don't want more digits if we will end the call\n"); 02642 add_header(resp, "R", "L/hu(N),L/hf(N)"); 02643 } 02644 }
| static int add_line | ( | struct mgcp_request * | req, | |
| char * | line | |||
| ) | [static] |
Definition at line 2078 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().
02079 { 02080 if (req->len >= sizeof(req->data) - 4) { 02081 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 02082 return -1; 02083 } 02084 if (!req->lines) { 02085 /* Add extra empty return */ 02086 ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); 02087 req->len += strlen(req->data + req->len); 02088 } 02089 req->line[req->lines] = req->data + req->len; 02090 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 02091 req->len += strlen(req->line[req->lines]); 02092 if (req->lines < MGCP_MAX_LINES) { 02093 req->lines++; 02094 } else { 02095 ast_log(LOG_WARNING, "Out of line space\n"); 02096 return -1; 02097 } 02098 return 0; 02099 }
| static int add_sdp | ( | struct mgcp_request * | resp, | |
| struct mgcp_subchannel * | sub, | |||
| struct ast_rtp_instance * | rtp | |||
| ) | [static] |
Definition at line 2188 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().
02189 { 02190 int len; 02191 int codec; 02192 char costr[80]; 02193 struct sockaddr_in sin; 02194 struct ast_sockaddr sin_tmp; 02195 char v[256]; 02196 char s[256]; 02197 char o[256]; 02198 char c[256]; 02199 char t[256]; 02200 char m[256] = ""; 02201 char a[1024] = ""; 02202 int x; 02203 struct ast_format tmpfmt; 02204 struct sockaddr_in dest = { 0, }; 02205 struct ast_sockaddr dest_tmp; 02206 struct mgcp_endpoint *p = sub->parent; 02207 /* XXX We break with the "recommendation" and send our IP, in order that our 02208 peer doesn't have to ast_gethostbyname() us XXX */ 02209 len = 0; 02210 if (!sub->rtp) { 02211 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02212 return -1; 02213 } 02214 ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp); 02215 ast_sockaddr_to_sin(&sin_tmp, &sin); 02216 if (rtp) { 02217 ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp); 02218 ast_sockaddr_to_sin(&dest_tmp, &dest); 02219 } else { 02220 if (sub->tmpdest.sin_addr.s_addr) { 02221 dest.sin_addr = sub->tmpdest.sin_addr; 02222 dest.sin_port = sub->tmpdest.sin_port; 02223 /* Reset temporary destination */ 02224 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02225 } else { 02226 dest.sin_addr = p->parent->ourip; 02227 dest.sin_port = sin.sin_port; 02228 } 02229 } 02230 ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02231 ast_copy_string(v, "v=0\r\n", sizeof(v)); 02232 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); 02233 ast_copy_string(s, "s=session\r\n", sizeof(s)); 02234 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02235 ast_copy_string(t, "t=0 0\r\n", sizeof(t)); 02236 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02237 02238 ast_format_cap_iter_start(p->cap); 02239 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02240 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { 02241 /* Audio is now discontiguous */ 02242 continue; 02243 } 02244 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02245 ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt)); 02246 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0); 02247 if (codec > -1) { 02248 snprintf(costr, sizeof(costr), " %d", codec); 02249 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02250 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02251 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02252 } 02253 } 02254 } 02255 ast_format_cap_iter_end(p->cap); 02256 02257 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { 02258 if (p->nonCodecCapability & x) { 02259 ast_debug(1, "Answering with non-codec capability %d\n", (int) x); 02260 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, NULL, x); 02261 if (codec > -1) { 02262 snprintf(costr, sizeof(costr), " %d", codec); 02263 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02264 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0)); 02265 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02266 if (x == AST_RTP_DTMF) { 02267 /* Indicate we support DTMF... Not sure about 16, 02268 but MSN supports it so dang it, we will too... */ 02269 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02270 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02271 } 02272 } 02273 } 02274 } 02275 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02276 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02277 snprintf(costr, sizeof(costr), "%d", len); 02278 add_line(resp, v); 02279 add_line(resp, o); 02280 add_line(resp, s); 02281 add_line(resp, c); 02282 add_line(resp, t); 02283 add_line(resp, m); 02284 add_line(resp, a); 02285 return 0; 02286 }
| static struct ast_variable * add_var | ( | const char * | buf, | |
| struct ast_variable * | list | |||
| ) | [static, read] |
Definition at line 4597 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().
04598 { 04599 struct ast_variable *tmpvar = NULL; 04600 char *varname = ast_strdupa(buf), *varval = NULL; 04601 04602 if ((varval = strchr(varname, '='))) { 04603 *varval++ = '\0'; 04604 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 04605 tmpvar->next = list; 04606 list = tmpvar; 04607 } 04608 } 04609 return list; 04610 }
| static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 3223 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_masquerade(), ast_channel_name(), ast_channel_softhangup_internal_flag_add(), 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().
03224 { 03225 /* ************************* 03226 * I hope this works. 03227 * Copied out of chan_zap 03228 * Cross your fingers 03229 * *************************/ 03230 03231 /* In order to transfer, we need at least one of the channels to 03232 actually be in a call bridge. We can't conference two applications 03233 together (but then, why would we want to?) */ 03234 if (ast_bridged_channel(p->sub->owner)) { 03235 /* The three-way person we're about to transfer to could still be in MOH, so 03236 stop if now if appropriate */ 03237 if (ast_bridged_channel(p->sub->next->owner)) 03238 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03239 if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) { 03240 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03241 } 03242 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 03243 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03244 ast_channel_name(ast_bridged_channel(p->sub->owner)), ast_channel_name(p->sub->next->owner)); 03245 return -1; 03246 } 03247 /* Orphan the channel */ 03248 unalloc_sub(p->sub->next); 03249 } else if (ast_bridged_channel(p->sub->next->owner)) { 03250 if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) { 03251 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 03252 } 03253 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 03254 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 03255 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03256 ast_channel_name(ast_bridged_channel(p->sub->next->owner)), ast_channel_name(p->sub->owner)); 03257 return -1; 03258 } 03259 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 03260 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03261 p->sub = p->sub->next; 03262 unalloc_sub(p->sub->next); 03263 /* Tell the caller not to hangup */ 03264 return 1; 03265 } else { 03266 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03267 ast_channel_name(p->sub->owner), ast_channel_name(p->sub->next->owner)); 03268 ast_channel_softhangup_internal_flag_add(p->sub->next->owner, AST_SOFTHANGUP_DEV); 03269 if (p->sub->next->owner) { 03270 p->sub->next->alreadygone = 1; 03271 mgcp_queue_hangup(p->sub->next); 03272 } 03273 } 03274 return 0; 03275 }
| 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 3979 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().
03980 { 03981 struct mgcp_gateway *gw; 03982 struct mgcp_endpoint *e; 03983 struct mgcp_subchannel *sub; 03984 struct ast_variable *chanvars = NULL; 03985 03986 /*char txident[80];*/ 03987 int i=0, y=0; 03988 int gw_reload = 0; 03989 int ep_reload = 0; 03990 directmedia = DIRECTMEDIA; 03991 03992 /* locate existing gateway */ 03993 for (gw = gateways; gw; gw = gw->next) { 03994 if (!strcasecmp(cat, gw->name)) { 03995 /* gateway already exists */ 03996 gw->delme = 0; 03997 gw_reload = 1; 03998 break; 03999 } 04000 } 04001 04002 if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) { 04003 return NULL; 04004 } 04005 04006 if (!gw_reload) { 04007 gw->expire = -1; 04008 gw->realtime = 0; 04009 gw->retransid = -1; 04010 ast_mutex_init(&gw->msgs_lock); 04011 ast_copy_string(gw->name, cat, sizeof(gw->name)); 04012 /* check if the name is numeric ip */ 04013 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 04014 gw->isnamedottedip = 1; 04015 } 04016 for (; v; v = v->next) { 04017 if (!strcasecmp(v->name, "host")) { 04018 if (!strcasecmp(v->value, "dynamic")) { 04019 /* They'll register with us */ 04020 gw->dynamic = 1; 04021 memset(&gw->addr.sin_addr, 0, 4); 04022 if (gw->addr.sin_port) { 04023 /* If we've already got a port, make it the default rather than absolute */ 04024 gw->defaddr.sin_port = gw->addr.sin_port; 04025 gw->addr.sin_port = 0; 04026 } 04027 } else { 04028 /* Non-dynamic. Make sure we become that way if we're not */ 04029 AST_SCHED_DEL(sched, gw->expire); 04030 gw->dynamic = 0; 04031 { 04032 struct ast_sockaddr tmp; 04033 04034 ast_sockaddr_from_sin(&tmp, &gw->addr); 04035 if (ast_get_ip(&tmp, v->value)) { 04036 if (!gw_reload) { 04037 ast_mutex_destroy(&gw->msgs_lock); 04038 ast_free(gw); 04039 } 04040 return NULL; 04041 } 04042 ast_sockaddr_to_sin(&tmp, &gw->addr); 04043 } 04044 } 04045 } else if (!strcasecmp(v->name, "defaultip")) { 04046 struct ast_sockaddr tmp; 04047 04048 ast_sockaddr_from_sin(&tmp, &gw->defaddr); 04049 if (ast_get_ip(&tmp, v->value)) { 04050 if (!gw_reload) { 04051 ast_mutex_destroy(&gw->msgs_lock); 04052 ast_free(gw); 04053 } 04054 return NULL; 04055 } 04056 ast_sockaddr_to_sin(&tmp, &gw->defaddr); 04057 } else if (!strcasecmp(v->name, "permit") || 04058 !strcasecmp(v->name, "deny")) { 04059 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 04060 } else if (!strcasecmp(v->name, "port")) { 04061 gw->addr.sin_port = htons(atoi(v->value)); 04062 } else if (!strcasecmp(v->name, "context")) { 04063 ast_copy_string(context, v->value, sizeof(context)); 04064 } else if (!strcasecmp(v->name, "dtmfmode")) { 04065 if (!strcasecmp(v->value, "inband")) 04066 dtmfmode = MGCP_DTMF_INBAND; 04067 else if (!strcasecmp(v->value, "rfc2833")) 04068 dtmfmode = MGCP_DTMF_RFC2833; 04069 else if (!strcasecmp(v->value, "hybrid")) 04070 dtmfmode = MGCP_DTMF_HYBRID; 04071 else if (!strcasecmp(v->value, "none")) 04072 dtmfmode = 0; 04073 else 04074 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 04075 } else if (!strcasecmp(v->name, "nat")) { 04076 nat = ast_true(v->value); 04077 } else if (!strcasecmp(v->name, "ncs")) { 04078 ncs = ast_true(v->value); 04079 } else if (!strcasecmp(v->name, "hangupongateremove")) { 04080 hangupongateremove = ast_true(v->value); 04081 } else if (!strcasecmp(v->name, "pktcgatealloc")) { 04082 pktcgatealloc = ast_true(v->value); 04083 } else if (!strcasecmp(v->name, "callerid")) { 04084 if (!strcasecmp(v->value, "asreceived")) { 04085 cid_num[0] = '\0'; 04086 cid_name[0] = '\0'; 04087 } else { 04088 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 04089 } 04090 } else if (!strcasecmp(v->name, "language")) { 04091 ast_copy_string(language, v->value, sizeof(language)); 04092 } else if (!strcasecmp(v->name, "accountcode")) { 04093 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 04094 } else if (!strcasecmp(v->name, "amaflags")) { 04095 y = ast_cdr_amaflags2int(v->value); 04096 if (y < 0) { 04097 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 04098 } else { 04099 amaflags = y; 04100 } 04101 } else if (!strcasecmp(v->name, "setvar")) { 04102 chanvars = add_var(v->value, chanvars); 04103 } else if (!strcasecmp(v->name, "clearvars")) { 04104 if (chanvars) { 04105 ast_variables_destroy(chanvars); 04106 chanvars = NULL; 04107 } 04108 } else if (!strcasecmp(v->name, "musiconhold")) { 04109 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 04110 } else if (!strcasecmp(v->name, "parkinglot")) { 04111 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 04112 } else if (!strcasecmp(v->name, "callgroup")) { 04113 cur_callergroup = ast_get_group(v->value); 04114 } else if (!strcasecmp(v->name, "pickupgroup")) { 04115 cur_pickupgroup = ast_get_group(v->value); 04116 } else if (!strcasecmp(v->name, "immediate")) { 04117 immediate = ast_true(v->value); 04118 } else if (!strcasecmp(v->name, "cancallforward")) { 04119 cancallforward = ast_true(v->value); 04120 } else if (!strcasecmp(v->name, "singlepath")) { 04121 singlepath = ast_true(v->value); 04122 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 04123 directmedia = ast_true(v->value); 04124 } else if (!strcasecmp(v->name, "mailbox")) { 04125 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 04126 } else if (!strcasecmp(v->name, "hasvoicemail")) { 04127 if (ast_true(v->value) && ast_strlen_zero(mailbox)) { 04128 ast_copy_string(mailbox, gw->name, sizeof(mailbox)); 04129 } 04130 } else if (!strcasecmp(v->name, "adsi")) { 04131 adsi = ast_true(v->value); 04132 } else if (!strcasecmp(v->name, "callreturn")) { 04133 callreturn = ast_true(v->value); 04134 } else if (!strcasecmp(v->name, "callwaiting")) { 04135 callwaiting = ast_true(v->value); 04136 } else if (!strcasecmp(v->name, "slowsequence")) { 04137 slowsequence = ast_true(v->value); 04138 } else if (!strcasecmp(v->name, "transfer")) { 04139 transfer = ast_true(v->value); 04140 } else if (!strcasecmp(v->name, "threewaycalling")) { 04141 threewaycalling = ast_true(v->value); 04142 } else if (!strcasecmp(v->name, "wcardep")) { 04143 /* locate existing endpoint */ 04144 for (e = gw->endpoints; e; e = e->next) { 04145 if (!strcasecmp(v->value, e->name)) { 04146 /* endpoint already exists */ 04147 e->delme = 0; 04148 ep_reload = 1; 04149 break; 04150 } 04151 } 04152 04153 if (!e) { 04154 /* Allocate wildcard endpoint */ 04155 e = ast_calloc(1, sizeof(*e)); 04156 ep_reload = 0; 04157 } 04158 04159 if (e) { 04160 if (!ep_reload) { 04161 memset(e, 0, sizeof(struct mgcp_endpoint)); 04162 ast_mutex_init(&e->lock); 04163 ast_mutex_init(&e->rqnt_queue_lock); 04164 ast_mutex_init(&e->cmd_queue_lock); 04165 e->cap = ast_format_cap_alloc_nolock(); 04166 ast_copy_string(e->name, v->value, sizeof(e->name)); 04167 e->needaudit = 1; 04168 } 04169 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 04170 /* XXX Should we really check for uniqueness?? XXX */ 04171 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04172 ast_copy_string(e->context, context, sizeof(e->context)); 04173 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04174 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04175 ast_copy_string(e->language, language, sizeof(e->language)); 04176 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04177 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04178 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04179 if (!ast_strlen_zero(e->mailbox)) { 04180 char *mbox, *cntx; 04181 cntx = mbox = ast_strdupa(e->mailbox); 04182 strsep(&cntx, "@"); 04183 if (ast_strlen_zero(cntx)) { 04184 cntx = "default"; 04185 } 04186 e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL, 04187 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 04188 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 04189 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 04190 AST_EVENT_IE_END); 04191 } 04192 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04193 e->msgstate = -1; 04194 e->amaflags = amaflags; 04195 ast_format_cap_copy(e->cap, global_capability); 04196 e->parent = gw; 04197 e->ncs = ncs; 04198 e->dtmfmode = dtmfmode; 04199 if (!ep_reload && e->sub && e->sub->rtp) { 04200 e->dtmfmode |= MGCP_DTMF_INBAND; 04201 } 04202 e->adsi = adsi; 04203 e->type = TYPE_LINE; 04204 e->immediate = immediate; 04205 e->callgroup=cur_callergroup; 04206 e->pickupgroup=cur_pickupgroup; 04207 e->callreturn = callreturn; 04208 e->cancallforward = cancallforward; 04209 e->singlepath = singlepath; 04210 e->directmedia = directmedia; 04211 e->callwaiting = callwaiting; 04212 e->hascallwaiting = callwaiting; 04213 e->slowsequence = slowsequence; 04214 e->transfer = transfer; 04215 e->threewaycalling = threewaycalling; 04216 e->onhooktime = time(NULL); 04217 /* ASSUME we're onhook */ 04218 e->hookstate = MGCP_ONHOOK; 04219 e->chanvars = copy_vars(chanvars); 04220 if (!ep_reload) { 04221 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 04222 for (i = 0; i < MAX_SUBS; i++) { 04223 sub = ast_calloc(1, sizeof(*sub)); 04224 if (sub) { 04225 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04226 ast_mutex_init(&sub->lock); 04227 ast_mutex_init(&sub->cx_queue_lock); 04228 sub->parent = e; 04229 sub->id = i; 04230 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04231 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 04232 sub->cxmode = MGCP_CX_INACTIVE; 04233 sub->nat = nat; 04234 sub->gate = NULL; 04235 sub->sdpsent = 0; 04236 sub->next = e->sub; 04237 e->sub = sub; 04238 } else { 04239 /* XXX Should find a way to clean up our memory */ 04240 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04241 return NULL; 04242 } 04243 } 04244 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04245 /* find the end of the list */ 04246 for (sub = e->sub; sub && sub->next; sub = sub->next); 04247 /* set the last sub->next to the first sub */ 04248 sub->next = e->sub; 04249 04250 e->next = gw->endpoints; 04251 gw->endpoints = e; 04252 } 04253 } 04254 } else if (!strcasecmp(v->name, "trunk") || 04255 !strcasecmp(v->name, "line")) { 04256 04257 /* locate existing endpoint */ 04258 for (e = gw->endpoints; e; e = e->next) { 04259 if (!strcasecmp(v->value, e->name)) { 04260 /* endpoint already exists */ 04261 e->delme = 0; 04262 ep_reload = 1; 04263 break; 04264 } 04265 } 04266 04267 if (!e) { 04268 e = ast_calloc(1, sizeof(*e)); 04269 ep_reload = 0; 04270 } 04271 04272 if (e) { 04273 if (!ep_reload) { 04274 ast_mutex_init(&e->lock); 04275 ast_mutex_init(&e->rqnt_queue_lock); 04276 ast_mutex_init(&e->cmd_queue_lock); 04277 e->cap = ast_format_cap_alloc_nolock(); 04278 ast_copy_string(e->name, v->value, sizeof(e->name)); 04279 e->needaudit = 1; 04280 } 04281 /* XXX Should we really check for uniqueness?? XXX */ 04282 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 04283 ast_copy_string(e->context, context, sizeof(e->context)); 04284 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 04285 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 04286 ast_copy_string(e->language, language, sizeof(e->language)); 04287 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 04288 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 04289 ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); 04290 if (!ast_strlen_zero(mailbox)) { 04291 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 04292 } 04293 if (!ep_reload) { 04294 /* XXX potential issue due to reload */ 04295 e->msgstate = -1; 04296 e->parent = gw; 04297 } 04298 e->amaflags = amaflags; 04299 ast_format_cap_copy(e->cap, global_capability); 04300 e->dtmfmode = dtmfmode; 04301 e->ncs = ncs; 04302 e->pktcgatealloc = pktcgatealloc; 04303 e->hangupongateremove = hangupongateremove; 04304 e->adsi = adsi; 04305 e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE; 04306 e->immediate = immediate; 04307 e->callgroup=cur_callergroup; 04308 e->pickupgroup=cur_pickupgroup; 04309 e->callreturn = callreturn; 04310 e->cancallforward = cancallforward; 04311 e->directmedia = directmedia; 04312 e->singlepath = singlepath; 04313 e->callwaiting = callwaiting; 04314 e->hascallwaiting = callwaiting; 04315 e->slowsequence = slowsequence; 04316 e->transfer = transfer; 04317 e->threewaycalling = threewaycalling; 04318 04319 /* If we already have a valid chanvars, it's not a new endpoint (it's a reload), 04320 so first, free previous mem 04321 */ 04322 if (e->chanvars) { 04323 ast_variables_destroy(e->chanvars); 04324 e->chanvars = NULL; 04325 } 04326 e->chanvars = copy_vars(chanvars); 04327 04328 if (!ep_reload) { 04329 e->onhooktime = time(NULL); 04330 /* ASSUME we're onhook */ 04331 e->hookstate = MGCP_ONHOOK; 04332 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 04333 } 04334 04335 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 04336 if (!ep_reload) { 04337 sub = ast_calloc(1, sizeof(*sub)); 04338 } else { 04339 if (!sub) { 04340 sub = e->sub; 04341 } else { 04342 sub = sub->next; 04343 } 04344 } 04345 04346 if (sub) { 04347 if (!ep_reload) { 04348 ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 04349 ast_mutex_init(&sub->lock); 04350 ast_mutex_init(&sub->cx_queue_lock); 04351 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 04352 sub->parent = e; 04353 sub->id = i; 04354 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 04355 sub->cxmode = MGCP_CX_INACTIVE; 04356 sub->next = e->sub; 04357 e->sub = sub; 04358 } 04359 sub->nat = nat; 04360 } else { 04361 /* XXX Should find a way to clean up our memory */ 04362 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 04363 return NULL; 04364 } 04365 } 04366 if (!ep_reload) { 04367 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 04368 /* find the end of the list */ 04369 for (sub = e->sub; sub && sub->next; sub = sub->next); 04370 /* set the last sub->next to the first sub */ 04371 sub->next = e->sub; 04372 04373 e->next = gw->endpoints; 04374 gw->endpoints = e; 04375 } 04376 } 04377 } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) { 04378 /* just eliminate realtime warnings */ 04379 } else { 04380 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 04381 } 04382 } 04383 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 04384 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 04385 if (!gw_reload) { 04386 ast_mutex_destroy(&gw->msgs_lock); 04387 ast_free(gw); 04388 } 04389 04390 /* Return NULL */ 04391 gw_reload = 1; 04392 } else { 04393 gw->defaddr.sin_family = AF_INET; 04394 gw->addr.sin_family = AF_INET; 04395 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) { 04396 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04397 } 04398 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) { 04399 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 04400 } 04401 { 04402 struct ast_sockaddr tmp1, tmp2; 04403 struct sockaddr_in tmp3 = {0,}; 04404 04405 tmp3.sin_addr = gw->ourip; 04406 ast_sockaddr_from_sin(&tmp1, &gw->addr); 04407 ast_sockaddr_from_sin(&tmp2, &tmp3); 04408 if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) { 04409 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 04410 } else { 04411 ast_sockaddr_to_sin(&tmp2, &tmp3); 04412 gw->ourip = tmp3.sin_addr; 04413 } 04414 } 04415 } 04416 04417 if (chanvars) { 04418 ast_variables_destroy(chanvars); 04419 chanvars = NULL; 04420 } 04421 return (gw_reload ? NULL : gw); 04422 }
| static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1411 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().
01411 { 01412 switch (ind) { 01413 case AST_CONTROL_HANGUP: 01414 return "Other end has hungup"; 01415 case AST_CONTROL_RING: 01416 return "Local ring"; 01417 case AST_CONTROL_RINGING: 01418 return "Remote end is ringing"; 01419 case AST_CONTROL_ANSWER: 01420 return "Remote end has answered"; 01421 case AST_CONTROL_BUSY: 01422 return "Remote end is busy"; 01423 case AST_CONTROL_TAKEOFFHOOK: 01424 return "Make it go off hook"; 01425 case AST_CONTROL_OFFHOOK: 01426 return "Line is off hook"; 01427 case AST_CONTROL_CONGESTION: 01428 return "Congestion (circuits busy)"; 01429 case AST_CONTROL_FLASH: 01430 return "Flash hook"; 01431 case AST_CONTROL_WINK: 01432 return "Wink"; 01433 case AST_CONTROL_OPTION: 01434 return "Set a low-level option"; 01435 case AST_CONTROL_RADIO_KEY: 01436 return "Key Radio"; 01437 case AST_CONTROL_RADIO_UNKEY: 01438 return "Un-Key Radio"; 01439 } 01440 return "UNKNOWN"; 01441 }
| static struct ast_variable * copy_vars | ( | struct ast_variable * | src | ) | [static, read] |
duplicate a list of channel variables,
Definition at line 4615 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().
04616 { 04617 struct ast_variable *res = NULL, *tmp, *v = NULL; 04618 04619 for (v = src ; v ; v = v->next) { 04620 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 04621 tmp->next = res; 04622 res = tmp; 04623 } 04624 } 04625 return res; 04626 }
| static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 4486 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().
04487 { 04488 struct mgcp_subchannel *sub = e->sub->next, *s; 04489 int i; 04490 04491 for (i = 0; i < MAX_SUBS; i++) { 04492 ast_mutex_lock(&sub->lock); 04493 if (!ast_strlen_zero(sub->cxident)) { 04494 transmit_connection_del(sub); 04495 } 04496 if (sub->rtp) { 04497 ast_rtp_instance_destroy(sub->rtp); 04498 sub->rtp = NULL; 04499 } 04500 memset(sub->magic, 0, sizeof(sub->magic)); 04501 mgcp_queue_hangup(sub); 04502 dump_cmd_queues(NULL, sub); 04503 if(sub->gate) { 04504 sub->gate->tech_pvt = NULL; 04505 sub->gate->got_dq_gi = NULL; 04506 sub->gate->gate_remove = NULL; 04507 sub->gate->gate_open = NULL; 04508 } 04509 ast_mutex_unlock(&sub->lock); 04510 sub = sub->next; 04511 } 04512 04513 if (e->dsp) { 04514 ast_dsp_free(e->dsp); 04515 } 04516 04517 dump_queue(e->parent, e); 04518 dump_cmd_queues(e, NULL); 04519 04520 sub = e->sub; 04521 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04522 s = sub; 04523 sub = sub->next; 04524 ast_mutex_destroy(&s->lock); 04525 ast_mutex_destroy(&s->cx_queue_lock); 04526 ast_free(s); 04527 } 04528 04529 if (e->mwi_event_sub) 04530 ast_event_unsubscribe(e->mwi_event_sub); 04531 04532 if (e->chanvars) { 04533 ast_variables_destroy(e->chanvars); 04534 e->chanvars = NULL; 04535 } 04536 04537 ast_mutex_destroy(&e->lock); 04538 ast_mutex_destroy(&e->rqnt_queue_lock); 04539 ast_mutex_destroy(&e->cmd_queue_lock); 04540 e->cap = ast_format_cap_destroy(e->cap); 04541 ast_free(e); 04542 }
| static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4544 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().
04545 { 04546 if (g->ha) 04547 ast_free_ha(g->ha); 04548 04549 dump_queue(g, NULL); 04550 04551 ast_free(g); 04552 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3783 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.
03784 { 03785 int res; 03786 int reloading; 03787 struct mgcp_gateway *g, *gprev; 03788 /*struct mgcp_gateway *g;*/ 03789 /*struct mgcp_endpoint *e;*/ 03790 /*time_t thispass = 0, lastpass = 0;*/ 03791 time_t lastrun = 0; 03792 03793 /* Add an I/O event to our UDP socket */ 03794 if (mgcpsock > -1) { 03795 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03796 } 03797 /* This thread monitors all the frame relay interfaces which are not yet in use 03798 (and thus do not have a separate thread) indefinitely */ 03799 /* From here on out, we die whenever asked */ 03800 for (;;) { 03801 /* Check for a reload request */ 03802 ast_mutex_lock(&mgcp_reload_lock); 03803 reloading = mgcp_reloading; 03804 mgcp_reloading = 0; 03805 ast_mutex_unlock(&mgcp_reload_lock); 03806 if (reloading) { 03807 ast_verb(1, "Reloading MGCP\n"); 03808 reload_config(1); 03809 /* Add an I/O event to our UDP socket */ 03810 if (mgcpsock > -1 && !mgcpsock_read_id) { 03811 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03812 } 03813 } 03814 03815 /* Check for interfaces needing to be killed */ 03816 /* Don't let anybody kill us right away. Nobody should lock the interface list 03817 and wait for the monitor list, but the other way around is okay. */ 03818 ast_mutex_lock(&monlock); 03819 /* Lock the network interface */ 03820 ast_mutex_lock(&netlock); 03821 03822 #if 0 03823 /* XXX THIS IS COMPLETELY HOSED */ 03824 /* The gateway goes into a state of panic */ 03825 /* If the vmwi indicator is sent while it is reseting interfaces */ 03826 lastpass = thispass; 03827 thispass = time(NULL); 03828 g = gateways; 03829 while(g) { 03830 if (thispass != lastpass) { 03831 e = g->endpoints; 03832 while(e) { 03833 if (e->type == TYPE_LINE) { 03834 res = has_voicemail(e); 03835 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03836 if (res) { 03837 transmit_notify_request(e, "L/vmwi(+)"); 03838 } else { 03839 transmit_notify_request(e, "L/vmwi(-)"); 03840 } 03841 e->msgstate = res; 03842 e->onhooktime = thispass; 03843 } 03844 } 03845 e = e->next; 03846 } 03847 } 03848 g = g->next; 03849 } 03850 #endif 03851 /* pruning unused realtime gateways, running in every 60 seconds*/ 03852 if(time(NULL) > (lastrun + 60)) { 03853 ast_mutex_lock(&gatelock); 03854 g = gateways; 03855 gprev = NULL; 03856 while(g) { 03857 if(g->realtime) { 03858 if(mgcp_prune_realtime_gateway(g)) { 03859 if(gprev) { 03860 gprev->next = g->next; 03861 } else { 03862 gateways = g->next; 03863 } 03864 ast_mutex_unlock(&g->msgs_lock); 03865 ast_mutex_destroy(&g->msgs_lock); 03866 free(g); 03867 } else { 03868 ast_mutex_unlock(&g->msgs_lock); 03869 gprev = g; 03870 } 03871 } else { 03872 gprev = g; 03873 } 03874 g = g->next; 03875 } 03876 ast_mutex_unlock(&gatelock); 03877 lastrun = time(NULL); 03878 } 03879 /* Okay, now that we know what to do, release the network lock */ 03880 ast_mutex_unlock(&netlock); 03881 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03882 ast_mutex_unlock(&monlock); 03883 pthread_testcancel(); 03884 /* Wait for sched or io */ 03885 res = ast_sched_wait(sched); 03886 /* copied from chan_sip.c */ 03887 if ((res < 0) || (res > 1000)) { 03888 res = 1000; 03889 } 03890 res = ast_io_wait(io, res); 03891 ast_mutex_lock(&monlock); 03892 if (res >= 0) { 03893 ast_sched_runq(sched); 03894 } 03895 ast_mutex_unlock(&monlock); 03896 } 03897 /* Never reached */ 03898 return NULL; 03899 }
| static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub | |||
| ) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2704 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().
02705 { 02706 struct mgcp_request *t, *q; 02707 02708 if (p) { 02709 ast_mutex_lock(&p->rqnt_queue_lock); 02710 for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); 02711 p->rqnt_queue = NULL; 02712 ast_mutex_unlock(&p->rqnt_queue_lock); 02713 02714 ast_mutex_lock(&p->cmd_queue_lock); 02715 for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); 02716 p->cmd_queue = NULL; 02717 ast_mutex_unlock(&p->cmd_queue_lock); 02718 02719 ast_mutex_lock(&p->sub->cx_queue_lock); 02720 for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02721 p->sub->cx_queue = NULL; 02722 ast_mutex_unlock(&p->sub->cx_queue_lock); 02723 02724 ast_mutex_lock(&p->sub->next->cx_queue_lock); 02725 for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); 02726 p->sub->next->cx_queue = NULL; 02727 ast_mutex_unlock(&p->sub->next->cx_queue_lock); 02728 } else if (sub) { 02729 ast_mutex_lock(&sub->cx_queue_lock); 02730 for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); 02731 sub->cx_queue = NULL; 02732 ast_mutex_unlock(&sub->cx_queue_lock); 02733 } 02734 }
| static void dump_queue | ( | struct mgcp_gateway * | gw, | |
| struct mgcp_endpoint * | p | |||
| ) | [static] |
Definition at line 584 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().
00585 { 00586 struct mgcp_message *cur, *q = NULL, *w, *prev; 00587 00588 ast_mutex_lock(&gw->msgs_lock); 00589 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00590 if (!p || cur->owner_ep == p) { 00591 if (prev) { 00592 prev->next = cur->next; 00593 } else { 00594 gw->msgs = cur->next; 00595 } 00596 00597 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 00598 gw->name, cur->seqno); 00599 00600 w = cur; 00601 if (q) { 00602 w->next = q; 00603 } else { 00604 w->next = NULL; 00605 } 00606 q = w; 00607 } 00608 } 00609 ast_mutex_unlock(&gw->msgs_lock); 00610 00611 while (q) { 00612 cur = q; 00613 q = q->next; 00614 ast_free(cur); 00615 } 00616 }
| static int find_and_retrans | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 3604 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().
03605 { 03606 int seqno=0; 03607 time_t now; 03608 struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL; 03609 time(&now); 03610 if (sscanf(req->identifier, "%30d", &seqno) != 1) { 03611 seqno = 0; 03612 } 03613 for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) { 03614 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03615 /* Delete this entry */ 03616 if (prev) 03617 prev->next = next; 03618 else 03619 sub->parent->parent->responses = next; 03620 ast_free(cur); 03621 } else { 03622 if (seqno == cur->seqno) 03623 answer = cur; 03624 prev = cur; 03625 } 03626 } 03627 if (answer) { 03628 resend_response(sub, answer); 03629 return 1; 03630 } 03631 return 0; 03632 }
| 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 2738 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().
02740 { 02741 struct mgcp_request *prev, *req; 02742 02743 ast_mutex_lock(l); 02744 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02745 if (req->trid == ident) { 02746 /* remove from queue */ 02747 if (!prev) 02748 *queue = req->next; 02749 else 02750 prev->next = req->next; 02751 02752 /* send next pending command */ 02753 if (*queue) { 02754 ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02755 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02756 02757 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02758 } 02759 break; 02760 } 02761 } 02762 ast_mutex_unlock(l); 02763 return req; 02764 }
| static struct mgcp_gateway* find_realtime_gw | ( | char * | name, | |
| char * | at, | |||
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 1673 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().
01674 { 01675 struct mgcp_gateway *g = NULL; 01676 struct ast_variable *mgcpgwconfig = NULL; 01677 struct ast_variable *gwv, *epname = NULL; 01678 struct mgcp_endpoint *e; 01679 char lines[256]; 01680 int i, j; 01681 01682 ast_debug(1, "*** find Realtime MGCPGW\n"); 01683 01684 if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) { 01685 return NULL; 01686 } 01687 01688 if (ast_strlen_zero(at)) { 01689 ast_debug(1, "null gw name\n"); 01690 return NULL; 01691 } 01692 01693 if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) { 01694 return NULL; 01695 } 01696 01697 /*! 01698 * \note This is a fairly odd way of instantiating lines. Instead of each 01699 * line created by virtue of being in the database (and loaded via 01700 * ast_load_realtime_multientry), this code forces a specific order with a 01701 * "lines" entry in the "mgcpgw" record. This has benefits, because as with 01702 * chan_dahdi, values are inherited across definitions. The downside is 01703 * that it's not as clear what the values will be simply by looking at a 01704 * single row in the database, and it's probable that the sanest configuration 01705 * should have the first column in the "mgcpep" table be "clearvars", with a 01706 * static value of "all", if any variables are set at all. It may be worth 01707 * making this assumption explicit in the code in the future, and then just 01708 * using ast_load_realtime_multientry for the "mgcpep" records. 01709 */ 01710 lines[0] = '\0'; 01711 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) { 01712 if (!strcasecmp(gwv->name, "lines")) { 01713 ast_copy_string(lines, gwv->value, sizeof(lines)); 01714 break; 01715 } 01716 } 01717 /* Position gwv at the end of the list */ 01718 for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next); 01719 01720 if (!ast_strlen_zero(lines)) { 01721 AST_DECLARE_APP_ARGS(args, 01722 AST_APP_ARG(line)[100]; 01723 ); 01724 AST_STANDARD_APP_ARGS(args, lines); 01725 for (i = 0; i < args.argc; i++) { 01726 gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL); 01727 01728 /* Remove "line" AND position gwv at the end of the list. */ 01729 for (epname = NULL; gwv->next; gwv = gwv->next) { 01730 if (!strcasecmp(gwv->next->name, "line")) { 01731 /* Remove it from the list */ 01732 epname = gwv->next; 01733 gwv->next = gwv->next->next; 01734 } 01735 } 01736 /* Since "line" instantiates the configuration, we have to move it to the end. */ 01737 if (epname) { 01738 gwv->next = epname; 01739 epname->next = NULL; 01740 gwv = gwv->next; 01741 } 01742 } 01743 } 01744 for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) { 01745 ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value); 01746 } 01747 01748 if (mgcpgwconfig) { 01749 g = build_gateway(at, mgcpgwconfig); 01750 ast_variables_destroy(mgcpgwconfig); 01751 } 01752 if (g) { 01753 g->next = gateways; 01754 g->realtime = 1; 01755 gateways = g; 01756 for (e = g->endpoints; e; e = e->next) { 01757 transmit_audit_endpoint(e); 01758 e->needaudit = 0; 01759 } 01760 } 01761 return g; 01762 }
| static struct mgcp_subchannel* find_subchannel_and_lock | ( | char * | name, | |
| int | msgid, | |||
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 1764 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().
01765 { 01766 struct mgcp_endpoint *p = NULL; 01767 struct mgcp_subchannel *sub = NULL; 01768 struct mgcp_gateway *g; 01769 char tmp[256] = ""; 01770 char *at = NULL, *c; 01771 int found = 0; 01772 if (name) { 01773 ast_copy_string(tmp, name, sizeof(tmp)); 01774 at = strchr(tmp, '@'); 01775 if (!at) { 01776 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); 01777 return NULL; 01778 } 01779 *at++ = '\0'; 01780 } 01781 ast_mutex_lock(&gatelock); 01782 if (at && (at[0] == '[')) { 01783 at++; 01784 c = strrchr(at, ']'); 01785 if (c) { 01786 *c = '\0'; 01787 } 01788 } 01789 for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) { 01790 if ((!name || !strcasecmp(g->name, at)) && 01791 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { 01792 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ 01793 if (sin && g->dynamic && name) { 01794 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01795 (g->addr.sin_port != sin->sin_port)) { 01796 memcpy(&g->addr, sin, sizeof(g->addr)); 01797 { 01798 struct ast_sockaddr tmp1, tmp2; 01799 struct sockaddr_in tmp3 = {0,}; 01800 01801 tmp3.sin_addr = g->ourip; 01802 ast_sockaddr_from_sin(&tmp1, &g->addr); 01803 ast_sockaddr_from_sin(&tmp2, &tmp3); 01804 if (ast_ouraddrfor(&tmp1, &tmp2)) { 01805 memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 01806 } 01807 ast_sockaddr_to_sin(&tmp2, &tmp3); 01808 g->ourip = tmp3.sin_addr; 01809 } 01810 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)); 01811 } 01812 /* not dynamic, check if the name matches */ 01813 } else if (name) { 01814 if (strcasecmp(g->name, at)) { 01815 g = g->next; 01816 continue; 01817 } 01818 /* not dynamic, no name, check if the addr matches */ 01819 } else if (!name && sin) { 01820 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01821 (g->addr.sin_port != sin->sin_port)) { 01822 if(!g->next) 01823 g = find_realtime_gw(name, at, sin); 01824 else 01825 g = g->next; 01826 continue; 01827 } 01828 } else { 01829 continue; 01830 } 01831 for (p = g->endpoints; p; p = p->next) { 01832 ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name); 01833 if (msgid) { 01834 sub = p->sub; 01835 found = 1; 01836 break; 01837 } else if (name && !strcasecmp(p->name, tmp)) { 01838 ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 01839 p->name, g->name, p->sub->id); 01840 sub = p->sub; 01841 found = 1; 01842 break; 01843 } 01844 } 01845 if (sub && found) { 01846 ast_mutex_lock(&sub->lock); 01847 break; 01848 } 01849 } 01850 } 01851 ast_mutex_unlock(&gatelock); 01852 if (!sub) { 01853 if (name) { 01854 if (g) { 01855 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); 01856 } else { 01857 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); 01858 } 01859 } 01860 } 01861 return sub; 01862 }
| static char* get_csv | ( | char * | c, | |
| int * | len, | |||
| char ** | next | |||
| ) | [static] |
get_csv: (SC:) get comma separated value
Definition at line 1649 of file chan_mgcp.c.
Referenced by handle_response().
01650 { 01651 char *s; 01652 01653 *next = NULL, *len = 0; 01654 if (!c) return NULL; 01655 01656 while (*c && (*c < 33 || *c == ',')) { 01657 c++; 01658 } 01659 01660 s = c; 01661 while (*c && (*c >= 33 && *c != ',')) { 01662 c++, (*len)++; 01663 } 01664 *next = c; 01665 01666 if (*len == 0) { 01667 s = NULL, *next = NULL; 01668 } 01669 01670 return s; 01671 }
| static char* get_header | ( | struct mgcp_request * | req, | |
| char * | name | |||
| ) | [static] |
Definition at line 1642 of file chan_mgcp.c.
References __get_header().
Referenced by handle_request(), and handle_response().
01643 { 01644 int start = 0; 01645 return __get_header(req, name, &start, ""); 01646 }
| static char* get_sdp | ( | struct mgcp_request * | req, | |
| char * | name | |||
| ) | [static] |
Definition at line 1593 of file chan_mgcp.c.
References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.
Referenced by process_sdp().
01594 { 01595 int x; 01596 int len = strlen(name); 01597 char *r; 01598 01599 for (x = 0; x < req->lines; x++) { 01600 r = get_sdp_by_line(req->line[x], name, len); 01601 if (r[0] != '\0') return r; 01602 } 01603 return ""; 01604 }
| static char* get_sdp_by_line | ( | char * | line, | |
| char * | name, | |||
| int | nameLen | |||
| ) | [static] |
Definition at line 1583 of file chan_mgcp.c.
Referenced by get_sdp(), and get_sdp_iterate().
01584 { 01585 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { 01586 char *r = line + nameLen + 1; 01587 while (*r && (*r < 33)) ++r; 01588 return r; 01589 } 01590 return ""; 01591 }
| static char* get_sdp_iterate | ( | int * | iterator, | |
| struct mgcp_request * | req, | |||
| char * | name | |||
| ) | [static] |
Definition at line 1611 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().
01612 { 01613 int len = strlen(name); 01614 char *r; 01615 while (*iterator < req->lines) { 01616 r = get_sdp_by_line(req->line[(*iterator)++], name, len); 01617 if (r[0] != '\0') return r; 01618 } 01619 return ""; 01620 }
| static void handle_hd_hf | ( | struct mgcp_subchannel * | sub, | |
| char * | ev | |||
| ) | [static] |
Definition at line 3277 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().
03278 { 03279 struct mgcp_endpoint *p = sub->parent; 03280 struct ast_channel *c; 03281 pthread_t t; 03282 03283 /* Off hook / answer */ 03284 if (sub->outgoing) { 03285 /* Answered */ 03286 if (sub->owner) { 03287 if (ast_bridged_channel(sub->owner)) 03288 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03289 sub->cxmode = MGCP_CX_SENDRECV; 03290 if (!sub->rtp) { 03291 start_rtp(sub); 03292 } else { 03293 transmit_modify_request(sub); 03294 } 03295 /*transmit_notify_request(sub, "aw");*/ 03296 transmit_notify_request(sub, ""); 03297 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 03298 } 03299 } else { 03300 /* Start switch */ 03301 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 03302 if (!sub->owner) { 03303 if (!sub->rtp) { 03304 start_rtp(sub); 03305 } else { 03306 transmit_modify_request(sub); 03307 } 03308 if (p->immediate) { 03309 /* The channel is immediately up. Start right away */ 03310 #ifdef DLINK_BUGGY_FIRMWARE 03311 transmit_notify_request(sub, "rt"); 03312 #else 03313 transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt"); 03314 #endif 03315 c = mgcp_new(sub, AST_STATE_RING, NULL); 03316 if (!c) { 03317 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 03318 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03319 ast_hangup(c); 03320 } 03321 } else { 03322 if (has_voicemail(p)) { 03323 transmit_notify_request(sub, "L/sl"); 03324 } else { 03325 transmit_notify_request(sub, "L/dl"); 03326 } 03327 c = mgcp_new(sub, AST_STATE_DOWN, NULL); 03328 if (c) { 03329 if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { 03330 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 03331 ast_hangup(c); 03332 } 03333 } else { 03334 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 03335 } 03336 } 03337 } else { 03338 if (p->hookstate == MGCP_OFFHOOK) { 03339 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03340 } else { 03341 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 03342 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 03343 } 03344 if (ast_bridged_channel(sub->owner)) 03345 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 03346 sub->cxmode = MGCP_CX_SENDRECV; 03347 if (!sub->rtp) { 03348 start_rtp(sub); 03349 } else { 03350 transmit_modify_request(sub); 03351 } 03352 /*transmit_notify_request(sub, "aw");*/ 03353 transmit_notify_request(sub, ""); 03354 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03355 } 03356 } 03357 }
| static char* handle_mgcp_audit_endpoint | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1084 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.
01085 { 01086 struct mgcp_gateway *mg; 01087 struct mgcp_endpoint *me; 01088 int found = 0; 01089 char *ename,*gname, *c; 01090 01091 switch (cmd) { 01092 case CLI_INIT: 01093 e->command = "mgcp audit endpoint"; 01094 e->usage = 01095 "Usage: mgcp audit endpoint <endpointid>\n" 01096 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n" 01097 " mgcp debug MUST be on to see the results of this command.\n"; 01098 return NULL; 01099 case CLI_GENERATE: 01100 return NULL; 01101 } 01102 01103 if (!mgcpdebug) { 01104 return CLI_SHOWUSAGE; 01105 } 01106 if (a->argc != 4) 01107 return CLI_SHOWUSAGE; 01108 /* split the name into parts by null */ 01109 ename = ast_strdupa(a->argv[3]); 01110 for (gname = ename; *gname; gname++) { 01111 if (*gname == '@') { 01112 *gname = 0; 01113 gname++; 01114 break; 01115 } 01116 } 01117 if (gname[0] == '[') { 01118 gname++; 01119 } 01120 if ((c = strrchr(gname, ']'))) { 01121 *c = '\0'; 01122 } 01123 ast_mutex_lock(&gatelock); 01124 for (mg = gateways; mg; mg = mg->next) { 01125 if (!strcasecmp(mg->name, gname)) { 01126 for (me = mg->endpoints; me; me = me->next) { 01127 if (!strcasecmp(me->name, ename)) { 01128 found = 1; 01129 transmit_audit_endpoint(me); 01130 break; 01131 } 01132 } 01133 if (found) { 01134 break; 01135 } 01136 } 01137 } 01138 if (!found) { 01139 ast_cli(a->fd, " << Could not find endpoint >> "); 01140 } 01141 ast_mutex_unlock(&gatelock); 01142 return CLI_SUCCESS; 01143 }
| static char* handle_mgcp_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1145 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.
01146 { 01147 switch (cmd) { 01148 case CLI_INIT: 01149 e->command = "mgcp set debug {on|off}"; 01150 e->usage = 01151 "Usage: mgcp set debug {on|off}\n" 01152 " Enables/Disables dumping of MGCP packets for debugging purposes\n"; 01153 return NULL; 01154 case CLI_GENERATE: 01155 return NULL; 01156 } 01157 01158 if (a->argc != e->args) 01159 return CLI_SHOWUSAGE; 01160 01161 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 01162 mgcpdebug = 1; 01163 ast_cli(a->fd, "MGCP Debugging Enabled\n"); 01164 } else if (!strncasecmp(a->argv[3], "off", 3)) { 01165 mgcpdebug = 0; 01166 ast_cli(a->fd, "MGCP Debugging Disabled\n"); 01167 } else { 01168 return CLI_SHOWUSAGE; 01169 } 01170 return CLI_SUCCESS; 01171 }
| static char* handle_mgcp_show_endpoints | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1042 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.
01043 { 01044 struct mgcp_gateway *mg; 01045 struct mgcp_endpoint *me; 01046 int hasendpoints = 0; 01047 struct ast_variable * v = NULL; 01048 01049 switch (cmd) { 01050 case CLI_INIT: 01051 e->command = "mgcp show endpoints"; 01052 e->usage = 01053 "Usage: mgcp show endpoints\n" 01054 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n"; 01055 return NULL; 01056 case CLI_GENERATE: 01057 return NULL; 01058 } 01059 01060 if (a->argc != 3) { 01061 return CLI_SHOWUSAGE; 01062 } 01063 ast_mutex_lock(&gatelock); 01064 for (mg = gateways; mg; mg = mg->next) { 01065 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"); 01066 for (me = mg->endpoints; me; me = me->next) { 01067 ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle"); 01068 if (me->chanvars) { 01069 ast_cli(a->fd, " Variables:\n"); 01070 for (v = me->chanvars ; v ; v = v->next) { 01071 ast_cli(a->fd, " %s = '%s'\n", v->name, v->value); 01072 } 01073 } 01074 hasendpoints = 1; 01075 } 01076 if (!hasendpoints) { 01077 ast_cli(a->fd, " << No Endpoints Defined >> "); 01078 } 01079 } 01080 ast_mutex_unlock(&gatelock); 01081 return CLI_SUCCESS; 01082 }
| static int handle_request | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req, | |||
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 3359 of file chan_mgcp.c.
References 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().
03360 { 03361 char *ev, *s; 03362 struct ast_frame f = { 0, }; 03363 struct mgcp_endpoint *p = sub->parent; 03364 struct mgcp_gateway *g = NULL; 03365 int res; 03366 03367 ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03368 /* Clear out potential response */ 03369 if (!strcasecmp(req->verb, "RSIP")) { 03370 /* Test if this RSIP request is just a keepalive */ 03371 if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03372 ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03373 transmit_response(sub, "200", req, "OK"); 03374 } else { 03375 dump_queue(p->parent, p); 03376 dump_cmd_queues(p, NULL); 03377 03378 if ((strcmp(p->name, p->parent->wcardep) != 0)) { 03379 ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); 03380 } 03381 /* For RSIP on wildcard we reset all endpoints */ 03382 if (!strcmp(p->name, p->parent->wcardep)) { 03383 /* Reset all endpoints */ 03384 struct mgcp_endpoint *tmp_ep; 03385 03386 g = p->parent; 03387 for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) { 03388 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03389 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03390 struct mgcp_subchannel *tmp_sub, *first_sub; 03391 ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03392 03393 first_sub = tmp_ep->sub; 03394 tmp_sub = tmp_ep->sub; 03395 while (tmp_sub) { 03396 mgcp_queue_hangup(tmp_sub); 03397 tmp_sub = tmp_sub->next; 03398 if (tmp_sub == first_sub) 03399 break; 03400 } 03401 } 03402 } 03403 } else if (sub->owner) { 03404 mgcp_queue_hangup(sub); 03405 } 03406 transmit_response(sub, "200", req, "OK"); 03407 /* We don't send NTFY or AUEP to wildcard ep */ 03408 if (strcmp(p->name, p->parent->wcardep) != 0) { 03409 transmit_notify_request(sub, ""); 03410 /* Audit endpoint. 03411 Idea is to prevent lost lines due to race conditions 03412 */ 03413 transmit_audit_endpoint(p); 03414 } 03415 } 03416 } else if (!strcasecmp(req->verb, "NTFY")) { 03417 /* Acknowledge and be sure we keep looking for the same things */ 03418 transmit_response(sub, "200", req, "OK"); 03419 /* Notified of an event */ 03420 ev = get_header(req, "O"); 03421 s = strchr(ev, '/'); 03422 if (s) ev = s + 1; 03423 ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03424 /* Keep looking for events unless this was a hangup */ 03425 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03426 transmit_notify_request(sub, p->curtone); 03427 } 03428 if (!strcasecmp(ev, "hd")) { 03429 p->hookstate = MGCP_OFFHOOK; 03430 sub->cxmode = MGCP_CX_SENDRECV; 03431 03432 if (p) { 03433 /* When the endpoint have a Off hook transition we allways 03434 starts without any previous dtmfs */ 03435 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03436 } 03437 03438 handle_hd_hf(sub, ev); 03439 } else if (!strcasecmp(ev, "hf")) { 03440 /* We can assume we are offhook if we received a hookflash */ 03441 /* First let's just do call wait and ignore threeway */ 03442 /* We're currently in charge */ 03443 if (p->hookstate != MGCP_OFFHOOK) { 03444 /* Cisco c7940 sends hf even if the phone is onhook */ 03445 /* Thanks to point on IRC for pointing this out */ 03446 return -1; 03447 } 03448 /* do not let * conference two down channels */ 03449 if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_DOWN && !sub->next->owner) 03450 return -1; 03451 03452 if (p->callwaiting || p->transfer || p->threewaycalling) { 03453 ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03454 p->sub = p->sub->next; 03455 03456 /* transfer control to our next subchannel */ 03457 if (!sub->next->owner) { 03458 /* plave the first call on hold and start up a new call */ 03459 sub->cxmode = MGCP_CX_MUTE; 03460 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03461 transmit_modify_request(sub); 03462 if (sub->owner && ast_bridged_channel(sub->owner)) 03463 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03464 sub->next->cxmode = MGCP_CX_RECVONLY; 03465 handle_hd_hf(sub->next, ev); 03466 } else if (sub->owner && sub->next->owner) { 03467 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03468 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03469 /* We made both calls lets conferenct */ 03470 ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", 03471 sub->id, sub->next->id, p->name, p->parent->name); 03472 sub->cxmode = MGCP_CX_CONF; 03473 sub->next->cxmode = MGCP_CX_CONF; 03474 if (ast_bridged_channel(sub->next->owner)) 03475 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03476 transmit_modify_request(sub); 03477 transmit_modify_request(sub->next); 03478 } else { 03479 /* Let's flipflop between calls */ 03480 /* XXX Need to check for state up ??? */ 03481 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03482 ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03483 sub->id, sub->next->id, p->name, p->parent->name); 03484 sub->cxmode = MGCP_CX_MUTE; 03485 ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03486 transmit_modify_request(sub); 03487 if (ast_bridged_channel(sub->owner)) 03488 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03489 03490 if (ast_bridged_channel(sub->next->owner)) 03491 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03492 03493 handle_hd_hf(sub->next, ev); 03494 } 03495 } else { 03496 /* We've most likely lost one of our calls find an active call and bring it up */ 03497 if (sub->owner) { 03498 p->sub = sub; 03499 } else if (sub->next->owner) { 03500 p->sub = sub->next; 03501 } else { 03502 /* We seem to have lost both our calls */ 03503 /* XXX - What do we do now? */ 03504 return -1; 03505 } 03506 if (ast_bridged_channel(p->sub->owner)) 03507 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03508 p->sub->cxmode = MGCP_CX_SENDRECV; 03509 transmit_modify_request(p->sub); 03510 } 03511 } else { 03512 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03513 p->name, p->parent->name); 03514 } 03515 } else if (!strcasecmp(ev, "hu")) { 03516 p->hookstate = MGCP_ONHOOK; 03517 sub->cxmode = MGCP_CX_RECVONLY; 03518 ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03519 /* Do we need to send MDCX before a DLCX ? 03520 if (sub->rtp) { 03521 transmit_modify_request(sub); 03522 } 03523 */ 03524 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03525 /* We're allowed to transfer, we have two avtive calls and */ 03526 /* we made at least one of the calls. Let's try and transfer */ 03527 ast_mutex_lock(&p->sub->next->lock); 03528 res = attempt_transfer(p); 03529 if (res < 0) { 03530 if (p->sub->next->owner) { 03531 sub->next->alreadygone = 1; 03532 mgcp_queue_hangup(sub->next); 03533 } 03534 } else if (res) { 03535 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03536 ast_mutex_unlock(&p->sub->next->lock); 03537 return -1; 03538 } 03539 ast_mutex_unlock(&p->sub->next->lock); 03540 } else { 03541 /* Hangup the current call */ 03542 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03543 if (sub->owner) { 03544 sub->alreadygone = 1; 03545 mgcp_queue_hangup(sub); 03546 } else { 03547 ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03548 p->name, p->parent->name, sub->id); 03549 /* Instruct the other side to remove the connection since it apparently * 03550 * still thinks the channel is active. * 03551 * For Cisco IAD2421 /BAK/ */ 03552 transmit_connection_del(sub); 03553 } 03554 } 03555 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03556 p->hidecallerid = 0; 03557 if (p->hascallwaiting && !p->callwaiting) { 03558 ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03559 p->callwaiting = -1; 03560 } 03561 if (has_voicemail(p)) { 03562 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03563 transmit_notify_request(sub, "L/vmwi(+)"); 03564 } else { 03565 ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03566 transmit_notify_request(sub, "L/vmwi(-)"); 03567 } 03568 } 03569 } else if ((strlen(ev) == 1) && 03570 (((ev[0] >= '0') && (ev[0] <= '9')) || 03571 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03572 (ev[0] == '*') || (ev[0] == '#'))) { 03573 if (sub && sub->owner && (ast_channel_state(sub->owner) >= AST_STATE_UP)) { 03574 f.frametype = AST_FRAME_DTMF; 03575 f.subclass.integer = ev[0]; 03576 f.src = "mgcp"; 03577 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03578 mgcp_queue_frame(sub, &f); 03579 ast_mutex_lock(&sub->next->lock); 03580 if (sub->next->owner) 03581 mgcp_queue_frame(sub->next, &f); 03582 ast_mutex_unlock(&sub->next->lock); 03583 if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) { 03584 memset(p->curtone, 0, sizeof(p->curtone)); 03585 } 03586 } else { 03587 p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; 03588 p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; 03589 } 03590 } else if (!strcasecmp(ev, "T")) { 03591 /* Digit timeout -- unimportant */ 03592 } else if (!strcasecmp(ev, "ping")) { 03593 /* ping -- unimportant */ 03594 } else { 03595 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03596 } 03597 } else { 03598 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03599 transmit_response(sub, "510", req, "Unknown verb"); 03600 } 03601 return 0; 03602 }
| 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 2767 of file chan_mgcp.c.
References AST_CONTROL_RINGING, ast_copy_string(), ast_free, ast_log(), ast_queue_control(), AST_STATE_RINGING, ast_strlen_zero(), ast_verb, mgcp_request::cmd, mgcp_endpoint::cmd_queue, mgcp_endpoint::cmd_queue_lock, mgcp_subchannel::cx_queue, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxident, dump_cmd_queues(), find_command(), get_csv(), get_header(), mgcp_endpoint::hookstate, mgcp_subchannel::id, len(), mgcp_request::lines, LOG_NOTICE, LOG_WARNING, MGCP_CMD_AUEP, MGCP_CMD_CRCX, MGCP_CMD_MDCX, MGCP_OFFHOOK, MGCP_ONHOOK, mgcp_queue_hangup(), mgcp_endpoint::name, mgcp_gateway::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_response().
Referenced by handle_incoming(), mgcpsock_read(), and retrans_pkt().
02769 { 02770 char *c; 02771 struct mgcp_request *req; 02772 struct mgcp_gateway *gw = p->parent; 02773 02774 if (result < 200) { 02775 /* provisional response */ 02776 return; 02777 } 02778 02779 if (p->slowsequence) 02780 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02781 else if (sub) 02782 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02783 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02784 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02785 02786 if (!req) { 02787 ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", 02788 gw->name, ident); 02789 return; 02790 } 02791 02792 if (p && (result >= 400) && (result <= 599)) { 02793 switch (result) { 02794 case 401: 02795 p->hookstate = MGCP_OFFHOOK; 02796 break; 02797 case 402: 02798 p->hookstate = MGCP_ONHOOK; 02799 break; 02800 case 406: 02801 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02802 break; 02803 case 407: 02804 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02805 break; 02806 } 02807 if (sub) { 02808 if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) { 02809 ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result); 02810 transmit_connection_del(sub); 02811 } 02812 if (sub->owner) { 02813 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02814 result, p->name, p->parent->name, sub ? sub->id:-1); 02815 mgcp_queue_hangup(sub); 02816 } 02817 } else { 02818 if (p->sub->next->owner) { 02819 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02820 result, p->name, p->parent->name, sub ? sub->id:-1); 02821 mgcp_queue_hangup(p->sub); 02822 } 02823 02824 if (p->sub->owner) { 02825 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02826 result, p->name, p->parent->name, sub ? sub->id:-1); 02827 mgcp_queue_hangup(p->sub); 02828 } 02829 02830 dump_cmd_queues(p, NULL); 02831 } 02832 } 02833 02834 if (resp) { 02835 /* responseAck: */ 02836 if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) { 02837 if (sub) { 02838 transmit_response(sub, "000", resp, "OK"); 02839 if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_RINGING) { 02840 ast_queue_control(sub->owner, AST_CONTROL_RINGING); 02841 } 02842 } 02843 } 02844 if (req->cmd == MGCP_CMD_CRCX) { 02845 if ((c = get_header(resp, "I"))) { 02846 if (!ast_strlen_zero(c) && sub) { 02847 /* if we are hanging up do not process this conn. */ 02848 if (sub->owner) { 02849 if (!ast_strlen_zero(sub->cxident)) { 02850 if (strcasecmp(c, sub->cxident)) { 02851 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02852 } 02853 } 02854 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02855 if (sub->tmpdest.sin_addr.s_addr) { 02856 transmit_modify_with_sdp(sub, NULL, 0); 02857 } 02858 } else { 02859 /* XXX delete this one 02860 callid and conn id may already be lost. 02861 so the following del conn may have a side effect of 02862 cleaning up the next subchannel */ 02863 transmit_connection_del(sub); 02864 } 02865 } 02866 } 02867 } 02868 02869 if (req->cmd == MGCP_CMD_AUEP) { 02870 /* check stale connection ids */ 02871 if ((c = get_header(resp, "I"))) { 02872 char *v, *n; 02873 int len; 02874 while ((v = get_csv(c, &len, &n))) { 02875 if (len) { 02876 if (strncasecmp(v, p->sub->cxident, len) && 02877 strncasecmp(v, p->sub->next->cxident, len)) { 02878 /* connection id not found. delete it */ 02879 char cxident[80] = ""; 02880 02881 if (len > (sizeof(cxident) - 1)) 02882 len = sizeof(cxident) - 1; 02883 ast_copy_string(cxident, v, len); 02884 ast_verb(3, "Non existing connection id %s on %s@%s \n", 02885 cxident, p->name, gw->name); 02886 transmit_connection_del_w_params(p, NULL, cxident); 02887 } 02888 } 02889 c = n; 02890 } 02891 } 02892 02893 /* Try to determine the hookstate returned from an audit endpoint command */ 02894 if ((c = get_header(resp, "ES"))) { 02895 if (!ast_strlen_zero(c)) { 02896 if (strstr(c, "hu")) { 02897 if (p->hookstate != MGCP_ONHOOK) { 02898 /* XXX cleanup if we think we are offhook XXX */ 02899 if ((p->sub->owner || p->sub->next->owner ) && 02900 p->hookstate == MGCP_OFFHOOK) 02901 mgcp_queue_hangup(sub); 02902 p->hookstate = MGCP_ONHOOK; 02903 02904 /* update the requested events according to the new hookstate */ 02905 transmit_notify_request(p->sub, ""); 02906 02907 ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02908 } 02909 } else if (strstr(c, "hd")) { 02910 if (p->hookstate != MGCP_OFFHOOK) { 02911 p->hookstate = MGCP_OFFHOOK; 02912 02913 /* update the requested events according to the new hookstate */ 02914 transmit_notify_request(p->sub, ""); 02915 02916 ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02917 } 02918 } 02919 } 02920 } 02921 } 02922 02923 if (resp && resp->lines) { 02924 /* do not process sdp if we are hanging up. this may be a late response */ 02925 if (sub && sub->owner) { 02926 if (!sub->rtp) 02927 start_rtp(sub); 02928 if (sub->rtp) 02929 process_sdp(sub, resp); 02930 } 02931 } 02932 } 02933 02934 ast_free(req); 02935 }
| static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 495 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().
00496 { 00497 int new_msgs; 00498 struct ast_event *event; 00499 char *mbox, *cntx; 00500 00501 cntx = mbox = ast_strdupa(p->mailbox); 00502 strsep(&cntx, "@"); 00503 if (ast_strlen_zero(cntx)) 00504 cntx = "default"; 00505 00506 event = ast_event_get_cached(AST_EVENT_MWI, 00507 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, 00508 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, 00509 AST_EVENT_IE_END); 00510 00511 if (event) { 00512 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 00513 ast_event_destroy(event); 00514 } else 00515 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 00516 00517 return new_msgs; 00518 }
| static int init_req | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_request * | req, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2119 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().
02120 { 02121 /* Initialize a response */ 02122 if (req->headers || req->len) { 02123 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02124 return -1; 02125 } 02126 req->header[req->headers] = req->data + req->len; 02127 /* check if we need brackets around the gw name */ 02128 if (p->parent->isnamedottedip) { 02129 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" : ""); 02130 } else { 02131 + 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" : ""); 02132 } 02133 req->len += strlen(req->header[req->headers]); 02134 if (req->headers < MGCP_MAX_HEADERS) { 02135 req->headers++; 02136 } else { 02137 ast_log(LOG_WARNING, "Out of header space\n"); 02138 } 02139 return 0; 02140 }
| static int init_resp | ( | struct mgcp_request * | req, | |
| char * | resp, | |||
| struct mgcp_request * | orig, | |||
| char * | resprest | |||
| ) | [static] |
Definition at line 2101 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().
02102 { 02103 /* Initialize a response */ 02104 if (req->headers || req->len) { 02105 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 02106 return -1; 02107 } 02108 req->header[req->headers] = req->data + req->len; 02109 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 02110 req->len += strlen(req->header[req->headers]); 02111 if (req->headers < MGCP_MAX_HEADERS) { 02112 req->headers++; 02113 } else { 02114 ast_log(LOG_WARNING, "Out of header space\n"); 02115 } 02116 return 0; 02117 }
| static int load_module | ( | void | ) | [static] |
Load the module.
Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
Definition at line 4813 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().
04814 { 04815 struct ast_format tmpfmt; 04816 04817 if (!(global_capability = ast_format_cap_alloc())) { 04818 return AST_MODULE_LOAD_FAILURE; 04819 } 04820 if (!(mgcp_tech.capabilities = ast_format_cap_alloc())) { 04821 return AST_MODULE_LOAD_FAILURE; 04822 } 04823 ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 04824 ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0)); 04825 ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)); 04826 if (!(sched = ast_sched_context_create())) { 04827 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 04828 return AST_MODULE_LOAD_FAILURE; 04829 } 04830 04831 if (!(io = io_context_create())) { 04832 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 04833 ast_sched_context_destroy(sched); 04834 return AST_MODULE_LOAD_FAILURE; 04835 } 04836 04837 if (reload_config(0)) 04838 return AST_MODULE_LOAD_DECLINE; 04839 04840 /* Make sure we can register our mgcp channel type */ 04841 if (ast_channel_register(&mgcp_tech)) { 04842 ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); 04843 io_context_destroy(io); 04844 ast_sched_context_destroy(sched); 04845 return AST_MODULE_LOAD_FAILURE; 04846 } 04847 04848 ast_rtp_glue_register(&mgcp_rtp_glue); 04849 ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); 04850 04851 /* And start the monitor for the first time */ 04852 restart_monitor(); 04853 04854 return AST_MODULE_LOAD_SUCCESS; 04855 }
| static int mgcp_alloc_pktcgate | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2430 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().
02431 { 02432 struct mgcp_endpoint *p = sub->parent; 02433 sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr), 02434 8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove); 02435 02436 if (!sub->gate) { 02437 return 0; 02438 } 02439 sub->gate->tech_pvt = sub; 02440 sub->gate->gate_open = &mgcp_pktcgate_open; 02441 return 1; 02442 }
| static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1180 of file chan_mgcp.c.
References ast_channel_name(), ast_channel_tech_pvt(), 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, transmit_modify_request(), and transmit_notify_request().
01181 { 01182 int res = 0; 01183 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 01184 struct mgcp_endpoint *p = sub->parent; 01185 01186 ast_mutex_lock(&sub->lock); 01187 sub->cxmode = MGCP_CX_SENDRECV; 01188 if (!sub->rtp) { 01189 start_rtp(sub); 01190 } else { 01191 transmit_modify_request(sub); 01192 } 01193 ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", 01194 ast_channel_name(ast), p->name, p->parent->name, sub->id); 01195 if (ast_channel_state(ast) != AST_STATE_UP) { 01196 ast_setstate(ast, AST_STATE_UP); 01197 ast_debug(1, "mgcp_answer(%s)\n", ast_channel_name(ast)); 01198 transmit_notify_request(sub, ""); 01199 transmit_modify_request(sub); 01200 } 01201 ast_mutex_unlock(&sub->lock); 01202 return res; 01203 }
| static int mgcp_call | ( | struct ast_channel * | ast, | |
| const char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 840 of file chan_mgcp.c.
References ast_channel_connected(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_varshead(), 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, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, S_COR, start_rtp(), sub, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, and TYPE_LINE.
00841 { 00842 int res; 00843 struct mgcp_endpoint *p; 00844 struct mgcp_subchannel *sub; 00845 char tone[50] = ""; 00846 const char *distinctive_ring = NULL; 00847 struct varshead *headp; 00848 struct ast_var_t *current; 00849 00850 ast_debug(3, "MGCP mgcp_call(%s)\n", ast_channel_name(ast)); 00851 sub = ast_channel_tech_pvt(ast); 00852 p = sub->parent; 00853 headp = ast_channel_varshead(ast); 00854 AST_LIST_TRAVERSE(headp,current,entries) { 00855 /* Check whether there is an ALERT_INFO variable */ 00856 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { 00857 distinctive_ring = ast_var_value(current); 00858 } 00859 } 00860 00861 ast_mutex_lock(&sub->lock); 00862 switch (p->hookstate) { 00863 case MGCP_OFFHOOK: 00864 if (!ast_strlen_zero(distinctive_ring)) { 00865 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); 00866 ast_debug(3, "MGCP distinctive callwait %s\n", tone); 00867 } else { 00868 ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone)); 00869 ast_debug(3, "MGCP normal callwait %s\n", tone); 00870 } 00871 break; 00872 case MGCP_ONHOOK: 00873 default: 00874 if (!ast_strlen_zero(distinctive_ring)) { 00875 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); 00876 ast_debug(3, "MGCP distinctive ring %s\n", tone); 00877 } else { 00878 ast_copy_string(tone, "L/rg", sizeof(tone)); 00879 ast_debug(3, "MGCP default ring\n"); 00880 } 00881 break; 00882 } 00883 00884 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) { 00885 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast_channel_name(ast)); 00886 ast_mutex_unlock(&sub->lock); 00887 return -1; 00888 } 00889 00890 res = 0; 00891 sub->outgoing = 1; 00892 sub->cxmode = MGCP_CX_RECVONLY; 00893 ast_setstate(ast, AST_STATE_RINGING); 00894 if (p->type == TYPE_LINE) { 00895 if (!sub->rtp) { 00896 start_rtp(sub); 00897 } else { 00898 transmit_modify_request(sub); 00899 } 00900 00901 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00902 /* try to prevent a callwait from disturbing the other connection */ 00903 sub->next->cxmode = MGCP_CX_RECVONLY; 00904 transmit_modify_request(sub->next); 00905 } 00906 00907 transmit_notify_request_with_callerid(sub, tone, 00908 S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""), 00909 S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, "")); 00910 ast_setstate(ast, AST_STATE_RINGING); 00911 00912 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00913 /* Put the connection back in sendrecv */ 00914 sub->next->cxmode = MGCP_CX_SENDRECV; 00915 transmit_modify_request(sub->next); 00916 } 00917 } else { 00918 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); 00919 res = -1; 00920 } 00921 ast_mutex_unlock(&sub->lock); 00922 return res; 00923 }
| 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 1365 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.
01366 { 01367 struct mgcp_gateway *g; 01368 struct mgcp_endpoint *e = NULL; 01369 char *tmp, *endpt, *gw; 01370 int ret = AST_DEVICE_INVALID; 01371 01372 endpt = ast_strdupa(data); 01373 if ((tmp = strchr(endpt, '@'))) { 01374 *tmp++ = '\0'; 01375 gw = tmp; 01376 } else 01377 goto error; 01378 01379 ast_mutex_lock(&gatelock); 01380 for (g = gateways; g; g = g->next) { 01381 if (strcasecmp(g->name, gw) == 0) { 01382 e = g->endpoints; 01383 break; 01384 } 01385 } 01386 01387 if (!e) 01388 goto error; 01389 01390 for (; e; e = e->next) { 01391 if (strcasecmp(e->name, endpt) == 0) { 01392 break; 01393 } 01394 } 01395 01396 if (!e) 01397 goto error; 01398 01399 /* 01400 * As long as the gateway/endpoint is valid, we'll 01401 * assume that the device is available and its state 01402 * can be tracked. 01403 */ 01404 ret = AST_DEVICE_UNKNOWN; 01405 01406 error: 01407 ast_mutex_unlock(&gatelock); 01408 return ret; 01409 }
| static int mgcp_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 1287 of file chan_mgcp.c.
References ast_channel_name(), ast_channel_tech_pvt(), ast_log(), ast_mutex_lock, ast_mutex_unlock, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_subchannel::owner, and sub.
01288 { 01289 struct mgcp_subchannel *sub = ast_channel_tech_pvt(newchan); 01290 01291 ast_mutex_lock(&sub->lock); 01292 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan)); 01293 if (sub->owner != oldchan) { 01294 ast_mutex_unlock(&sub->lock); 01295 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01296 return -1; 01297 } 01298 sub->owner = newchan; 01299 ast_mutex_unlock(&sub->lock); 01300 return 0; 01301 }
| static void mgcp_get_codec | ( | struct ast_channel * | chan, | |
| struct ast_format_cap * | result | |||
| ) | [static] |
Definition at line 4451 of file chan_mgcp.c.
References ast_channel_tech_pvt(), ast_format_cap_copy(), mgcp_endpoint::cap, mgcp_subchannel::parent, and sub.
04452 { 04453 struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan); 04454 struct mgcp_endpoint *p = sub->parent; 04455 ast_format_cap_copy(result, p->cap); 04456 }
| static enum ast_rtp_glue_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp_instance ** | instance | |||
| ) | [static] |
Definition at line 4424 of file chan_mgcp.c.
References ao2_ref, ast_channel_tech_pvt(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, mgcp_endpoint::directmedia, mgcp_subchannel::parent, mgcp_subchannel::rtp, and sub.
04425 { 04426 struct mgcp_subchannel *sub = NULL; 04427 04428 if (!(sub = ast_channel_tech_pvt(chan)) || !(sub->rtp)) 04429 return AST_RTP_GLUE_RESULT_FORBID; 04430 04431 *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL; 04432 04433 if (sub->parent->directmedia) 04434 return AST_RTP_GLUE_RESULT_REMOTE; 04435 else 04436 return AST_RTP_GLUE_RESULT_LOCAL; 04437 }
| static int mgcp_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 925 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_channel_caller(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), 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, 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, 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, name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pktcgatealloc, mgcp_subchannel::rtp, S_COR, cops_gate::state, mgcp_endpoint::sub, sub, cops_gate::tech_pvt, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid().
00926 { 00927 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 00928 struct mgcp_endpoint *p = sub->parent; 00929 struct ast_channel *bridged; 00930 00931 ast_debug(1, "mgcp_hangup(%s)\n", ast_channel_name(ast)); 00932 if (!ast_channel_tech_pvt(ast)) { 00933 ast_debug(1, "Asked to hangup channel not connected\n"); 00934 return 0; 00935 } 00936 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) { 00937 ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n"); 00938 return 0; 00939 } 00940 ast_mutex_lock(&sub->lock); 00941 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast_channel_name(ast), p->name, p->parent->name); 00942 00943 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) { 00944 /* check whether other channel is active. */ 00945 if (!sub->next->owner) { 00946 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 00947 p->dtmfmode &= ~MGCP_DTMF_INBAND; 00948 } 00949 ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name); 00950 ast_dsp_free(p->dsp); 00951 p->dsp = NULL; 00952 } 00953 } 00954 00955 sub->owner = NULL; 00956 00957 /* for deleting gate */ 00958 if (p->pktcgatealloc && sub->gate) { 00959 sub->gate->gate_open = NULL; 00960 sub->gate->gate_remove = NULL; 00961 sub->gate->got_dq_gi = NULL; 00962 sub->gate->tech_pvt = NULL; 00963 if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) { 00964 ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL); 00965 } else { 00966 sub->gate->deltimer = time(NULL) + 5; 00967 } 00968 sub->gate = NULL; 00969 } 00970 00971 if (!ast_strlen_zero(sub->cxident)) { 00972 transmit_connection_del(sub); 00973 } 00974 sub->cxident[0] = '\0'; 00975 if ((sub == p->sub) && sub->next->owner) { 00976 if (p->hookstate == MGCP_OFFHOOK) { 00977 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00978 /* ncs fix! */ 00979 bridged = ast_bridged_channel(sub->next->owner); 00980 transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"), 00981 S_COR(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""), 00982 S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->id.name.str, "")); 00983 } 00984 } else { 00985 /* set our other connection as the primary and swith over to it */ 00986 p->sub = sub->next; 00987 p->sub->cxmode = MGCP_CX_RECVONLY; 00988 transmit_modify_request(p->sub); 00989 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 00990 bridged = ast_bridged_channel(sub->next->owner); 00991 transmit_notify_request_with_callerid(p->sub, "L/rg", 00992 S_COR(ast_channel_caller(bridged)->id.number.valid, ast_channel_caller(bridged)->id.number.str, ""), 00993 S_COR(ast_channel_caller(bridged)->id.name.valid, ast_channel_caller(bridged)->id.name.str, "")); 00994 } 00995 } 00996 00997 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) { 00998 transmit_notify_request(sub, p->ncs ? "" : "L/v"); 00999 } else if (p->hookstate == MGCP_OFFHOOK) { 01000 transmit_notify_request(sub, "L/ro"); 01001 } else { 01002 transmit_notify_request(sub, ""); 01003 } 01004 01005 ast_channel_tech_pvt_set(ast, NULL); 01006 sub->alreadygone = 0; 01007 sub->outgoing = 0; 01008 sub->cxmode = MGCP_CX_INACTIVE; 01009 sub->callid[0] = '\0'; 01010 if (p) { 01011 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 01012 } 01013 /* Reset temporary destination */ 01014 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 01015 if (sub->rtp) { 01016 ast_rtp_instance_destroy(sub->rtp); 01017 sub->rtp = NULL; 01018 } 01019 01020 ast_module_unref(ast_module_info->self); 01021 01022 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) { 01023 p->hidecallerid = 0; 01024 if (p->hascallwaiting && !p->callwaiting) { 01025 ast_verb(3, "Enabling call waiting on %s\n", ast_channel_name(ast)); 01026 p->callwaiting = -1; 01027 } 01028 if (has_voicemail(p)) { 01029 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 01030 ast_channel_name(ast), p->name, p->parent->name); 01031 transmit_notify_request(sub, "L/vmwi(+)"); 01032 } else { 01033 ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 01034 ast_channel_name(ast), p->name, p->parent->name); 01035 transmit_notify_request(sub, "L/vmwi(-)"); 01036 } 01037 } 01038 ast_mutex_unlock(&sub->lock); 01039 return 0; 01040 }
| static int mgcp_indicate | ( | struct ast_channel * | ast, | |
| int | ind, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 1443 of file chan_mgcp.c.
References ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, 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, transmit_modify_request(), and transmit_notify_request().
01444 { 01445 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 01446 int res = 0; 01447 01448 ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", 01449 ind, control2str(ind), ast_channel_name(ast)); 01450 ast_mutex_lock(&sub->lock); 01451 switch(ind) { 01452 case AST_CONTROL_RINGING: 01453 #ifdef DLINK_BUGGY_FIRMWARE 01454 transmit_notify_request(sub, "rt"); 01455 #else 01456 if (!sub->sdpsent) { /* will hide the inband progress!!! */ 01457 transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt"); 01458 } 01459 #endif 01460 break; 01461 case AST_CONTROL_BUSY: 01462 transmit_notify_request(sub, "L/bz"); 01463 break; 01464 case AST_CONTROL_INCOMPLETE: 01465 /* We do not currently support resetting of the Interdigit Timer, so treat 01466 * Incomplete control frames as a congestion response 01467 */ 01468 case AST_CONTROL_CONGESTION: 01469 transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg"); 01470 break; 01471 case AST_CONTROL_HOLD: 01472 ast_moh_start(ast, data, NULL); 01473 break; 01474 case AST_CONTROL_UNHOLD: 01475 ast_moh_stop(ast); 01476 break; 01477 case AST_CONTROL_SRCUPDATE: 01478 ast_rtp_instance_update_source(sub->rtp); 01479 break; 01480 case AST_CONTROL_SRCCHANGE: 01481 ast_rtp_instance_change_source(sub->rtp); 01482 break; 01483 case AST_CONTROL_PROGRESS: 01484 case AST_CONTROL_PROCEEDING: 01485 transmit_modify_request(sub); 01486 case -1: 01487 transmit_notify_request(sub, ""); 01488 break; 01489 default: 01490 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); 01491 /* fallthrough */ 01492 case AST_CONTROL_PVT_CAUSE_CODE: 01493 res = -1; 01494 } 01495 ast_mutex_unlock(&sub->lock); 01496 return res; 01497 }
| static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, | |
| int | state, | |||
| const char * | linkedid | |||
| ) | [static, read] |
Definition at line 1499 of file chan_mgcp.c.
References mgcp_endpoint::accountcode, mgcp_endpoint::adsi, mgcp_endpoint::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_adsicpe_set(), ast_channel_alloc, ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_writeformat(), 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, ast_party_id::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, pbx_builtin_setvar_helper(), mgcp_endpoint::pickupgroup, mgcp_subchannel::rtp, ast_party_number::str, ast_party_number::valid, and ast_variable::value.
Referenced by handle_hd_hf(), and mgcp_request().
01500 { 01501 struct ast_channel *tmp; 01502 struct ast_variable *v = NULL; 01503 struct mgcp_endpoint *i = sub->parent; 01504 struct ast_format tmpfmt; 01505 01506 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); 01507 if (tmp) { 01508 ast_channel_tech_set(tmp, &mgcp_tech); 01509 ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap); 01510 if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) { 01511 ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability); 01512 } 01513 if (sub->rtp) { 01514 ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0)); 01515 } 01516 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { 01517 i->dsp = ast_dsp_new(); 01518 ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); 01519 /* this is to prevent clipping of dtmf tones during dsp processing */ 01520 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); 01521 } else { 01522 i->dsp = NULL; 01523 } 01524 if (state == AST_STATE_RING) 01525 ast_channel_rings_set(tmp, 1); 01526 01527 ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt); 01528 ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt); 01529 ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt); 01530 ast_format_copy(ast_channel_readformat(tmp), &tmpfmt); 01531 ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt); 01532 ast_channel_tech_pvt_set(tmp, sub); 01533 if (!ast_strlen_zero(i->language)) 01534 ast_channel_language_set(tmp, i->language); 01535 if (!ast_strlen_zero(i->accountcode)) 01536 ast_channel_accountcode_set(tmp, i->accountcode); 01537 if (i->amaflags) 01538 ast_channel_amaflags_set(tmp, i->amaflags); 01539 sub->owner = tmp; 01540 ast_module_ref(ast_module_info->self); 01541 ast_channel_callgroup_set(tmp, i->callgroup); 01542 ast_channel_pickupgroup_set(tmp, i->pickupgroup); 01543 ast_channel_call_forward_set(tmp, i->call_forward); 01544 ast_channel_context_set(tmp, i->context); 01545 ast_channel_exten_set(tmp, i->exten); 01546 01547 /* Don't use ast_set_callerid() here because it will 01548 * generate a needless NewCallerID event */ 01549 if (!ast_strlen_zero(i->cid_num)) { 01550 ast_channel_caller(tmp)->ani.number.valid = 1; 01551 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num); 01552 } 01553 01554 if (!i->adsi) { 01555 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE); 01556 } 01557 ast_channel_priority_set(tmp, 1); 01558 01559 /* Set channel variables for this call from configuration */ 01560 for (v = i->chanvars ; v ; v = v->next) { 01561 char valuebuf[1024]; 01562 pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf))); 01563 } 01564 01565 if (sub->rtp) { 01566 ast_jb_configure(tmp, &global_jbconf); 01567 } 01568 if (state != AST_STATE_DOWN) { 01569 if (ast_pbx_start(tmp)) { 01570 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp)); 01571 ast_hangup(tmp); 01572 tmp = NULL; 01573 } 01574 } 01575 ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", 01576 ast_channel_name(tmp), ast_state2str(state)); 01577 } else { 01578 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01579 } 01580 return tmp; 01581 }
| static int mgcp_pktcgate_open | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2417 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().
02418 { 02419 struct mgcp_subchannel *sub = gate->tech_pvt; 02420 if (!sub) { 02421 return 1; 02422 } 02423 ast_mutex_lock(&sub->lock); 02424 ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid); 02425 if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0); 02426 ast_mutex_unlock(&sub->lock); 02427 return 1; 02428 }
| static int mgcp_pktcgate_remove | ( | struct cops_gate * | gate | ) | [static] |
Definition at line 2394 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().
02395 { 02396 struct mgcp_subchannel *sub = gate->tech_pvt; 02397 02398 if (!sub) { 02399 return 1; 02400 } 02401 02402 ast_mutex_lock(&sub->lock); 02403 ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid); 02404 if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) { 02405 sub->gate = NULL; 02406 if (sub->owner) { 02407 ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL); 02408 ast_channel_unlock(sub->owner); 02409 } 02410 } else { 02411 sub->gate = NULL; 02412 } 02413 ast_mutex_unlock(&sub->lock); 02414 return 1; 02415 }
| static int mgcp_postrequest | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub, | |||
| char * | data, | |||
| int | len, | |||
| unsigned int | seqno | |||
| ) | [static] |
Definition at line 713 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().
00715 { 00716 struct mgcp_message *msg; 00717 struct mgcp_message *cur; 00718 struct mgcp_gateway *gw; 00719 struct timeval now; 00720 00721 if (!(msg = ast_malloc(sizeof(*msg) + len))) { 00722 return -1; 00723 } 00724 if (!(gw = ((p && p->parent) ? p->parent : NULL))) { 00725 ast_free(msg); 00726 return -1; 00727 } 00728 00729 msg->owner_sub = sub; 00730 msg->owner_ep = p; 00731 msg->seqno = seqno; 00732 msg->next = NULL; 00733 msg->len = len; 00734 msg->retrans = 0; 00735 memcpy(msg->buf, data, msg->len); 00736 00737 ast_mutex_lock(&gw->msgs_lock); 00738 for (cur = gw->msgs; cur && cur->next; cur = cur->next); 00739 if (cur) { 00740 cur->next = msg; 00741 } else { 00742 gw->msgs = msg; 00743 } 00744 00745 now = ast_tvnow(); 00746 msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS; 00747 00748 if (gw->retransid == -1) 00749 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw); 00750 ast_mutex_unlock(&gw->msgs_lock); 00751 __mgcp_xmit(gw, msg->buf, msg->len); 00752 /* XXX Should schedule retransmission XXX */ 00753 return 0; 00754 }
| static int mgcp_prune_realtime_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 3725 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().
03726 { 03727 struct mgcp_endpoint *enext, *e; 03728 struct mgcp_subchannel *s, *sub; 03729 int i, prune = 1; 03730 03731 if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) { 03732 ast_mutex_unlock(&g->msgs_lock); 03733 return 0; 03734 } 03735 03736 for (e = g->endpoints; e; e = e->next) { 03737 ast_mutex_lock(&e->lock); 03738 if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) { 03739 prune = 0; 03740 } else if (e->rqnt_queue || e->cmd_queue) { 03741 prune = 0; 03742 } 03743 s = e->sub; 03744 for (i = 0; (i < MAX_SUBS) && s; i++) { 03745 ast_mutex_lock(&s->lock); 03746 if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) { 03747 prune = 0; 03748 } else if (s->cx_queue) { 03749 prune = 0; 03750 } 03751 s = s->next; 03752 } 03753 } 03754 03755 for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) { 03756 for (i = 0; (i < MAX_SUBS) && sub; i++) { 03757 s = sub; 03758 sub = sub->next; 03759 ast_mutex_unlock(&s->lock); 03760 ast_mutex_unlock(&s->cx_queue_lock); 03761 if (prune) { 03762 ast_mutex_destroy(&s->lock); 03763 ast_mutex_destroy(&s->cx_queue_lock); 03764 free(s); 03765 } 03766 } 03767 ast_mutex_unlock(&e->lock); 03768 ast_mutex_unlock(&e->rqnt_queue_lock); 03769 ast_mutex_unlock(&e->cmd_queue_lock); 03770 if (prune) { 03771 ast_mutex_destroy(&e->lock); 03772 ast_mutex_destroy(&e->rqnt_queue_lock); 03773 ast_mutex_destroy(&e->cmd_queue_lock); 03774 free(e); 03775 } 03776 } 03777 if (prune) { 03778 ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name); 03779 } 03780 return prune; 03781 }
| static void mgcp_queue_control | ( | struct mgcp_subchannel * | sub, | |
| int | control | |||
| ) | [static] |
Definition at line 652 of file chan_mgcp.c.
References AST_FRAME_CONTROL, and mgcp_queue_frame().
Referenced by handle_hd_hf().
00653 { 00654 struct ast_frame f = { AST_FRAME_CONTROL, { control } }; 00655 return mgcp_queue_frame(sub, &f); 00656 }
| static void mgcp_queue_frame | ( | struct mgcp_subchannel * | sub, | |
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 618 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().
00619 { 00620 for (;;) { 00621 if (sub->owner) { 00622 if (!ast_channel_trylock(sub->owner)) { 00623 ast_queue_frame(sub->owner, f); 00624 ast_channel_unlock(sub->owner); 00625 break; 00626 } else { 00627 DEADLOCK_AVOIDANCE(&sub->lock); 00628 } 00629 } else { 00630 break; 00631 } 00632 } 00633 }
| static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 635 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().
00636 { 00637 for (;;) { 00638 if (sub->owner) { 00639 if (!ast_channel_trylock(sub->owner)) { 00640 ast_queue_hangup(sub->owner); 00641 ast_channel_unlock(sub->owner); 00642 break; 00643 } else { 00644 DEADLOCK_AVOIDANCE(&sub->lock); 00645 } 00646 } else { 00647 break; 00648 } 00649 } 00650 }
| static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1236 of file chan_mgcp.c.
References ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, f, mgcp_subchannel::lock, mgcp_rtp_read(), and sub.
01237 { 01238 struct ast_frame *f; 01239 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 01240 ast_mutex_lock(&sub->lock); 01241 f = mgcp_rtp_read(sub); 01242 ast_mutex_unlock(&sub->lock); 01243 return f; 01244 }
| static char * mgcp_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4857 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().
04858 { 04859 static int deprecated = 0; 04860 04861 if (e) { 04862 switch (cmd) { 04863 case CLI_INIT: 04864 e->command = "mgcp reload"; 04865 e->usage = 04866 "Usage: mgcp reload\n" 04867 " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; 04868 return NULL; 04869 case CLI_GENERATE: 04870 return NULL; 04871 } 04872 } 04873 04874 if (!deprecated && a && a->argc > 0) { 04875 ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); 04876 deprecated = 1; 04877 } 04878 04879 ast_mutex_lock(&mgcp_reload_lock); 04880 if (mgcp_reloading) { 04881 ast_verbose("Previous mgcp reload not yet done\n"); 04882 } else { 04883 mgcp_reloading = 1; 04884 } 04885 ast_mutex_unlock(&mgcp_reload_lock); 04886 restart_monitor(); 04887 return CLI_SUCCESS; 04888 }
| 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 3930 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().
03931 { 03932 struct mgcp_subchannel *sub; 03933 struct ast_channel *tmpc = NULL; 03934 char tmp[256]; 03935 03936 if (!(ast_format_cap_has_joint(cap, global_capability))) { 03937 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap)); 03938 /*return NULL;*/ 03939 } 03940 ast_copy_string(tmp, dest, sizeof(tmp)); 03941 if (ast_strlen_zero(tmp)) { 03942 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); 03943 return NULL; 03944 } 03945 if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) { 03946 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); 03947 *cause = AST_CAUSE_UNREGISTERED; 03948 return NULL; 03949 } 03950 03951 ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); 03952 ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 03953 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); 03954 /* Must be busy */ 03955 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || 03956 ((!sub->parent->callwaiting) && (sub->owner)) || 03957 (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { 03958 if (sub->parent->hookstate == MGCP_ONHOOK) { 03959 if (has_voicemail(sub->parent)) { 03960 transmit_notify_request(sub,"L/vmwi(+)"); 03961 } else { 03962 transmit_notify_request(sub,"L/vmwi(-)"); 03963 } 03964 } 03965 *cause = AST_CAUSE_BUSY; 03966 ast_mutex_unlock(&sub->lock); 03967 return NULL; 03968 } 03969 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL); 03970 ast_mutex_unlock(&sub->lock); 03971 if (!tmpc) 03972 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); 03973 restart_monitor(); 03974 return tmpc; 03975 }
| static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static, read] |
Definition at line 1205 of file chan_mgcp.c.
References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_writeformat(), 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, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_frame::subclass.
Referenced by mgcp_read().
01206 { 01207 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ 01208 struct ast_frame *f; 01209 01210 f = ast_rtp_instance_read(sub->rtp, 0); 01211 /* Don't send RFC2833 if we're not supposed to */ 01212 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) 01213 return &ast_null_frame; 01214 if (sub->owner) { 01215 /* We already hold the channel lock */ 01216 if (f->frametype == AST_FRAME_VOICE) { 01217 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format)) { 01218 ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format)); 01219 ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format); 01220 ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner)); 01221 ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner)); 01222 } 01223 /* Courtesy fearnor aka alex@pilosoft.com */ 01224 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { 01225 #if 0 01226 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); 01227 #endif 01228 f = ast_dsp_process(sub->owner, sub->parent->dsp, f); 01229 } 01230 } 01231 } 01232 return f; 01233 }
| static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1303 of file chan_mgcp.c.
References ast_channel_tech_pvt(), 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, and sub.
01304 { 01305 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 01306 struct mgcp_endpoint *p = sub->parent; 01307 int res = 0; 01308 01309 ast_mutex_lock(&sub->lock); 01310 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01311 ast_debug(1, "Sending DTMF using inband/hybrid\n"); 01312 res = -1; /* Let asterisk play inband indications */ 01313 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01314 ast_debug(1, "Sending DTMF using RFC2833\n"); 01315 ast_rtp_instance_dtmf_begin(sub->rtp, digit); 01316 } else { 01317 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01318 } 01319 ast_mutex_unlock(&sub->lock); 01320 01321 return res; 01322 }
| static int mgcp_senddigit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1324 of file chan_mgcp.c.
References ast_channel_tech_pvt(), 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, and transmit_notify_request().
01325 { 01326 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 01327 struct mgcp_endpoint *p = sub->parent; 01328 int res = 0; 01329 char tmp[4]; 01330 01331 ast_mutex_lock(&sub->lock); 01332 if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { 01333 ast_debug(1, "Stopping DTMF using inband/hybrid\n"); 01334 res = -1; /* Tell Asterisk to stop inband indications */ 01335 } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { 01336 ast_debug(1, "Stopping DTMF using RFC2833\n"); 01337 if (sub->parent->ncs) { 01338 tmp[0] = digit; 01339 tmp[1] = '\0'; 01340 } else { 01341 tmp[0] = 'D'; 01342 tmp[1] = '/'; 01343 tmp[2] = digit; 01344 tmp[3] = '\0'; 01345 } 01346 transmit_notify_request(sub, tmp); 01347 ast_rtp_instance_dtmf_end(sub->rtp, digit); 01348 } else { 01349 ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); 01350 } 01351 ast_mutex_unlock(&sub->lock); 01352 01353 return res; 01354 }
| 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 4439 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_channel_tech_pvt(), sub, and transmit_modify_with_sdp().
04440 { 04441 /* XXX Is there such thing as video support with MGCP? XXX */ 04442 struct mgcp_subchannel *sub; 04443 sub = ast_channel_tech_pvt(chan); 04444 if (sub && !sub->alreadygone) { 04445 transmit_modify_with_sdp(sub, rtp, cap); 04446 return 0; 04447 } 04448 return -1; 04449 }
| static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2970 of file chan_mgcp.c.
References ast_bridged_channel(), ast_canmatch_extension(), ast_channel_caller(), ast_channel_context(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_language(), ast_channel_name(), ast_channel_tech_pvt(), 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, mgcp_endpoint::callreturn, mgcp_endpoint::callwaiting, mgcp_endpoint::cancallforward, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, ast_channel::exten, exten, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_gateway::name, mgcp_endpoint::name, mgcp_endpoint::ncs, mgcp_subchannel::next, ast_party_dialed::number, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, ast_channel::rings, S_COR, start_rtp(), ast_party_dialed::str, sub, and transmit_notify_request().
Referenced by handle_hd_hf().
02971 { 02972 struct ast_channel *chan = data; 02973 struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan); 02974 struct mgcp_endpoint *p = sub->parent; 02975 /* char exten[AST_MAX_EXTENSION] = ""; */ 02976 int len = 0; 02977 int timeout = firstdigittimeout; 02978 int res= 0; 02979 int getforward = 0; 02980 int loop_pause = 100; 02981 02982 len = strlen(p->dtmf_buf); 02983 02984 while (len < AST_MAX_EXTENSION - 1) { 02985 ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name); 02986 res = 1; /* Assume that we will get a digit */ 02987 while (strlen(p->dtmf_buf) == len) { 02988 ast_safe_sleep(chan, loop_pause); 02989 timeout -= loop_pause; 02990 if (timeout <= 0){ 02991 res = 0; 02992 break; 02993 } 02994 res = 1; 02995 } 02996 02997 timeout = 0; 02998 len = strlen(p->dtmf_buf); 02999 03000 if (!ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf)) { 03001 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03002 ast_indicate(chan, -1); 03003 } else { 03004 /* XXX Redundant? We should already be playing dialtone */ 03005 /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 03006 transmit_notify_request(sub, "L/dl"); 03007 } 03008 if (ast_exists_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) { 03009 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) { 03010 if (getforward) { 03011 /* Record this as the forwarding extension */ 03012 ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); 03013 ast_verb(3, "Setting call forward to '%s' on channel %s\n", 03014 p->call_forward, ast_channel_name(chan)); 03015 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03016 transmit_notify_request(sub, "L/sl"); 03017 if (res) 03018 break; 03019 usleep(500000); 03020 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03021 ast_indicate(chan, -1); 03022 sleep(1); 03023 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03024 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ 03025 transmit_notify_request(sub, "L/dl"); 03026 len = 0; 03027 getforward = 0; 03028 } else { 03029 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03030 ast_indicate(chan, -1); 03031 ast_channel_exten_set(chan, p->dtmf_buf); 03032 ast_channel_dialed(chan)->number.str = ast_strdup(p->dtmf_buf); 03033 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03034 ast_set_callerid(chan, 03035 p->hidecallerid ? "" : p->cid_num, 03036 p->hidecallerid ? "" : p->cid_name, 03037 ast_channel_caller(chan)->ani.number.valid ? NULL : p->cid_num); 03038 ast_setstate(chan, AST_STATE_RING); 03039 /*dahdi_enable_ec(p);*/ 03040 if (p->dtmfmode & MGCP_DTMF_HYBRID) { 03041 p->dtmfmode |= MGCP_DTMF_INBAND; 03042 ast_indicate(chan, -1); 03043 } 03044 res = ast_pbx_run(chan); 03045 if (res) { 03046 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 03047 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03048 /*transmit_notify_request(p, "nbz", 1);*/ 03049 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03050 } 03051 return NULL; 03052 } 03053 } else { 03054 /* It's a match, but they just typed a digit, and there is an ambiguous match, 03055 so just set the timeout to matchdigittimeout and wait some more */ 03056 timeout = matchdigittimeout; 03057 } 03058 } else if (res == 0) { 03059 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 03060 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03061 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03062 /*dahdi_wait_event(p->subs[index].zfd);*/ 03063 ast_hangup(chan); 03064 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03065 return NULL; 03066 } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { 03067 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan)); 03068 /* Disable call waiting if enabled */ 03069 p->callwaiting = 0; 03070 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03071 transmit_notify_request(sub, "L/sl"); 03072 len = 0; 03073 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03074 timeout = firstdigittimeout; 03075 } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { 03076 /* Scan all channels and see if any there 03077 * ringing channqels with that have call groups 03078 * that equal this channels pickup group 03079 */ 03080 if (ast_pickup_call(chan)) { 03081 ast_log(LOG_WARNING, "No call pickup possible...\n"); 03082 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ 03083 transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg"); 03084 } 03085 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03086 ast_hangup(chan); 03087 return NULL; 03088 } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { 03089 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan)); 03090 /* Disable Caller*ID if enabled */ 03091 p->hidecallerid = 1; 03092 ast_set_callerid(chan, "", "", NULL); 03093 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03094 transmit_notify_request(sub, "L/sl"); 03095 len = 0; 03096 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03097 timeout = firstdigittimeout; 03098 } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { 03099 res = 0; 03100 if (!ast_strlen_zero(p->lastcallerid)) { 03101 res = ast_say_digit_str(chan, p->lastcallerid, "", ast_channel_language(chan)); 03102 } 03103 if (!res) 03104 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03105 transmit_notify_request(sub, "L/sl"); 03106 break; 03107 } else if (!strcmp(p->dtmf_buf, "*78")) { 03108 /* Do not disturb */ 03109 ast_verb(3, "Enabled DND on channel %s\n", ast_channel_name(chan)); 03110 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03111 transmit_notify_request(sub, "L/sl"); 03112 p->dnd = 1; 03113 getforward = 0; 03114 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03115 len = 0; 03116 } else if (!strcmp(p->dtmf_buf, "*79")) { 03117 /* Do not disturb */ 03118 ast_verb(3, "Disabled DND on channel %s\n", ast_channel_name(chan)); 03119 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03120 transmit_notify_request(sub, "L/sl"); 03121 p->dnd = 0; 03122 getforward = 0; 03123 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03124 len = 0; 03125 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { 03126 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03127 transmit_notify_request(sub, "L/sl"); 03128 getforward = 1; 03129 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03130 len = 0; 03131 } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { 03132 ast_verb(3, "Cancelling call forwarding on channel %s\n", ast_channel_name(chan)); 03133 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03134 transmit_notify_request(sub, "L/sl"); 03135 memset(p->call_forward, 0, sizeof(p->call_forward)); 03136 getforward = 0; 03137 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03138 len = 0; 03139 } else if (ast_parking_ext_valid(p->dtmf_buf, chan, ast_channel_context(chan)) && 03140 sub->next->owner && ast_bridged_channel(sub->next->owner)) { 03141 /* This is a three way call, the main call being a real channel, 03142 and we're parking the first call. */ 03143 ast_masq_park_call_exten(ast_bridged_channel(sub->next->owner), chan, 03144 p->dtmf_buf, ast_channel_context(chan), 0, NULL); 03145 ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan)); 03146 break; 03147 } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { 03148 ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); 03149 res = ast_db_put("blacklist", p->lastcallerid, "1"); 03150 if (!res) { 03151 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03152 transmit_notify_request(sub, "L/sl"); 03153 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03154 len = 0; 03155 } 03156 } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { 03157 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan)); 03158 /* Enable Caller*ID if enabled */ 03159 p->hidecallerid = 0; 03160 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 03161 /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ 03162 transmit_notify_request(sub, "L/sl"); 03163 len = 0; 03164 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03165 timeout = firstdigittimeout; 03166 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, 03167 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)) 03168 && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 03169 ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, 03170 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"), 03171 ast_channel_context(chan)); 03172 break; 03173 } 03174 if (!timeout) 03175 timeout = gendigittimeout; 03176 if (len && !ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf)) 03177 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ 03178 ast_indicate(chan, -1); 03179 } 03180 #if 0 03181 for (;;) { 03182 res = ast_waitfordigit(chan, to); 03183 if (!res) { 03184 ast_debug(1, "Timeout...\n"); 03185 break; 03186 } 03187 if (res < 0) { 03188 ast_debug(1, "Got hangup...\n"); 03189 ast_hangup(chan); 03190 break; 03191 } 03192 exten[pos++] = res; 03193 if (!ast_ignore_pattern(chan->context, exten)) 03194 ast_indicate(chan, -1); 03195 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { 03196 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 03197 to = 3000; 03198 else 03199 to = 8000; 03200 } else 03201 break; 03202 } 03203 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { 03204 ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); 03205 if (!p->rtp) { 03206 start_rtp(p); 03207 } 03208 ast_setstate(chan, AST_STATE_RING); 03209 chan->rings = 1; 03210 if (ast_pbx_run(chan)) { 03211 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); 03212 } else { 03213 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03214 return NULL; 03215 } 03216 } 03217 #endif 03218 ast_hangup(chan); 03219 memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); 03220 return NULL; 03221 }
| static int mgcp_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 1246 of file chan_mgcp.c.
References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_tech_pvt(), ast_channel_writeformat(), 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, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_subchannel::sdpsent, mgcp_endpoint::singlepath, cops_gate::state, mgcp_endpoint::sub, sub, ast_frame::subclass, and transmit_modify_with_sdp().
01247 { 01248 struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast); 01249 int res = 0; 01250 char buf[256]; 01251 01252 if (frame->frametype != AST_FRAME_VOICE) { 01253 if (frame->frametype == AST_FRAME_IMAGE) 01254 return 0; 01255 else { 01256 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); 01257 return 0; 01258 } 01259 } else { 01260 if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) { 01261 ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n", 01262 ast_getformatname(&frame->subclass.format), 01263 ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)), 01264 ast_getformatname(ast_channel_readformat(ast)), 01265 ast_getformatname(ast_channel_writeformat(ast))); 01266 /* return -1; */ 01267 } 01268 } 01269 if (sub) { 01270 ast_mutex_lock(&sub->lock); 01271 if (!sub->sdpsent && sub->gate) { 01272 if (sub->gate->state == GATE_ALLOCATED) { 01273 ast_debug(1, "GATE ALLOCATED, sending sdp\n"); 01274 transmit_modify_with_sdp(sub, NULL, 0); 01275 } 01276 } 01277 if ((sub->parent->sub == sub) || !sub->parent->singlepath) { 01278 if (sub->rtp) { 01279 res = ast_rtp_instance_write(sub->rtp, frame); 01280 } 01281 } 01282 ast_mutex_unlock(&sub->lock); 01283 } 01284 return res; 01285 }
| static int mgcpsock_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | ignore | |||
| ) | [static] |
Definition at line 3634 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().
03635 { 03636 struct mgcp_request req; 03637 struct sockaddr_in sin; 03638 struct mgcp_subchannel *sub; 03639 int res; 03640 socklen_t len; 03641 int result; 03642 int ident; 03643 len = sizeof(sin); 03644 memset(&req, 0, sizeof(req)); 03645 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); 03646 if (res < 0) { 03647 if (errno != ECONNREFUSED) 03648 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 03649 return 1; 03650 } 03651 req.data[res] = '\0'; 03652 req.len = res; 03653 ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 03654 parse(&req); 03655 if (req.headers < 1) { 03656 /* Must have at least one header */ 03657 return 1; 03658 } 03659 if (ast_strlen_zero(req.identifier)) { 03660 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); 03661 return 1; 03662 } 03663 03664 if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { 03665 if (result < 200) { 03666 ast_debug(1, "Ignoring provisional response on transaction %d\n", ident); 03667 return 1; 03668 } 03669 /* Try to find who this message is for, if it's important */ 03670 sub = find_subchannel_and_lock(NULL, ident, &sin); 03671 if (sub) { 03672 struct mgcp_gateway *gw = sub->parent->parent; 03673 struct mgcp_message *cur, *prev; 03674 03675 ast_mutex_unlock(&sub->lock); 03676 ast_mutex_lock(&gw->msgs_lock); 03677 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 03678 if (cur->seqno == ident) { 03679 ast_debug(1, "Got response back on transaction %d\n", ident); 03680 if (prev) 03681 prev->next = cur->next; 03682 else 03683 gw->msgs = cur->next; 03684 break; 03685 } 03686 } 03687 03688 /* stop retrans timer if the queue is empty */ 03689 if (!gw->msgs) { 03690 AST_SCHED_DEL(sched, gw->retransid); 03691 } 03692 03693 ast_mutex_unlock(&gw->msgs_lock); 03694 if (cur) { 03695 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); 03696 ast_free(cur); 03697 return 1; 03698 } 03699 03700 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 03701 gw->name, ident); 03702 } 03703 } else { 03704 if (ast_strlen_zero(req.endpoint) || 03705 ast_strlen_zero(req.version) || 03706 ast_strlen_zero(req.verb)) { 03707 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); 03708 return 1; 03709 } 03710 /* Process request, with iflock held */ 03711 sub = find_subchannel_and_lock(req.endpoint, 0, &sin); 03712 if (sub) { 03713 /* look first to find a matching response in the queue */ 03714 if (!find_and_retrans(sub, &req)) 03715 /* pass the request off to the currently mastering subchannel */ 03716 handle_request(sub, &req, &sin); 03717 ast_mutex_unlock(&sub->lock); 03718 } 03719 } 03720 return 1; 03721 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 487 of file chan_mgcp.c.
00488 { 00489 /* This module does not handle MWI in an event-based manner. However, it 00490 * subscribes to MWI for each mailbox that is configured so that the core 00491 * knows that we care about it. Then, chan_mgcp will get the MWI from the 00492 * event cache instead of checking the mailbox directly. */ 00493 }
| static void parse | ( | struct mgcp_request * | req | ) | [static] |
Definition at line 1864 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(), expand_gosub_args(), extenspy_exec(), find_conf(), func_confbridge_info(), function_agent(), get_comma(), get_in_brackets_full(), gosub_exec(), handle_presencechange(), 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(), presence_read(), 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(), vm_playmsgexec(), xfer_park_call_helper(), and zapateller_exec().
01865 { 01866 /* Divide fields by NULL's */ 01867 char *c; 01868 int f = 0; 01869 c = req->data; 01870 01871 /* First header starts immediately */ 01872 req->header[f] = c; 01873 for (; *c; c++) { 01874 if (*c == '\n') { 01875 /* We've got a new header */ 01876 *c = 0; 01877 ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f])); 01878 if (ast_strlen_zero(req->header[f])) { 01879 /* Line by itself means we're now in content */ 01880 c++; 01881 break; 01882 } 01883 if (f >= MGCP_MAX_HEADERS - 1) { 01884 ast_log(LOG_WARNING, "Too many MGCP headers...\n"); 01885 } else { 01886 f++; 01887 } 01888 req->header[f] = c + 1; 01889 } else if (*c == '\r') { 01890 /* Ignore but eliminate \r's */ 01891 *c = 0; 01892 } 01893 } 01894 /* Check for last header */ 01895 if (!ast_strlen_zero(req->header[f])) { 01896 f++; 01897 } 01898 req->headers = f; 01899 /* Now we process any mime content */ 01900 f = 0; 01901 req->line[f] = c; 01902 for (; *c; c++) { 01903 if (*c == '\n') { 01904 /* We've got a new line */ 01905 *c = 0; 01906 ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f])); 01907 if (f >= MGCP_MAX_LINES - 1) { 01908 ast_log(LOG_WARNING, "Too many SDP lines...\n"); 01909 } else { 01910 f++; 01911 } 01912 req->line[f] = c + 1; 01913 } else if (*c == '\r') { 01914 /* Ignore and eliminate \r's */ 01915 *c = 0; 01916 } 01917 } 01918 /* Check for last line */ 01919 if (!ast_strlen_zero(req->line[f])) { 01920 f++; 01921 } 01922 req->lines = f; 01923 /* Parse up the initial header */ 01924 c = req->header[0]; 01925 while (*c && *c < 33) c++; 01926 /* First the verb */ 01927 req->verb = c; 01928 while (*c && (*c > 32)) c++; 01929 if (*c) { 01930 *c = '\0'; 01931 c++; 01932 while (*c && (*c < 33)) c++; 01933 req->identifier = c; 01934 while (*c && (*c > 32)) c++; 01935 if (*c) { 01936 *c = '\0'; 01937 c++; 01938 while (*c && (*c < 33)) c++; 01939 req->endpoint = c; 01940 while (*c && (*c > 32)) c++; 01941 if (*c) { 01942 *c = '\0'; 01943 c++; 01944 while (*c && (*c < 33)) c++; 01945 req->version = c; 01946 while (*c && (*c > 32)) c++; 01947 while (*c && (*c < 33)) c++; 01948 while (*c && (*c > 32)) c++; 01949 *c = '\0'; 01950 } 01951 } 01952 } 01953 01954 ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", 01955 req->verb, req->identifier, req->endpoint, req->version); 01956 ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines); 01957 if (*c) { 01958 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); 01959 } 01960 }
| static int process_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 1962 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().
01963 { 01964 char *m; 01965 char *c; 01966 char *a; 01967 char host[258]; 01968 int len; 01969 int portno; 01970 struct ast_format_cap *peercap; 01971 int peerNonCodecCapability; 01972 struct sockaddr_in sin; 01973 struct ast_sockaddr sin_tmp; 01974 char *codecs; 01975 struct ast_hostent ahp; struct hostent *hp; 01976 int codec, codec_count=0; 01977 int iterator; 01978 struct mgcp_endpoint *p = sub->parent; 01979 char tmp1[256], tmp2[256], tmp3[256]; 01980 01981 /* Get codec and RTP info from SDP */ 01982 m = get_sdp(req, "m"); 01983 c = get_sdp(req, "c"); 01984 if (ast_strlen_zero(m) || ast_strlen_zero(c)) { 01985 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); 01986 return -1; 01987 } 01988 if (sscanf(c, "IN IP4 %256s", host) != 1) { 01989 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 01990 return -1; 01991 } 01992 /* XXX This could block for a long time, and block the main thread! XXX */ 01993 hp = ast_gethostbyname(host, &ahp); 01994 if (!hp) { 01995 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); 01996 return -1; 01997 } 01998 if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) { 01999 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 02000 return -1; 02001 } 02002 sin.sin_family = AF_INET; 02003 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 02004 sin.sin_port = htons(portno); 02005 ast_sockaddr_from_sin(&sin_tmp, &sin); 02006 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp); 02007 ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 02008 /* Scan through the RTP payload types specified in a "m=" line: */ 02009 ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp); 02010 codecs = ast_strdupa(m + len); 02011 while (!ast_strlen_zero(codecs)) { 02012 if (sscanf(codecs, "%30d%n", &codec, &len) != 1) { 02013 if (codec_count) { 02014 break; 02015 } 02016 ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs); 02017 return -1; 02018 } 02019 ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec); 02020 codec_count++; 02021 codecs += len; 02022 } 02023 02024 /* Next, scan through each "a=rtpmap:" line, noting each */ 02025 /* specified RTP payload type (with corresponding MIME subtype): */ 02026 sdpLineNum_iterator_init(&iterator); 02027 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 02028 char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */ 02029 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2) 02030 continue; 02031 /* Note: should really look at the 'freq' and '#chans' params too */ 02032 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0); 02033 } 02034 02035 /* Now gather all of the codecs that were asked for: */ 02036 if (!(peercap = ast_format_cap_alloc_nolock())) { 02037 return -1; 02038 } 02039 ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability); 02040 ast_format_cap_joint_copy(global_capability, peercap, p->cap); 02041 ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n", 02042 ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability), 02043 ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap), 02044 ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap)); 02045 peercap = ast_format_cap_destroy(peercap); 02046 02047 ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n", 02048 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); 02049 if (ast_format_cap_is_empty(p->cap)) { 02050 ast_log(LOG_WARNING, "No compatible codecs!\n"); 02051 return -1; 02052 } 02053 return 0; 02054 }
| static void prune_gateways | ( | void | ) | [static] |
Definition at line 4554 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().
04555 { 04556 struct mgcp_gateway *g, *z, *r; 04557 struct mgcp_endpoint *e, *p, *t; 04558 04559 ast_mutex_lock(&gatelock); 04560 04561 /* prune gateways */ 04562 for (z = NULL, g = gateways; g;) { 04563 /* prune endpoints */ 04564 for (p = NULL, e = g->endpoints; e; ) { 04565 if (!g->realtime && (e->delme || g->delme)) { 04566 t = e; 04567 e = e->next; 04568 if (!p) 04569 g->endpoints = e; 04570 else 04571 p->next = e; 04572 destroy_endpoint(t); 04573 } else { 04574 p = e; 04575 e = e->next; 04576 } 04577 } 04578 04579 if (g->delme) { 04580 r = g; 04581 g = g->next; 04582 if (!z) 04583 gateways = g; 04584 else 04585 z->next = g; 04586 04587 destroy_gateway(r); 04588 } else { 04589 z = g; 04590 g = g->next; 04591 } 04592 } 04593 04594 ast_mutex_unlock(&gatelock); 04595 }
| static int reload | ( | void | ) | [static] |
Definition at line 4890 of file chan_mgcp.c.
References mgcp_reload().
04891 { 04892 mgcp_reload(NULL, 0, NULL); 04893 return 0; 04894 }
| static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4629 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_sched_runq(), ast_set_qos(), 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.
04630 { 04631 struct ast_config *cfg; 04632 struct ast_variable *v; 04633 struct mgcp_gateway *g; 04634 struct mgcp_endpoint *e; 04635 char *cat; 04636 struct ast_hostent ahp; 04637 struct hostent *hp; 04638 struct ast_format format; 04639 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04640 04641 if (gethostname(ourhost, sizeof(ourhost)-1)) { 04642 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); 04643 return 0; 04644 } 04645 cfg = ast_config_load(config, config_flags); 04646 04647 /* We *must* have a config file otherwise stop immediately */ 04648 if (!cfg) { 04649 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); 04650 return 0; 04651 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 04652 return 0; 04653 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 04654 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 04655 return 0; 04656 } 04657 04658 memset(&bindaddr, 0, sizeof(bindaddr)); 04659 dtmfmode = 0; 04660 04661 /* Copy the default jb config over global_jbconf */ 04662 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 04663 04664 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 04665 /* handle jb conf */ 04666 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { 04667 continue; 04668 } 04669 04670 /* Create the interface list */ 04671 if (!strcasecmp(v->name, "bindaddr")) { 04672 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 04673 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 04674 } else { 04675 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 04676 } 04677 } else if (!strcasecmp(v->name, "allow")) { 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_add(global_capability, &format); 04683 } 04684 } else if (!strcasecmp(v->name, "disallow")) { 04685 ast_getformatbyname(v->value, &format); 04686 if (!format.id) { 04687 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); 04688 } else { 04689 ast_format_cap_remove(global_capability, &format); 04690 } 04691 } else if (!strcasecmp(v->name, "tos")) { 04692 if (ast_str2tos(v->value, &qos.tos)) { 04693 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); 04694 } 04695 } else if (!strcasecmp(v->name, "tos_audio")) { 04696 if (ast_str2tos(v->value, &qos.tos_audio)) 04697 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04698 } else if (!strcasecmp(v->name, "cos")) { 04699 if (ast_str2cos(v->value, &qos.cos)) 04700 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); 04701 } else if (!strcasecmp(v->name, "cos_audio")) { 04702 if (ast_str2cos(v->value, &qos.cos_audio)) 04703 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 04704 } else if (!strcasecmp(v->name, "port")) { 04705 if (sscanf(v->value, "%5d", &ourport) == 1) { 04706 bindaddr.sin_port = htons(ourport); 04707 } else { 04708 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 04709 } 04710 } else if (!strcasecmp(v->name, "firstdigittimeout")) { 04711 firstdigittimeout = atoi(v->value); 04712 } else if (!strcasecmp(v->name, "gendigittimeout")) { 04713 gendigittimeout = atoi(v->value); 04714 } else if (!strcasecmp(v->name, "matchdigittimeout")) { 04715 matchdigittimeout = atoi(v->value); 04716 } 04717 } 04718 04719 /* mark existing entries for deletion */ 04720 ast_mutex_lock(&gatelock); 04721 for (g = gateways; g; g = g->next) { 04722 g->delme = 1; 04723 for (e = g->endpoints; e; e = e->next) { 04724 e->delme = 1; 04725 } 04726 } 04727 ast_mutex_unlock(&gatelock); 04728 04729 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) { 04730 if (strcasecmp(cat, "general")) { 04731 ast_mutex_lock(&gatelock); 04732 if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) { 04733 ast_verb(3, "Added gateway '%s'\n", g->name); 04734 g->next = gateways; 04735 gateways = g; 04736 } 04737 ast_mutex_unlock(&gatelock); 04738 04739 /* FS: process queue and IO */ 04740 if (monitor_thread == pthread_self()) { 04741 if (sched) ast_sched_runq(sched); 04742 if (io) ast_io_wait(io, 10); 04743 } 04744 } 04745 } 04746 04747 /* prune deleted entries etc. */ 04748 prune_gateways(); 04749 04750 if (ntohl(bindaddr.sin_addr.s_addr)) { 04751 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); 04752 } else { 04753 hp = ast_gethostbyname(ourhost, &ahp); 04754 if (!hp) { 04755 ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); 04756 ast_config_destroy(cfg); 04757 return 0; 04758 } 04759 memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); 04760 } 04761 if (!ntohs(bindaddr.sin_port)) 04762 bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT); 04763 bindaddr.sin_family = AF_INET; 04764 ast_mutex_lock(&netlock); 04765 if (mgcpsock > -1) 04766 close(mgcpsock); 04767 04768 if (mgcpsock_read_id != NULL) 04769 ast_io_remove(io, mgcpsock_read_id); 04770 mgcpsock_read_id = NULL; 04771 04772 mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); 04773 if (mgcpsock < 0) { 04774 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); 04775 } else { 04776 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 04777 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 04778 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 04779 strerror(errno)); 04780 close(mgcpsock); 04781 mgcpsock = -1; 04782 } else { 04783 ast_verb(2, "MGCP Listening on %s:%d\n", 04784 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 04785 ast_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); 04786 } 04787 } 04788 ast_mutex_unlock(&netlock); 04789 ast_config_destroy(cfg); 04790 04791 /* send audit only to the new endpoints */ 04792 for (g = gateways; g; g = g->next) { 04793 for (e = g->endpoints; e && e->needaudit; e = e->next) { 04794 e->needaudit = 0; 04795 transmit_audit_endpoint(e); 04796 ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); 04797 } 04798 } 04799 04800 return 0; 04801 }
| static int reqprep | ( | struct mgcp_request * | req, | |
| struct mgcp_endpoint * | p, | |||
| char * | verb | |||
| ) | [static] |
Definition at line 2150 of file chan_mgcp.c.
References init_req().
Referenced by ast_sipinfo_send(), 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_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_state_notify(), and update_connectedline().
02151 { 02152 memset(req, 0, sizeof(struct mgcp_request)); 02153 oseq++; 02154 if (oseq > 999999999) { 02155 oseq = 1; 02156 } 02157 init_req(p, req, verb); 02158 return 0; 02159 }
| static int resend_response | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_response * | resp | |||
| ) | [static] |
Definition at line 561 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().
00562 { 00563 struct mgcp_endpoint *p = sub->parent; 00564 int res; 00565 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)); 00566 res = __mgcp_xmit(p->parent, resp->buf, resp->len); 00567 if (res > 0) 00568 res = 0; 00569 return res; 00570 }
| static int respprep | ( | struct mgcp_request * | resp, | |
| struct mgcp_endpoint * | p, | |||
| char * | msg, | |||
| struct mgcp_request * | req, | |||
| char * | msgrest | |||
| ) | [static] |
Definition at line 2143 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().
02144 { 02145 memset(resp, 0, sizeof(*resp)); 02146 init_resp(resp, msg, req, msgrest); 02147 return 0; 02148 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 3901 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.
03902 { 03903 /* If we're supposed to be stopped -- stay stopped */ 03904 if (monitor_thread == AST_PTHREADT_STOP) 03905 return 0; 03906 if (ast_mutex_lock(&monlock)) { 03907 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 03908 return -1; 03909 } 03910 if (monitor_thread == pthread_self()) { 03911 ast_mutex_unlock(&monlock); 03912 ast_log(LOG_WARNING, "Cannot kill myself\n"); 03913 return -1; 03914 } 03915 if (monitor_thread != AST_PTHREADT_NULL) { 03916 /* Wake up the thread */ 03917 pthread_kill(monitor_thread, SIGURG); 03918 } else { 03919 /* Start a new monitor */ 03920 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 03921 ast_mutex_unlock(&monlock); 03922 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 03923 return -1; 03924 } 03925 } 03926 ast_mutex_unlock(&monlock); 03927 return 0; 03928 }
| static int retrans_pkt | ( | const void * | data | ) | [static] |
Definition at line 658 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().
00659 { 00660 struct mgcp_gateway *gw = (struct mgcp_gateway *)data; 00661 struct mgcp_message *cur, *exq = NULL, *w, *prev; 00662 int res = 0; 00663 00664 /* find out expired msgs */ 00665 ast_mutex_lock(&gw->msgs_lock); 00666 00667 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { 00668 if (cur->retrans < MAX_RETRANS) { 00669 cur->retrans++; 00670 ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n", 00671 cur->retrans, cur->seqno, gw->name); 00672 __mgcp_xmit(gw, cur->buf, cur->len); 00673 } else { 00674 if (prev) 00675 prev->next = cur->next; 00676 else 00677 gw->msgs = cur->next; 00678 00679 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", 00680 cur->seqno, gw->name); 00681 00682 w = cur; 00683 00684 if (exq) { 00685 w->next = exq; 00686 } else { 00687 w->next = NULL; 00688 } 00689 exq = w; 00690 } 00691 } 00692 00693 if (!gw->msgs) { 00694 gw->retransid = -1; 00695 res = 0; 00696 } else { 00697 res = 1; 00698 } 00699 ast_mutex_unlock(&gw->msgs_lock); 00700 00701 while (exq) { 00702 cur = exq; 00703 /* time-out transaction */ 00704 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 00705 exq = exq->next; 00706 ast_free(cur); 00707 } 00708 00709 return res; 00710 }
| static void sdpLineNum_iterator_init | ( | int * | iterator | ) | [static] |
| static int send_request | ( | struct mgcp_endpoint * | p, | |
| struct mgcp_subchannel * | sub, | |||
| struct mgcp_request * | req, | |||
| unsigned int | seqno | |||
| ) | [static] |
Definition at line 757 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_malloc, ast_mutex_lock, ast_mutex_unlock, 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 ast_sipinfo_send(), 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_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_state_notify(), and update_connectedline().
00759 { 00760 int res = 0; 00761 struct mgcp_request **queue, *q, *r, *t; 00762 ast_mutex_t *l; 00763 00764 ast_debug(1, "Slow sequence is %d\n", p->slowsequence); 00765 if (p->slowsequence) { 00766 queue = &p->cmd_queue; 00767 l = &p->cmd_queue_lock; 00768 ast_mutex_lock(l); 00769 } else { 00770 switch (req->cmd) { 00771 case MGCP_CMD_DLCX: 00772 queue = &sub->cx_queue; 00773 l = &sub->cx_queue_lock; 00774 ast_mutex_lock(l); 00775 q = sub->cx_queue; 00776 /* delete pending cx cmds */ 00777 /* buggy sb5120 */ 00778 if (!sub->parent->ncs) { 00779 while (q) { 00780 r = q->next; 00781 ast_free(q); 00782 q = r; 00783 } 00784 *queue = NULL; 00785 } 00786 break; 00787 00788 case MGCP_CMD_CRCX: 00789 case MGCP_CMD_MDCX: 00790 queue = &sub->cx_queue; 00791 l = &sub->cx_queue_lock; 00792 ast_mutex_lock(l); 00793 break; 00794 00795 case MGCP_CMD_RQNT: 00796 queue = &p->rqnt_queue; 00797 l = &p->rqnt_queue_lock; 00798 ast_mutex_lock(l); 00799 break; 00800 00801 default: 00802 queue = &p->cmd_queue; 00803 l = &p->cmd_queue_lock; 00804 ast_mutex_lock(l); 00805 break; 00806 } 00807 } 00808 00809 if (!(r = ast_malloc(sizeof(*r)))) { 00810 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n"); 00811 ast_mutex_unlock(l); 00812 return -1; 00813 } 00814 memcpy(r, req, sizeof(*r)); 00815 00816 if (!(*queue)) { 00817 ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data, 00818 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00819 00820 res = mgcp_postrequest(p, sub, req->data, req->len, seqno); 00821 } else { 00822 ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data, 00823 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 00824 } 00825 00826 /* XXX find tail. We could also keep tail in the data struct for faster access */ 00827 for (t = *queue; t && t->next; t = t->next); 00828 00829 r->next = NULL; 00830 if (t) 00831 t->next = r; 00832 else 00833 *queue = r; 00834 00835 ast_mutex_unlock(l); 00836 00837 return res; 00838 }
| static int send_response | ( | struct mgcp_subchannel * | sub, | |
| struct mgcp_request * | req | |||
| ) | [static] |
Definition at line 572 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().
00573 { 00574 struct mgcp_endpoint *p = sub->parent; 00575 int res; 00576 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)); 00577 res = __mgcp_xmit(p->parent, req->data, req->len); 00578 if (res > 0) 00579 res = 0; 00580 return res; 00581 }
| static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2937 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_call_outgoing(), handle_hd_hf(), handle_response(), mgcp_answer(), mgcp_call(), mgcp_ss(), setsubstate(), skinny_newcall(), unistim_answer(), and unistim_request().
02938 { 02939 struct ast_sockaddr bindaddr_tmp; 02940 02941 ast_mutex_lock(&sub->lock); 02942 /* check again to be on the safe side */ 02943 if (sub->rtp) { 02944 ast_rtp_instance_destroy(sub->rtp); 02945 sub->rtp = NULL; 02946 } 02947 /* Allocate the RTP now */ 02948 ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr); 02949 sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL); 02950 if (sub->rtp && sub->owner) 02951 ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0)); 02952 if (sub->rtp) { 02953 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); 02954 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat); 02955 } 02956 /* Make a call*ID */ 02957 snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); 02958 /* Transmit the connection create */ 02959 if(!sub->parent->pktcgatealloc) { 02960 transmit_connect_with_sdp(sub, NULL); 02961 } else { 02962 transmit_connect(sub); 02963 sub->gate = NULL; 02964 if(!mgcp_alloc_pktcgate(sub)) 02965 mgcp_queue_hangup(sub); 02966 } 02967 ast_mutex_unlock(&sub->lock); 02968 }
| static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2649 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().
02650 { 02651 struct mgcp_request resp; 02652 reqprep(&resp, p, "AUEP"); 02653 /* removed unknown param VS */ 02654 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ 02655 add_header(&resp, "F", "A"); 02656 /* fill in new fields */ 02657 resp.cmd = MGCP_CMD_AUEP; 02658 resp.trid = oseq; 02659 return send_request(p, NULL, &resp, oseq); 02660 }
| static int transmit_connect | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2444 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().
02445 { 02446 struct mgcp_request resp; 02447 char local[256]; 02448 char tmp[80]; 02449 struct ast_format tmpfmt; 02450 struct mgcp_endpoint *p = sub->parent; 02451 02452 ast_copy_string(local, "p:20, s:off, e:on", sizeof(local)); 02453 02454 ast_format_cap_iter_start(p->cap); 02455 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02456 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02457 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02458 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02459 } 02460 } 02461 ast_format_cap_iter_end(p->cap); 02462 02463 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02464 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02465 sub->sdpsent = 0; 02466 reqprep(&resp, p, "CRCX"); 02467 add_header(&resp, "C", sub->callid); 02468 add_header(&resp, "L", local); 02469 add_header(&resp, "M", "inactive"); 02470 /* X header should not be sent. kept for compatibility */ 02471 add_header(&resp, "X", sub->txident); 02472 /*add_header(&resp, "S", "");*/ 02473 /* fill in new fields */ 02474 resp.cmd = MGCP_CMD_CRCX; 02475 resp.trid = oseq; 02476 return send_request(p, sub, &resp, oseq); 02477 }
| static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, | |
| struct ast_rtp_instance * | rtp | |||
| ) | [static] |
Definition at line 2347 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().
02348 { 02349 struct mgcp_request resp; 02350 char local[256]; 02351 char tmp[80]; 02352 struct ast_format tmpfmt; 02353 struct mgcp_endpoint *p = sub->parent; 02354 02355 ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 02356 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02357 02358 ast_copy_string(local, "e:on, s:off, p:20", sizeof(local)); 02359 02360 ast_format_cap_iter_start(p->cap); 02361 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02362 if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) { 02363 /* Audio is now discontiguous */ 02364 continue; 02365 } 02366 if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) { 02367 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0)); 02368 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02369 } 02370 } 02371 ast_format_cap_iter_end(p->cap); 02372 02373 if (sub->gate) { 02374 if(sub->gate->state == GATE_ALLOCATED) { 02375 snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid); 02376 strncat(local, tmp, sizeof(local) - strlen(local) - 1); 02377 } 02378 } 02379 sub->sdpsent = 1; 02380 reqprep(&resp, p, "CRCX"); 02381 add_header(&resp, "C", sub->callid); 02382 add_header(&resp, "L", local); 02383 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); 02384 /* X header should not be sent. kept for compatibility */ 02385 add_header(&resp, "X", sub->txident); 02386 /*add_header(&resp, "S", "");*/ 02387 add_sdp(&resp, sub, rtp); 02388 /* fill in new fields */ 02389 resp.cmd = MGCP_CMD_CRCX; 02390 resp.trid = oseq; 02391 return send_request(p, sub, &resp, oseq); 02392 }
| static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2662 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().
02663 { 02664 struct mgcp_endpoint *p = sub->parent; 02665 struct mgcp_request resp; 02666 02667 ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 02668 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02669 reqprep(&resp, p, "DLCX"); 02670 /* check if call id is avail */ 02671 if (sub->callid[0]) 02672 add_header(&resp, "C", sub->callid); 02673 /* X header should not be sent. kept for compatibility */ 02674 add_header(&resp, "X", sub->txident); 02675 /* check if cxident is avail */ 02676 if (sub->cxident[0]) 02677 add_header(&resp, "I", sub->cxident); 02678 /* fill in new fields */ 02679 resp.cmd = MGCP_CMD_DLCX; 02680 resp.trid = oseq; 02681 return send_request(p, sub, &resp, oseq); 02682 }
| static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, | |
| char * | callid, | |||
| char * | cxident | |||
| ) | [static] |
Definition at line 2684 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().
02685 { 02686 struct mgcp_request resp; 02687 02688 ast_debug(3, "Delete connection %s %s@%s on callid: %s\n", 02689 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); 02690 reqprep(&resp, p, "DLCX"); 02691 /* check if call id is avail */ 02692 if (callid && *callid) 02693 add_header(&resp, "C", callid); 02694 /* check if cxident is avail */ 02695 if (cxident && *cxident) 02696 add_header(&resp, "I", cxident); 02697 /* fill in new fields */ 02698 resp.cmd = MGCP_CMD_DLCX; 02699 resp.trid = oseq; 02700 return send_request(p, p->sub, &resp, oseq); 02701 }
| static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2550 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().
02551 { 02552 struct mgcp_request resp; 02553 struct mgcp_endpoint *p = sub->parent; 02554 struct ast_format tmpfmt; 02555 int fc = 1; 02556 char local[256]; 02557 char tmp[80]; 02558 02559 if (ast_strlen_zero(sub->cxident)) { 02560 /* We don't have a CXident yet, store the destination and 02561 wait a bit */ 02562 return 0; 02563 } 02564 ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", 02565 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); 02566 02567 ast_copy_string(local, "", sizeof(local)); 02568 ast_format_cap_iter_start(p->cap); 02569 while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) { 02570 if (p->ncs && !fc) { 02571 ast_format_cap_set(p->