#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/signal.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/event.h"
#include "asterisk/chanvars.h"

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