Implementation of Media Gateway Control Protocol. More...
#include "asterisk.h"
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/signal.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/netsock.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/event.h"
Go to the source code of this file.
Data Structures | |
struct | mgcp_endpoint |
struct | mgcp_gateway |
struct | mgcp_message |
mgcp_message: MGCP message for queuing up More... | |
struct | mgcp_request |
struct | mgcp_response |
struct | mgcp_subchannel |
Defines | |
#define | 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, char *var, char *value) |
static void | add_header_offhook (struct mgcp_subchannel *sub, struct mgcp_request *resp) |
static int | add_line (struct mgcp_request *req, char *line) |
static int | add_sdp (struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp) |
static int | attempt_transfer (struct mgcp_endpoint *p) |
static struct mgcp_gateway * | build_gateway (char *cat, struct ast_variable *v) |
build_gateway: parse mgcp.conf and create gateway/endpoint structures | |
static char * | control2str (int ind) |
static void | destroy_endpoint (struct mgcp_endpoint *e) |
static void | destroy_gateway (struct mgcp_gateway *g) |
static void * | do_monitor (void *data) |
static void | dump_cmd_queues (struct mgcp_endpoint *p, struct mgcp_subchannel *sub) |
dump_cmd_queues: (SC:) cleanup pending commands | |
static void | dump_queue (struct mgcp_gateway *gw, struct mgcp_endpoint *p) |
static int | find_and_retrans (struct mgcp_subchannel *sub, struct mgcp_request *req) |
static struct mgcp_request * | find_command (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request **queue, ast_mutex_t *l, int ident) |
find_command: (SC:) remove command transaction from queue | |
static struct mgcp_subchannel * | find_subchannel_and_lock (char *name, int msgid, struct sockaddr_in *sin) |
static char * | get_csv (char *c, int *len, char **next) |
get_csv: (SC:) get comma separated value | |
static char * | get_header (struct mgcp_request *req, char *name) |
static char * | get_sdp (struct mgcp_request *req, char *name) |
static char * | get_sdp_by_line (char *line, char *name, int nameLen) |
static char * | get_sdp_iterate (int *iterator, struct mgcp_request *req, char *name) |
static void | handle_hd_hf (struct mgcp_subchannel *sub, char *ev) |
static char * | handle_mgcp_audit_endpoint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mgcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_mgcp_show_endpoints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | handle_request (struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin) |
static void | handle_response (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, int result, unsigned int ident, struct mgcp_request *resp) |
static int | has_voicemail (struct mgcp_endpoint *p) |
static int | init_req (struct mgcp_endpoint *p, struct mgcp_request *req, char *verb) |
static int | init_resp (struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest) |
static int | load_module (void) |
load_module: PBX load module - initialization --- | |
static int | mgcp_answer (struct ast_channel *ast) |
static int | mgcp_call (struct ast_channel *ast, char *dest, int timeout) |
static int | mgcp_devicestate (void *data) |
mgcp_devicestate: channel callback for device status monitoring | |
static int | mgcp_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static enum ast_rtp_get_result | mgcp_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
static int | mgcp_hangup (struct ast_channel *ast) |
static int | mgcp_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen) |
static struct ast_channel * | mgcp_new (struct mgcp_subchannel *sub, int state) |
static int | mgcp_postrequest (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, char *data, int len, unsigned int seqno) |
static void | mgcp_queue_control (struct mgcp_subchannel *sub, int control) |
static void | mgcp_queue_frame (struct mgcp_subchannel *sub, struct ast_frame *f) |
static void | mgcp_queue_hangup (struct mgcp_subchannel *sub) |
static struct ast_frame * | mgcp_read (struct ast_channel *ast) |
static char * | mgcp_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static struct ast_channel * | mgcp_request (const char *type, int format, void *data, int *cause) |
static struct ast_frame * | mgcp_rtp_read (struct mgcp_subchannel *sub) |
static int | mgcp_senddigit_begin (struct ast_channel *ast, char digit) |
static int | mgcp_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration) |
static int | mgcp_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active) |
static void * | mgcp_ss (void *data) |
static int | mgcp_write (struct ast_channel *ast, struct ast_frame *frame) |
static int | mgcpsock_read (int *id, int fd, short events, void *ignore) |
static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
static void | parse (struct mgcp_request *req) |
static int | process_sdp (struct mgcp_subchannel *sub, struct mgcp_request *req) |
static void | prune_gateways (void) |
static int | reload (void) |
static int | reload_config (int reload) |
static int | reqprep (struct mgcp_request *req, struct mgcp_endpoint *p, char *verb) |
static int | resend_response (struct mgcp_subchannel *sub, struct mgcp_response *resp) |
static int | respprep (struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest) |
static int | restart_monitor (void) |
static int | retrans_pkt (const void *data) |
static void | sdpLineNum_iterator_init (int *iterator) |
static int | send_request (struct mgcp_endpoint *p, struct mgcp_subchannel *sub, struct mgcp_request *req, unsigned int seqno) |
static int | send_response (struct mgcp_subchannel *sub, struct mgcp_request *req) |
static void | start_rtp (struct mgcp_subchannel *sub) |
static int | transmit_audit_endpoint (struct mgcp_endpoint *p) |
static int | transmit_connect_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp) |
static int | transmit_connection_del (struct mgcp_subchannel *sub) |
static int | transmit_connection_del_w_params (struct mgcp_endpoint *p, char *callid, char *cxident) |
static int | transmit_modify_request (struct mgcp_subchannel *sub) |
static int | transmit_modify_with_sdp (struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs) |
static int | transmit_notify_request (struct mgcp_subchannel *sub, char *tone) |
static int | transmit_notify_request_with_callerid (struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername) |
static int | transmit_response (struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest) |
static int | unalloc_sub (struct mgcp_subchannel *sub) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = ASTERISK_GPL_KEY , .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_INIT_VALUE |
gatelock: mutex for gateway/endpoint lists | |
static struct mgcp_gateway * | gateways |
static int | gendigittimeout = 8000 |
static struct ast_jb_conf | global_jbconf |
static int | immediate = 0 |
static struct io_context * | io |
static char | language [MAX_LANGUAGE] = "" |
static char | mailbox [AST_MAX_EXTENSION] |
static int | matchdigittimeout = 3000 |
static char * | mgcp_cxmodes [] |
static ast_mutex_t | mgcp_reload_lock = AST_MUTEX_INIT_VALUE |
static int | mgcp_reloading = 0 |
static struct ast_rtp_protocol | mgcp_rtp |
static struct ast_channel_tech | mgcp_tech |
static int | mgcpdebug = 0 |
static int | mgcpsock = -1 |
static int * | mgcpsock_read_id = NULL |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
static ast_mutex_t | monlock = AST_MUTEX_INIT_VALUE |
static char | musicclass [MAX_MUSICCLASS] = "" |
static int | nat = 0 |
static ast_mutex_t | netlock = AST_MUTEX_INIT_VALUE |
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 |
#define DEFAULT_EXPIRY 120 |
Definition at line 81 of file chan_mgcp.c.
#define DEFAULT_MGCP_CA_PORT 2727 |
#define DEFAULT_MGCP_GW_PORT 2427 |
#define DEFAULT_RETRANS 1000 |
How frequently to retransmit
Definition at line 110 of file chan_mgcp.c.
Referenced by mgcp_postrequest().
#define DIRECTMEDIA 1 |
Definition at line 83 of file chan_mgcp.c.
Referenced by build_gateway().
#define INADDR_NONE (in_addr_t)(-1) |
Definition at line 86 of file chan_mgcp.c.
Referenced by build_gateway().
#define MAX_EXPIRY 3600 |
Definition at line 82 of file chan_mgcp.c.
#define MAX_RETRANS 5 |
Try only 5 times for retransmissions
Definition at line 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(), and destroy_endpoint().
#define MGCP_CX_CONF 3 |
Definition at line 117 of file chan_mgcp.c.
Referenced by handle_request().
#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 |
Definition at line 119 of file chan_mgcp.c.
Referenced by handle_request().
#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 |
Definition at line 229 of file chan_mgcp.c.
Referenced by add_line(), and parse().
#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 80 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(), do_monitor(), and mgcp_call().
#define TYPE_TRUNK 1 |
Definition at line 305 of file chan_mgcp.c.
Referenced by build_gateway().
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.
static char* __get_header | ( | struct mgcp_request * | req, |
char * | name, | ||
int * | start | ||
) | [static] |
Definition at line 1581 of file chan_mgcp.c.
References mgcp_request::header, mgcp_request::headers, and len().
Referenced by get_header().
{ int x; int len = strlen(name); char *r; for (x=*start;x<req->headers;x++) { if (!strncasecmp(req->header[x], name, len) && (req->header[x][len] == ':')) { r = req->header[x] + len + 1; while(*r && (*r < 33)) r++; *start = x+1; return r; } } /* Don't return NULL, so get_header is always a valid pointer */ return ""; }
static int __mgcp_xmit | ( | struct mgcp_gateway * | gw, |
char * | data, | ||
int | len | ||
) | [static] |
Definition at line 515 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().
{ int res; if (gw->addr.sin_addr.s_addr) res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); else res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); if (res != len) { ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); } return res; }
static void __reg_module | ( | void | ) | [static] |
Definition at line 4397 of file chan_mgcp.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4397 of file chan_mgcp.c.
static int add_header | ( | struct mgcp_request * | req, |
char * | var, | ||
char * | value | ||
) | [static] |
Definition at line 1927 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 add_header_offhook(), transmit_audit_endpoint(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
{ if (req->len >= sizeof(req->data) - 4) { ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); return -1; } if (req->lines) { ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); return -1; } req->header[req->headers] = req->data + req->len; snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value); req->len += strlen(req->header[req->headers]); if (req->headers < MGCP_MAX_HEADERS) req->headers++; else { ast_log(LOG_WARNING, "Out of header space\n"); return -1; } return 0; }
static void add_header_offhook | ( | struct mgcp_subchannel * | sub, |
struct mgcp_request * | resp | ||
) | [static] |
Definition at line 2322 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().
{ struct mgcp_endpoint *p = sub->parent; if (p && p->sub && p->sub->owner && p->sub->owner->_state >= AST_STATE_RINGING && (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) add_header(resp, "R", "L/hu(N),L/hf(N)"); else add_header(resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)"); }
static int add_line | ( | struct mgcp_request * | req, |
char * | line | ||
) | [static] |
Definition at line 1949 of file chan_mgcp.c.
References ast_copy_string(), ast_log(), mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES.
Referenced by add_sdp().
{ if (req->len >= sizeof(req->data) - 4) { ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); return -1; } if (!req->lines) { /* Add extra empty return */ ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len); req->len += strlen(req->data + req->len); } req->line[req->lines] = req->data + req->len; snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); req->len += strlen(req->line[req->lines]); if (req->lines < MGCP_MAX_LINES) req->lines++; else { ast_log(LOG_WARNING, "Out of line space\n"); return -1; } return 0; }
static int add_sdp | ( | struct mgcp_request * | resp, |
struct mgcp_subchannel * | sub, | ||
struct ast_rtp * | rtp | ||
) | [static] |
Definition at line 2050 of file chan_mgcp.c.
References add_line(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_get_peer(), ast_rtp_get_us(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), 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(), and transmit_modify_with_sdp().
{ int len; int codec; char costr[80]; struct sockaddr_in sin; char v[256]; char s[256]; char o[256]; char c[256]; char t[256]; char m[256] = ""; char a[1024] = ""; int x; struct sockaddr_in dest; struct mgcp_endpoint *p = sub->parent; /* XXX We break with the "recommendation" and send our IP, in order that our peer doesn't have to ast_gethostbyname() us XXX */ len = 0; if (!sub->rtp) { ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); return -1; } ast_rtp_get_us(sub->rtp, &sin); if (rtp) { ast_rtp_get_peer(rtp, &dest); } else { if (sub->tmpdest.sin_addr.s_addr) { dest.sin_addr = sub->tmpdest.sin_addr; dest.sin_port = sub->tmpdest.sin_port; /* Reset temporary destination */ memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); } else { dest.sin_addr = p->parent->ourip; dest.sin_port = sin.sin_port; } } if (mgcpdebug) { ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); } ast_copy_string(v, "v=0\r\n", sizeof(v)); snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr)); ast_copy_string(s, "s=session\r\n", sizeof(s)); snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); ast_copy_string(t, "t=0 0\r\n", sizeof(t)); snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { if (p->capability & x) { if (mgcpdebug) { ast_verbose("Answering with capability %d\n", x); } codec = ast_rtp_lookup_code(sub->rtp, 1, x); if (codec > -1) { snprintf(costr, sizeof(costr), " %d", codec); strncat(m, costr, sizeof(m) - strlen(m) - 1); snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0)); strncat(a, costr, sizeof(a) - strlen(a) - 1); } } } for (x = 1; x <= AST_RTP_MAX; x <<= 1) { if (p->nonCodecCapability & x) { if (mgcpdebug) { ast_verbose("Answering with non-codec capability %d\n", x); } codec = ast_rtp_lookup_code(sub->rtp, 0, x); if (codec > -1) { snprintf(costr, sizeof(costr), " %d", codec); strncat(m, costr, sizeof(m) - strlen(m) - 1); snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0)); strncat(a, costr, sizeof(a) - strlen(a) - 1); if (x == AST_RTP_DTMF) { /* Indicate we support DTMF... Not sure about 16, but MSN supports it so dang it, we will too... */ snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); strncat(a, costr, sizeof(a) - strlen(a) - 1); } } } } strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); snprintf(costr, sizeof(costr), "%d", len); add_line(resp, v); add_line(resp, o); add_line(resp, s); add_line(resp, c); add_line(resp, t); add_line(resp, m); add_line(resp, a); return 0; }
static int attempt_transfer | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2887 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().
Referenced by handle_request().
{ /* ************************* * I hope this works. * Copied out of chan_zap * Cross your fingers * *************************/ /* In order to transfer, we need at least one of the channels to actually be in a call bridge. We can't conference two applications together (but then, why would we want to?) */ if (ast_bridged_channel(p->sub->owner)) { /* The three-way person we're about to transfer to could still be in MOH, so stop if now if appropriate */ if (ast_bridged_channel(p->sub->next->owner)) ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); if (p->sub->owner->_state == AST_STATE_RINGING) { ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); } if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); return -1; } /* Orphan the channel */ unalloc_sub(p->sub->next); } else if (ast_bridged_channel(p->sub->next->owner)) { if (p->sub->owner->_state == AST_STATE_RINGING) { ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); } ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); return -1; } /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); p->sub = p->sub->next; unalloc_sub(p->sub->next); /* Tell the caller not to hangup */ return 1; } else { ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", p->sub->owner->name, p->sub->next->owner->name); p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; if (p->sub->next->owner) { p->sub->next->alreadygone = 1; mgcp_queue_hangup(p->sub->next); } } return 0; }
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 3555 of file chan_mgcp.c.
References __ourip, mgcp_endpoint::accountcode, mgcp_gateway::addr, adsi, mgcp_endpoint::adsi, amaflags, 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_verb, mgcp_endpoint::callgroup, callreturn, mgcp_endpoint::callreturn, callwaiting, mgcp_endpoint::callwaiting, cancallforward, mgcp_endpoint::cancallforward, capability, mgcp_endpoint::capability, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, mgcp_endpoint::cmd_queue_lock, mgcp_endpoint::context, cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, DEFAULT_MGCP_GW_PORT, mgcp_endpoint::delme, mgcp_gateway::delme, directmedia, mgcp_endpoint::directmedia, DIRECTMEDIA, dtmfmode, 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, immediate, 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, nat, 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, singlepath, mgcp_endpoint::singlepath, slowsequence, mgcp_endpoint::slowsequence, strsep(), mgcp_endpoint::sub, threewaycalling, mgcp_endpoint::threewaycalling, transfer, mgcp_endpoint::transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and mgcp_gateway::wcardep.
Referenced by reload_config().
{ struct mgcp_gateway *gw; struct mgcp_endpoint *e; struct mgcp_subchannel *sub; /*char txident[80];*/ int i=0, y=0; int gw_reload = 0; int ep_reload = 0; directmedia = DIRECTMEDIA; /* locate existing gateway */ gw = gateways; while (gw) { if (!strcasecmp(cat, gw->name)) { /* gateway already exists */ gw->delme = 0; gw_reload = 1; break; } gw = gw->next; } if (!gw) gw = ast_calloc(1, sizeof(*gw)); if (gw) { if (!gw_reload) { gw->expire = -1; gw->retransid = -1; /* SC */ ast_mutex_init(&gw->msgs_lock); ast_copy_string(gw->name, cat, sizeof(gw->name)); /* check if the name is numeric ip */ if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) gw->isnamedottedip = 1; } while(v) { if (!strcasecmp(v->name, "host")) { if (!strcasecmp(v->value, "dynamic")) { /* They'll register with us */ gw->dynamic = 1; memset(&gw->addr.sin_addr, 0, 4); if (gw->addr.sin_port) { /* If we've already got a port, make it the default rather than absolute */ gw->defaddr.sin_port = gw->addr.sin_port; gw->addr.sin_port = 0; } } else { /* Non-dynamic. Make sure we become that way if we're not */ AST_SCHED_DEL(sched, gw->expire); gw->dynamic = 0; if (ast_get_ip(&gw->addr, v->value)) { if (!gw_reload) { ast_mutex_destroy(&gw->msgs_lock); ast_free(gw); } return NULL; } } } else if (!strcasecmp(v->name, "defaultip")) { if (ast_get_ip(&gw->defaddr, v->value)) { if (!gw_reload) { ast_mutex_destroy(&gw->msgs_lock); ast_free(gw); } return NULL; } } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); } else if (!strcasecmp(v->name, "port")) { gw->addr.sin_port = htons(atoi(v->value)); } else if (!strcasecmp(v->name, "context")) { ast_copy_string(context, v->value, sizeof(context)); } else if (!strcasecmp(v->name, "dtmfmode")) { if (!strcasecmp(v->value, "inband")) dtmfmode = MGCP_DTMF_INBAND; else if (!strcasecmp(v->value, "rfc2833")) dtmfmode = MGCP_DTMF_RFC2833; else if (!strcasecmp(v->value, "hybrid")) dtmfmode = MGCP_DTMF_HYBRID; else if (!strcasecmp(v->value, "none")) dtmfmode = 0; else ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); } else if (!strcasecmp(v->name, "nat")) { nat = ast_true(v->value); } else if (!strcasecmp(v->name, "callerid")) { if (!strcasecmp(v->value, "asreceived")) { cid_num[0] = '\0'; cid_name[0] = '\0'; } else { ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); } } else if (!strcasecmp(v->name, "language")) { ast_copy_string(language, v->value, sizeof(language)); } else if (!strcasecmp(v->name, "accountcode")) { ast_copy_string(accountcode, v->value, sizeof(accountcode)); } else if (!strcasecmp(v->name, "amaflags")) { y = ast_cdr_amaflags2int(v->value); if (y < 0) { ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); } else { amaflags = y; } } else if (!strcasecmp(v->name, "musiconhold")) { ast_copy_string(musicclass, v->value, sizeof(musicclass)); } else if (!strcasecmp(v->name, "parkinglot")) { ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); } else if (!strcasecmp(v->name, "callgroup")) { cur_callergroup = ast_get_group(v->value); } else if (!strcasecmp(v->name, "pickupgroup")) { cur_pickupgroup = ast_get_group(v->value); } else if (!strcasecmp(v->name, "immediate")) { immediate = ast_true(v->value); } else if (!strcasecmp(v->name, "cancallforward")) { cancallforward = ast_true(v->value); } else if (!strcasecmp(v->name, "singlepath")) { singlepath = ast_true(v->value); } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { directmedia = ast_true(v->value); } else if (!strcasecmp(v->name, "mailbox")) { ast_copy_string(mailbox, v->value, sizeof(mailbox)); } else if (!strcasecmp(v->name, "hasvoicemail")) { if (ast_true(v->value) && ast_strlen_zero(mailbox)) { ast_copy_string(mailbox, gw->name, sizeof(mailbox)); } } else if (!strcasecmp(v->name, "adsi")) { adsi = ast_true(v->value); } else if (!strcasecmp(v->name, "callreturn")) { callreturn = ast_true(v->value); } else if (!strcasecmp(v->name, "callwaiting")) { callwaiting = ast_true(v->value); } else if (!strcasecmp(v->name, "slowsequence")) { slowsequence = ast_true(v->value); } else if (!strcasecmp(v->name, "transfer")) { transfer = ast_true(v->value); } else if (!strcasecmp(v->name, "threewaycalling")) { threewaycalling = ast_true(v->value); } else if (!strcasecmp(v->name, "wcardep")) { /* locate existing endpoint */ e = gw->endpoints; while (e) { if (!strcasecmp(v->value, e->name)) { /* endpoint already exists */ e->delme = 0; ep_reload = 1; break; } e = e->next; } if (!e) { /* Allocate wildcard endpoint */ e = ast_calloc(1, sizeof(*e)); ep_reload = 0; } if (e) { if (!ep_reload) { memset(e, 0, sizeof(struct mgcp_endpoint)); ast_mutex_init(&e->lock); ast_mutex_init(&e->rqnt_queue_lock); ast_mutex_init(&e->cmd_queue_lock); ast_copy_string(e->name, v->value, sizeof(e->name)); e->needaudit = 1; } ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); /* XXX Should we really check for uniqueness?? XXX */ ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); ast_copy_string(e->context, context, sizeof(e->context)); ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); ast_copy_string(e->language, language, sizeof(e->language)); ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); if (!ast_strlen_zero(e->mailbox)) { char *mbox, *cntx; cntx = mbox = ast_strdupa(e->mailbox); strsep(&cntx, "@"); if (ast_strlen_zero(cntx)) cntx = "default"; e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_END); } snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); e->msgstate = -1; e->amaflags = amaflags; e->capability = capability; e->parent = gw; e->dtmfmode = dtmfmode; if (!ep_reload && e->sub && e->sub->rtp) e->dtmfmode |= MGCP_DTMF_INBAND; e->adsi = adsi; e->type = TYPE_LINE; e->immediate = immediate; e->callgroup=cur_callergroup; e->pickupgroup=cur_pickupgroup; e->callreturn = callreturn; e->cancallforward = cancallforward; e->singlepath = singlepath; e->directmedia = directmedia; e->callwaiting = callwaiting; e->hascallwaiting = callwaiting; e->slowsequence = slowsequence; e->transfer = transfer; e->threewaycalling = threewaycalling; e->onhooktime = time(NULL); /* ASSUME we're onhook */ e->hookstate = MGCP_ONHOOK; if (!ep_reload) { /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ for (i = 0; i < MAX_SUBS; i++) { sub = ast_calloc(1, sizeof(*sub)); if (sub) { ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); ast_mutex_init(&sub->lock); ast_mutex_init(&sub->cx_queue_lock); sub->parent = e; sub->id = i; snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ sub->cxmode = MGCP_CX_INACTIVE; sub->nat = nat; sub->next = e->sub; e->sub = sub; } else { /* XXX Should find a way to clean up our memory */ ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); return NULL; } } /* Make out subs a circular linked list so we can always sping through the whole bunch */ sub = e->sub; /* find the end of the list */ while(sub->next){ sub = sub->next; } /* set the last sub->next to the first sub */ sub->next = e->sub; e->next = gw->endpoints; gw->endpoints = e; } } } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) { /* locate existing endpoint */ e = gw->endpoints; while (e) { if (!strcasecmp(v->value, e->name)) { /* endpoint already exists */ e->delme = 0; ep_reload = 1; break; } e = e->next; } if (!e) { e = ast_calloc(1, sizeof(*e)); ep_reload = 0; } if (e) { if (!ep_reload) { ast_mutex_init(&e->lock); ast_mutex_init(&e->rqnt_queue_lock); ast_mutex_init(&e->cmd_queue_lock); ast_copy_string(e->name, v->value, sizeof(e->name)); e->needaudit = 1; } /* XXX Should we really check for uniqueness?? XXX */ ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); ast_copy_string(e->context, context, sizeof(e->context)); ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); ast_copy_string(e->language, language, sizeof(e->language)); ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot)); if (!ast_strlen_zero(mailbox)) { ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); } if (!ep_reload) { /* XXX potential issue due to reload */ e->msgstate = -1; e->parent = gw; } e->amaflags = amaflags; e->capability = capability; e->dtmfmode = dtmfmode; e->adsi = adsi; if (!strcasecmp(v->name, "trunk")) e->type = TYPE_TRUNK; else e->type = TYPE_LINE; e->immediate = immediate; e->callgroup=cur_callergroup; e->pickupgroup=cur_pickupgroup; e->callreturn = callreturn; e->cancallforward = cancallforward; e->directmedia = directmedia; e->singlepath = singlepath; e->callwaiting = callwaiting; e->hascallwaiting = callwaiting; e->slowsequence = slowsequence; e->transfer = transfer; e->threewaycalling = threewaycalling; if (!ep_reload) { e->onhooktime = time(NULL); /* ASSUME we're onhook */ e->hookstate = MGCP_ONHOOK; snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); } for (i = 0, sub = NULL; i < MAX_SUBS; i++) { if (!ep_reload) { sub = ast_calloc(1, sizeof(*sub)); } else { if (!sub) sub = e->sub; else sub = sub->next; } if (sub) { if (!ep_reload) { ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); ast_mutex_init(&sub->lock); ast_mutex_init(&sub->cx_queue_lock); ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); sub->parent = e; sub->id = i; snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); sub->cxmode = MGCP_CX_INACTIVE; sub->next = e->sub; e->sub = sub; } sub->nat = nat; } else { /* XXX Should find a way to clean up our memory */ ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); return NULL; } } if (!ep_reload) { /* Make out subs a circular linked list so we can always sping through the whole bunch */ sub = e->sub; /* find the end of the list */ while (sub->next) { sub = sub->next; } /* set the last sub->next to the first sub */ sub->next = e->sub; e->next = gw->endpoints; gw->endpoints = e; } } } else ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); v = v->next; } } if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); if (!gw_reload) { ast_mutex_destroy(&gw->msgs_lock); ast_free(gw); } return NULL; } gw->defaddr.sin_family = AF_INET; gw->addr.sin_family = AF_INET; if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); if (gw->addr.sin_addr.s_addr) if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); return (gw_reload ? NULL : gw); }
static char* control2str | ( | int | ind | ) | [static] |
Definition at line 1394 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().
{ switch (ind) { case AST_CONTROL_HANGUP: return "Other end has hungup"; case AST_CONTROL_RING: return "Local ring"; case AST_CONTROL_RINGING: return "Remote end is ringing"; case AST_CONTROL_ANSWER: return "Remote end has answered"; case AST_CONTROL_BUSY: return "Remote end is busy"; case AST_CONTROL_TAKEOFFHOOK: return "Make it go off hook"; case AST_CONTROL_OFFHOOK: return "Line is off hook"; case AST_CONTROL_CONGESTION: return "Congestion (circuits busy)"; case AST_CONTROL_FLASH: return "Flash hook"; case AST_CONTROL_WINK: return "Wink"; case AST_CONTROL_OPTION: return "Set a low-level option"; case AST_CONTROL_RADIO_KEY: return "Key Radio"; case AST_CONTROL_RADIO_UNKEY: return "Un-Key Radio"; } return "UNKNOWN"; }
static void destroy_endpoint | ( | struct mgcp_endpoint * | e | ) | [static] |
Definition at line 3980 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_destroy(), ast_strlen_zero(), 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().
{ struct mgcp_subchannel *sub = e->sub->next, *s; int i; for (i = 0; i < MAX_SUBS; i++) { ast_mutex_lock(&sub->lock); if (!ast_strlen_zero(sub->cxident)) { transmit_connection_del(sub); } if (sub->rtp) { ast_rtp_destroy(sub->rtp); sub->rtp = NULL; } memset(sub->magic, 0, sizeof(sub->magic)); mgcp_queue_hangup(sub); dump_cmd_queues(NULL, sub); ast_mutex_unlock(&sub->lock); sub = sub->next; } if (e->dsp) { ast_dsp_free(e->dsp); } dump_queue(e->parent, e); dump_cmd_queues(e, NULL); sub = e->sub; for (i = 0; (i < MAX_SUBS) && sub; i++) { s = sub; sub = sub->next; ast_mutex_destroy(&s->lock); ast_mutex_destroy(&s->cx_queue_lock); ast_free(s); } if (e->mwi_event_sub) ast_event_unsubscribe(e->mwi_event_sub); ast_mutex_destroy(&e->lock); ast_mutex_destroy(&e->rqnt_queue_lock); ast_mutex_destroy(&e->cmd_queue_lock); ast_free(e); }
static void destroy_gateway | ( | struct mgcp_gateway * | g | ) | [static] |
Definition at line 4026 of file chan_mgcp.c.
References ast_free, ast_free_ha(), dump_queue(), and mgcp_gateway::ha.
Referenced by prune_gateways().
{ if (g->ha) ast_free_ha(g->ha); dump_queue(g, NULL); ast_free(g); }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 3386 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, mgcp_reloading, mgcpsock_read(), monlock, netlock, reload_config(), transmit_notify_request(), and TYPE_LINE.
Referenced by restart_monitor().
{ int res; int reloading; /*struct mgcp_gateway *g;*/ /*struct mgcp_endpoint *e;*/ /*time_t thispass = 0, lastpass = 0;*/ /* Add an I/O event to our UDP socket */ if (mgcpsock > -1) mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); /* This thread monitors all the frame relay interfaces which are not yet in use (and thus do not have a separate thread) indefinitely */ /* From here on out, we die whenever asked */ for(;;) { /* Check for a reload request */ ast_mutex_lock(&mgcp_reload_lock); reloading = mgcp_reloading; mgcp_reloading = 0; ast_mutex_unlock(&mgcp_reload_lock); if (reloading) { ast_verb(1, "Reloading MGCP\n"); reload_config(1); /* Add an I/O event to our UDP socket */ if (mgcpsock > -1 && !mgcpsock_read_id) { mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); } } /* Check for interfaces needing to be killed */ /* Don't let anybody kill us right away. Nobody should lock the interface list and wait for the monitor list, but the other way around is okay. */ ast_mutex_lock(&monlock); /* Lock the network interface */ ast_mutex_lock(&netlock); #if 0 /* XXX THIS IS COMPLETELY HOSED */ /* The gateway goes into a state of panic */ /* If the vmwi indicator is sent while it is reseting interfaces */ lastpass = thispass; thispass = time(NULL); g = gateways; while(g) { if (thispass != lastpass) { e = g->endpoints; while(e) { if (e->type == TYPE_LINE) { res = has_voicemail(e); if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ if (res) { transmit_notify_request(e, "L/vmwi(+)"); } else { transmit_notify_request(e, "L/vmwi(-)"); } e->msgstate = res; e->onhooktime = thispass; } } e = e->next; } } g = g->next; } #endif /* Okay, now that we know what to do, release the network lock */ ast_mutex_unlock(&netlock); /* And from now on, we're okay to be killed, so release the monitor lock as well */ ast_mutex_unlock(&monlock); pthread_testcancel(); /* Wait for sched or io */ res = ast_sched_wait(sched); /* copied from chan_sip.c */ if ((res < 0) || (res > 1000)) res = 1000; res = ast_io_wait(io, res); ast_mutex_lock(&monlock); if (res >= 0) ast_sched_runq(sched); ast_mutex_unlock(&monlock); } /* Never reached */ return NULL; }
static void dump_cmd_queues | ( | struct mgcp_endpoint * | p, |
struct mgcp_subchannel * | sub | ||
) | [static] |
dump_cmd_queues: (SC:) cleanup pending commands
Definition at line 2391 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().
{ struct mgcp_request *t, *q; if (p) { ast_mutex_lock(&p->rqnt_queue_lock); for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t); p->rqnt_queue = NULL; ast_mutex_unlock(&p->rqnt_queue_lock); ast_mutex_lock(&p->cmd_queue_lock); for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t); p->cmd_queue = NULL; ast_mutex_unlock(&p->cmd_queue_lock); ast_mutex_lock(&p->sub->cx_queue_lock); for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t); p->sub->cx_queue = NULL; ast_mutex_unlock(&p->sub->cx_queue_lock); ast_mutex_lock(&p->sub->next->cx_queue_lock); for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t); p->sub->next->cx_queue = NULL; ast_mutex_unlock(&p->sub->next->cx_queue_lock); } else if (sub) { ast_mutex_lock(&sub->cx_queue_lock); for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t); sub->cx_queue = NULL; ast_mutex_unlock(&sub->cx_queue_lock); } }
static void dump_queue | ( | struct mgcp_gateway * | gw, |
struct mgcp_endpoint * | p | ||
) | [static] |
Definition at line 555 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().
{ struct mgcp_message *cur, *q = NULL, *w, *prev; ast_mutex_lock(&gw->msgs_lock); prev = NULL, cur = gw->msgs; while (cur) { if (!p || cur->owner_ep == p) { if (prev) prev->next = cur->next; else gw->msgs = cur->next; ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", gw->name, cur->seqno); w = cur; cur = cur->next; if (q) { w->next = q; } else { w->next = NULL; } q = w; } else { prev = cur, cur=cur->next; } } ast_mutex_unlock(&gw->msgs_lock); while (q) { cur = q; q = q->next; ast_free(cur); } }
static int find_and_retrans | ( | struct mgcp_subchannel * | sub, |
struct mgcp_request * | req | ||
) | [static] |
Definition at line 3265 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().
{ int seqno=0; time_t now; struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL; time(&now); if (sscanf(req->identifier, "%30d", &seqno) != 1) seqno = 0; cur = sub->parent->parent->responses; while(cur) { next = cur->next; if (now - cur->whensent > RESPONSE_TIMEOUT) { /* Delete this entry */ if (prev) prev->next = next; else sub->parent->parent->responses = next; ast_free(cur); } else { if (seqno == cur->seqno) answer = cur; prev = cur; } cur = next; } if (answer) { resend_response(sub, answer); return 1; } return 0; }
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 2425 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 handle_response().
{ struct mgcp_request *prev, *req; ast_mutex_lock(l); for (prev = NULL, req = *queue; req; prev = req, req = req->next) { if (req->trid == ident) { /* remove from queue */ if (!prev) *queue = req->next; else prev->next = req->next; /* send next pending command */ if (*queue) { if (mgcpdebug) { ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); } mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); } break; } } ast_mutex_unlock(l); return req; }
static struct mgcp_subchannel* find_subchannel_and_lock | ( | char * | name, |
int | msgid, | ||
struct sockaddr_in * | sin | ||
) | [static, read] |
Definition at line 1628 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().
{ struct mgcp_endpoint *p = NULL; struct mgcp_subchannel *sub = NULL; struct mgcp_gateway *g; char tmp[256] = ""; char *at = NULL, *c; int found = 0; if (name) { ast_copy_string(tmp, name, sizeof(tmp)); at = strchr(tmp, '@'); if (!at) { ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); return NULL; } *at++ = '\0'; } ast_mutex_lock(&gatelock); if (at && (at[0] == '[')) { at++; c = strrchr(at, ']'); if (c) *c = '\0'; } g = gateways; while(g) { if ((!name || !strcasecmp(g->name, at)) && (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ if (sin && g->dynamic && name) { if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || (g->addr.sin_port != sin->sin_port)) { memcpy(&g->addr, sin, sizeof(g->addr)); if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip)) memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 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)); } } /* not dynamic, check if the name matches */ else if (name) { if (strcasecmp(g->name, at)) { g = g->next; continue; } } /* not dynamic, no name, check if the addr matches */ else if (!name && sin) { if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || (g->addr.sin_port != sin->sin_port)) { g = g->next; continue; } } else { g = g->next; continue; } /* SC */ p = g->endpoints; while(p) { ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name); if (msgid) { #if 0 /* new transport mech */ sub = p->sub; do { ast_debug(1, "Searching on %s@%s-%d for subchannel with lastout: %d\n", p->name, g->name, sub->id, msgid); if (sub->lastout == msgid) { ast_debug(1, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", sub->id, msgid, sub->lastout); found = 1; break; } sub = sub->next; } while (sub != p->sub); if (found) { break; } #endif /* SC */ sub = p->sub; found = 1; /* SC */ break; } else if (name && !strcasecmp(p->name, tmp)) { ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", p->name, g->name, p->sub->id); sub = p->sub; found = 1; break; } p = p->next; } if (sub && found) { ast_mutex_lock(&sub->lock); break; } } g = g->next; } ast_mutex_unlock(&gatelock); if (!sub) { if (name) { if (g) ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); else ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); } } return sub; }
static char* get_csv | ( | char * | c, |
int * | len, | ||
char ** | next | ||
) | [static] |
get_csv: (SC:) get comma separated value
Definition at line 1607 of file chan_mgcp.c.
References s.
Referenced by handle_response().
static char* get_header | ( | struct mgcp_request * | req, |
char * | name | ||
) | [static] |
Definition at line 1600 of file chan_mgcp.c.
References __get_header().
Referenced by handle_request(), and handle_response().
{ int start = 0; return __get_header(req, name, &start); }
static char* get_sdp | ( | struct mgcp_request * | req, |
char * | name | ||
) | [static] |
Definition at line 1552 of file chan_mgcp.c.
References get_sdp_by_line(), len(), mgcp_request::line, and mgcp_request::lines.
Referenced by process_sdp().
static char* get_sdp_by_line | ( | char * | line, |
char * | name, | ||
int | nameLen | ||
) | [static] |
Definition at line 1542 of file chan_mgcp.c.
Referenced by get_sdp(), and get_sdp_iterate().
{ if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { char* r = line + nameLen + 1; while (*r && (*r < 33)) ++r; return r; } return ""; }
static char* get_sdp_iterate | ( | int * | iterator, |
struct mgcp_request * | req, | ||
char * | name | ||
) | [static] |
Definition at line 1570 of file chan_mgcp.c.
References get_sdp_by_line(), len(), and mgcp_request::line.
Referenced by process_sdp().
static void handle_hd_hf | ( | struct mgcp_subchannel * | sub, |
char * | ev | ||
) | [static] |
Definition at line 2941 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().
{ struct mgcp_endpoint *p = sub->parent; struct ast_channel *c; pthread_t t; /* Off hook / answer */ if (sub->outgoing) { /* Answered */ if (sub->owner) { if (ast_bridged_channel(sub->owner)) ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { start_rtp(sub); } else { transmit_modify_request(sub); } /*transmit_notify_request(sub, "aw");*/ transmit_notify_request(sub, ""); mgcp_queue_control(sub, AST_CONTROL_ANSWER); } } else { /* Start switch */ /*sub->cxmode = MGCP_CX_SENDRECV;*/ if (!sub->owner) { if (!sub->rtp) { start_rtp(sub); } else { transmit_modify_request(sub); } if (p->immediate) { /* The channel is immediately up. Start right away */ #ifdef DLINK_BUGGY_FIRMWARE transmit_notify_request(sub, "rt"); #else transmit_notify_request(sub, "G/rt"); #endif c = mgcp_new(sub, AST_STATE_RING); if (!c) { ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); transmit_notify_request(sub, "G/cg"); ast_hangup(c); } } else { if (has_voicemail(p)) { transmit_notify_request(sub, "L/sl"); } else { transmit_notify_request(sub, "L/dl"); } c = mgcp_new(sub, AST_STATE_DOWN); if (c) { if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) { ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); ast_hangup(c); } } else { ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); } } } else { if (p->hookstate == MGCP_OFFHOOK) { ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); } else { ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); } if (ast_bridged_channel(sub->owner)) ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { start_rtp(sub); } else { transmit_modify_request(sub); } /*transmit_notify_request(sub, "aw");*/ transmit_notify_request(sub, ""); /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ } } }
static char* handle_mgcp_audit_endpoint | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 1077 of file chan_mgcp.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, mgcp_gateway::endpoints, ast_cli_args::fd, gatelock, gateways, me, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, transmit_audit_endpoint(), and ast_cli_entry::usage.
{ struct mgcp_gateway *mg; struct mgcp_endpoint *me; int found = 0; char *ename,*gname, *c; switch (cmd) { case CLI_INIT: e->command = "mgcp audit endpoint"; e->usage = "Usage: mgcp audit endpoint <endpointid>\n" " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n" " mgcp debug MUST be on to see the results of this command.\n"; return NULL; case CLI_GENERATE: return NULL; } if (!mgcpdebug) { return CLI_SHOWUSAGE; } if (a->argc != 4) return CLI_SHOWUSAGE; /* split the name into parts by null */ ename = a->argv[3]; gname = ename; while (*gname) { if (*gname == '@') { *gname = 0; gname++; break; } gname++; } if (gname[0] == '[') gname++; if ((c = strrchr(gname, ']'))) *c = '\0'; ast_mutex_lock(&gatelock); mg = gateways; while(mg) { if (!strcasecmp(mg->name, gname)) { me = mg->endpoints; while(me) { if (!strcasecmp(me->name, ename)) { found = 1; transmit_audit_endpoint(me); break; } me = me->next; } if (found) { break; } } mg = mg->next; } if (!found) { ast_cli(a->fd, " << Could not find endpoint >> "); } ast_mutex_unlock(&gatelock); return CLI_SUCCESS; }
static char* handle_mgcp_set_debug | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 1142 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.
{ switch (cmd) { case CLI_INIT: e->command = "mgcp set debug {on|off}"; e->usage = "Usage: mgcp set debug {on|off}\n" " Enables/Disables dumping of MGCP packets for debugging purposes\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != e->args) return CLI_SHOWUSAGE; if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { mgcpdebug = 1; ast_cli(a->fd, "MGCP Debugging Enabled\n"); } else if (!strncasecmp(a->argv[3], "off", 3)) { mgcpdebug = 0; ast_cli(a->fd, "MGCP Debugging Disabled\n"); } else { return CLI_SHOWUSAGE; } return CLI_SUCCESS; }
static char* handle_mgcp_show_endpoints | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 1037 of file chan_mgcp.c.
References mgcp_gateway::addr, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), 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, me, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, mgcp_subchannel::owner, mgcp_endpoint::sub, ast_cli_entry::usage, and mgcp_gateway::wcardep.
{ struct mgcp_gateway *mg; struct mgcp_endpoint *me; int hasendpoints = 0; switch (cmd) { case CLI_INIT: e->command = "mgcp show endpoints"; e->usage = "Usage: mgcp show endpoints\n" " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n"; return NULL; case CLI_GENERATE: return NULL; } if (a->argc != 3) return CLI_SHOWUSAGE; ast_mutex_lock(&gatelock); mg = gateways; while(mg) { me = mg->endpoints; 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"); while(me) { /* Don't show wilcard endpoint */ if (strcmp(me->name, mg->wcardep) != 0) ast_cli(a->fd, " -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle"); hasendpoints = 1; me = me->next; } if (!hasendpoints) { ast_cli(a->fd, " << No Endpoints Defined >> "); } mg = mg->next; } ast_mutex_unlock(&gatelock); return CLI_SUCCESS; }
static int handle_request | ( | struct mgcp_subchannel * | sub, |
struct mgcp_request * | req, | ||
struct sockaddr_in * | sin | ||
) | [static] |
Definition at line 3023 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().
{ char *ev, *s; struct ast_frame f = { 0, }; struct mgcp_endpoint *p = sub->parent; struct mgcp_gateway *g = NULL; int res; if (mgcpdebug) { ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); } /* Clear out potential response */ if (!strcasecmp(req->verb, "RSIP")) { /* Test if this RSIP request is just a keepalive */ if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) { ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name); transmit_response(sub, "200", req, "OK"); } else { dump_queue(p->parent, p); dump_cmd_queues(p, NULL); if ((strcmp(p->name, p->parent->wcardep) != 0)) { ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name); } /* For RSIP on wildcard we reset all endpoints */ if (!strcmp(p->name, p->parent->wcardep)) { /* Reset all endpoints */ struct mgcp_endpoint *tmp_ep; g = p->parent; tmp_ep = g->endpoints; while (tmp_ep) { /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ if (strcmp(tmp_ep->name, g->wcardep) != 0) { struct mgcp_subchannel *tmp_sub, *first_sub; ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); first_sub = tmp_ep->sub; tmp_sub = tmp_ep->sub; while (tmp_sub) { mgcp_queue_hangup(tmp_sub); tmp_sub = tmp_sub->next; if (tmp_sub == first_sub) break; } } tmp_ep = tmp_ep->next; } } else if (sub->owner) { mgcp_queue_hangup(sub); } transmit_response(sub, "200", req, "OK"); /* We dont send NTFY or AUEP to wildcard ep */ if (strcmp(p->name, p->parent->wcardep) != 0) { transmit_notify_request(sub, ""); /* Audit endpoint. Idea is to prevent lost lines due to race conditions */ transmit_audit_endpoint(p); } } } else if (!strcasecmp(req->verb, "NTFY")) { /* Acknowledge and be sure we keep looking for the same things */ transmit_response(sub, "200", req, "OK"); /* Notified of an event */ ev = get_header(req, "O"); s = strchr(ev, '/'); if (s) ev = s + 1; ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); /* Keep looking for events unless this was a hangup */ if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { transmit_notify_request(sub, p->curtone); } if (!strcasecmp(ev, "hd")) { p->hookstate = MGCP_OFFHOOK; sub->cxmode = MGCP_CX_SENDRECV; handle_hd_hf(sub, ev); } else if (!strcasecmp(ev, "hf")) { /* We can assume we are offhook if we received a hookflash */ /* First let's just do call wait and ignore threeway */ /* We're currently in charge */ if (p->hookstate != MGCP_OFFHOOK) { /* Cisco c7940 sends hf even if the phone is onhook */ /* Thanks to point on IRC for pointing this out */ return -1; } /* do not let * conference two down channels */ if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1; if (p->callwaiting || p->transfer || p->threewaycalling) { ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); p->sub = p->sub->next; /* transfer control to our next subchannel */ if (!sub->next->owner) { /* plave the first call on hold and start up a new call */ sub->cxmode = MGCP_CX_MUTE; ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); transmit_modify_request(sub); if (sub->owner && ast_bridged_channel(sub->owner)) ast_queue_control(sub->owner, AST_CONTROL_HOLD); sub->next->cxmode = MGCP_CX_RECVONLY; handle_hd_hf(sub->next, ev); } else if (sub->owner && sub->next->owner) { /* We've got two active calls lets decide whether or not to conference or just flip flop */ if ((!sub->outgoing) && (!sub->next->outgoing)) { /* We made both calls lets conferenct */ ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n", sub->id, sub->next->id, p->name, p->parent->name); sub->cxmode = MGCP_CX_CONF; sub->next->cxmode = MGCP_CX_CONF; if (ast_bridged_channel(sub->next->owner)) ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); transmit_modify_request(sub); transmit_modify_request(sub->next); } else { /* Let's flipflop between calls */ /* XXX Need to check for state up ??? */ /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", sub->id, sub->next->id, p->name, p->parent->name); sub->cxmode = MGCP_CX_MUTE; ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); transmit_modify_request(sub); if (ast_bridged_channel(sub->owner)) ast_queue_control(sub->owner, AST_CONTROL_HOLD); if (ast_bridged_channel(sub->next->owner)) ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); handle_hd_hf(sub->next, ev); } } else { /* We've most likely lost one of our calls find an active call and bring it up */ if (sub->owner) { p->sub = sub; } else if (sub->next->owner) { p->sub = sub->next; } else { /* We seem to have lost both our calls */ /* XXX - What do we do now? */ return -1; } if (ast_bridged_channel(p->sub->owner)) ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); p->sub->cxmode = MGCP_CX_SENDRECV; transmit_modify_request(p->sub); } } else { ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", p->name, p->parent->name); } } else if (!strcasecmp(ev, "hu")) { p->hookstate = MGCP_ONHOOK; sub->cxmode = MGCP_CX_RECVONLY; ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); /* Do we need to send MDCX before a DLCX ? if (sub->rtp) { transmit_modify_request(sub); } */ if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { /* We're allowed to transfer, we have two avtive calls and */ /* we made at least one of the calls. Let's try and transfer */ ast_mutex_lock(&p->sub->next->lock); res = attempt_transfer(p); if (res < 0) { if (p->sub->next->owner) { sub->next->alreadygone = 1; mgcp_queue_hangup(sub->next); } } else if (res) { ast_log(LOG_WARNING, "Transfer attempt failed\n"); ast_mutex_unlock(&p->sub->next->lock); return -1; } ast_mutex_unlock(&p->sub->next->lock); } else { /* Hangup the current call */ /* If there is another active call, mgcp_hangup will ring the phone with the other call */ if (sub->owner) { sub->alreadygone = 1; mgcp_queue_hangup(sub); } else { ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", p->name, p->parent->name, sub->id); /* Instruct the other side to remove the connection since it apparently * * still thinks the channel is active. * * For Cisco IAD2421 /BAK/ */ transmit_connection_del(sub); } } if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { p->hidecallerid = 0; if (p->hascallwaiting && !p->callwaiting) { ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); p->callwaiting = -1; } if (has_voicemail(p)) { ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); transmit_notify_request(sub, "L/vmwi(+)"); } else { ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); transmit_notify_request(sub, "L/vmwi(-)"); } } } else if ((strlen(ev) == 1) && (((ev[0] >= '0') && (ev[0] <= '9')) || ((ev[0] >= 'A') && (ev[0] <= 'D')) || (ev[0] == '*') || (ev[0] == '#'))) { if (sub && sub->owner && (sub->owner->_state >= AST_STATE_UP)) { f.frametype = AST_FRAME_DTMF; f.subclass = ev[0]; f.src = "mgcp"; /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ mgcp_queue_frame(sub, &f); ast_mutex_lock(&sub->next->lock); if (sub->next->owner) mgcp_queue_frame(sub->next, &f); ast_mutex_unlock(&sub->next->lock); if (strstr(p->curtone, "wt") && (ev[0] == 'A')) { memset(p->curtone, 0, sizeof(p->curtone)); } } else { p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0]; p->dtmf_buf[strlen(p->dtmf_buf)] = '\0'; } } else if (!strcasecmp(ev, "T")) { /* Digit timeout -- unimportant */ } else if (!strcasecmp(ev, "ping")) { /* ping -- unimportant */ } else { ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); } } else { ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); transmit_response(sub, "510", req, "Unknown verb"); } return 0; }
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 2456 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 mgcpsock_read(), and retrans_pkt().
{ char *c; struct mgcp_request *req; struct mgcp_gateway *gw = p->parent; if (result < 200) { /* provisional response */ return; } if (p->slowsequence) req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); else if (sub) req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); if (!req) { ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n", gw->name, ident); return; } if (p && (result >= 400) && (result <= 599)) { switch (result) { case 401: p->hookstate = MGCP_OFFHOOK; break; case 402: p->hookstate = MGCP_ONHOOK; break; case 406: ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); break; case 407: ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); break; } if (sub) { if (sub->owner) { ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", result, p->name, p->parent->name, sub ? sub->id:-1); mgcp_queue_hangup(sub); } } else { if (p->sub->next->owner) { ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", result, p->name, p->parent->name, sub ? sub->id:-1); mgcp_queue_hangup(p->sub); } if (p->sub->owner) { ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", result, p->name, p->parent->name, sub ? sub->id:-1); mgcp_queue_hangup(p->sub); } dump_cmd_queues(p, NULL); } } if (resp) { if (req->cmd == MGCP_CMD_CRCX) { if ((c = get_header(resp, "I"))) { if (!ast_strlen_zero(c) && sub) { /* if we are hanging up do not process this conn. */ if (sub->owner) { if (!ast_strlen_zero(sub->cxident)) { if (strcasecmp(c, sub->cxident)) { ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); } } ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); if (sub->tmpdest.sin_addr.s_addr) { transmit_modify_with_sdp(sub, NULL, 0); } } else { /* XXX delete this one callid and conn id may already be lost. so the following del conn may have a side effect of cleaning up the next subchannel */ transmit_connection_del(sub); } } } } if (req->cmd == MGCP_CMD_AUEP) { /* check stale connection ids */ if ((c = get_header(resp, "I"))) { char *v, *n; int len; while ((v = get_csv(c, &len, &n))) { if (len) { if (strncasecmp(v, p->sub->cxident, len) && strncasecmp(v, p->sub->next->cxident, len)) { /* connection id not found. delete it */ char cxident[80] = ""; if (len > (sizeof(cxident) - 1)) len = sizeof(cxident) - 1; ast_copy_string(cxident, v, len); ast_verb(3, "Non existing connection id %s on %s@%s \n", cxident, p->name, gw->name); transmit_connection_del_w_params(p, NULL, cxident); } } c = n; } } /* Try to determine the hookstate returned from an audit endpoint command */ if ((c = get_header(resp, "ES"))) { if (!ast_strlen_zero(c)) { if (strstr(c, "hu")) { if (p->hookstate != MGCP_ONHOOK) { /* XXX cleanup if we think we are offhook XXX */ if ((p->sub->owner || p->sub->next->owner ) && p->hookstate == MGCP_OFFHOOK) mgcp_queue_hangup(sub); p->hookstate = MGCP_ONHOOK; /* update the requested events according to the new hookstate */ transmit_notify_request(p->sub, ""); ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); } } else if (strstr(c, "hd")) { if (p->hookstate != MGCP_OFFHOOK) { p->hookstate = MGCP_OFFHOOK; /* update the requested events according to the new hookstate */ transmit_notify_request(p->sub, ""); ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); } } } } } if (resp && resp->lines) { /* do not process sdp if we are hanging up. this may be a late response */ if (sub && sub->owner) { if (!sub->rtp) start_rtp(sub); if (sub->rtp) process_sdp(sub, resp); } } } ast_free(req); }
static int has_voicemail | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 462 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().
Referenced by do_monitor(), handle_hd_hf(), handle_request(), mgcp_hangup(), and mgcp_request().
{ int new_msgs; struct ast_event *event; char *mbox, *cntx; cntx = mbox = ast_strdupa(p->mailbox); strsep(&cntx, "@"); if (ast_strlen_zero(cntx)) cntx = "default"; event = ast_event_get_cached(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx, AST_EVENT_IE_END); if (event) { new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); ast_event_destroy(event); } else new_msgs = ast_app_has_voicemail(p->mailbox, NULL); return new_msgs; }
static int init_req | ( | struct mgcp_endpoint * | p, |
struct mgcp_request * | req, | ||
char * | verb | ||
) | [static] |
Definition at line 1989 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 reqprep().
{ /* Initialize a response */ if (req->headers || req->len) { ast_log(LOG_WARNING, "Request already initialized?!?\n"); return -1; } req->header[req->headers] = req->data + req->len; /* check if we need brackets around the gw name */ if (p->parent->isnamedottedip) 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); else 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); req->len += strlen(req->header[req->headers]); if (req->headers < MGCP_MAX_HEADERS) req->headers++; else ast_log(LOG_WARNING, "Out of header space\n"); return 0; }
static int init_resp | ( | struct mgcp_request * | req, |
char * | resp, | ||
struct mgcp_request * | orig, | ||
char * | resprest | ||
) | [static] |
Definition at line 1972 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().
{ /* Initialize a response */ if (req->headers || req->len) { ast_log(LOG_WARNING, "Request already initialized?!?\n"); return -1; } req->header[req->headers] = req->data + req->len; snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); req->len += strlen(req->header[req->headers]); if (req->headers < MGCP_MAX_HEADERS) req->headers++; else ast_log(LOG_WARNING, "Out of header space\n"); return 0; }
static int load_module | ( | void | ) | [static] |
load_module: PBX load module - initialization ---
Definition at line 4259 of file chan_mgcp.c.
References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), and sched_context_destroy().
{ if (!(sched = sched_context_create())) { ast_log(LOG_WARNING, "Unable to create schedule context\n"); return AST_MODULE_LOAD_FAILURE; } if (!(io = io_context_create())) { ast_log(LOG_WARNING, "Unable to create I/O context\n"); sched_context_destroy(sched); return AST_MODULE_LOAD_FAILURE; } if (reload_config(0)) return AST_MODULE_LOAD_DECLINE; /* Make sure we can register our mgcp channel type */ if (ast_channel_register(&mgcp_tech)) { ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n"); io_context_destroy(io); sched_context_destroy(sched); return AST_MODULE_LOAD_FAILURE; } ast_rtp_proto_register(&mgcp_rtp); ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); /* And start the monitor for the first time */ restart_monitor(); return AST_MODULE_LOAD_SUCCESS; }
static int mgcp_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1177 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().
{ int res = 0; struct mgcp_subchannel *sub = ast->tech_pvt; struct mgcp_endpoint *p = sub->parent; ast_mutex_lock(&sub->lock); sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { start_rtp(sub); } else { transmit_modify_request(sub); } ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n", ast->name, p->name, p->parent->name, sub->id); if (ast->_state != AST_STATE_UP) { ast_setstate(ast, AST_STATE_UP); ast_debug(1, "mgcp_answer(%s)\n", ast->name); transmit_notify_request(sub, ""); transmit_modify_request(sub); } ast_mutex_unlock(&sub->lock); return res; }
static int mgcp_call | ( | struct ast_channel * | ast, |
char * | dest, | ||
int | timeout | ||
) | [static] |
Definition at line 843 of file chan_mgcp.c.
References ast_channel::_state, AST_CONTROL_RINGING, ast_copy_string(), AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_verb, mgcp_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, ast_var_t::entries, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_subchannel::parent, mgcp_subchannel::rtp, start_rtp(), ast_channel::tech_pvt, transmit_modify_request(), transmit_notify_request_with_callerid(), mgcp_endpoint::type, TYPE_LINE, and ast_channel::varshead.
{ int res; struct mgcp_endpoint *p; struct mgcp_subchannel *sub; char tone[50] = ""; const char *distinctive_ring = NULL; struct varshead *headp; struct ast_var_t *current; if (mgcpdebug) { ast_verb(3, "MGCP mgcp_call(%s)\n", ast->name); } sub = ast->tech_pvt; p = sub->parent; headp = &ast->varshead; AST_LIST_TRAVERSE(headp,current,entries) { /* Check whether there is an ALERT_INFO variable */ if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { distinctive_ring = ast_var_value(current); } } ast_mutex_lock(&sub->lock); switch (p->hookstate) { case MGCP_OFFHOOK: if (!ast_strlen_zero(distinctive_ring)) { snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); if (mgcpdebug) { ast_verb(3, "MGCP distinctive callwait %s\n", tone); } } else { ast_copy_string(tone, "L/wt", sizeof(tone)); if (mgcpdebug) { ast_verb(3, "MGCP normal callwait %s\n", tone); } } break; case MGCP_ONHOOK: default: if (!ast_strlen_zero(distinctive_ring)) { snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); if (mgcpdebug) { ast_verb(3, "MGCP distinctive ring %s\n", tone); } } else { ast_copy_string(tone, "L/rg", sizeof(tone)); if (mgcpdebug) { ast_verb(3, "MGCP default ring\n"); } } break; } if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name); ast_mutex_unlock(&sub->lock); return -1; } res = 0; sub->outgoing = 1; sub->cxmode = MGCP_CX_RECVONLY; if (p->type == TYPE_LINE) { if (!sub->rtp) { start_rtp(sub); } else { transmit_modify_request(sub); } if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { /* try to prevent a callwait from disturbing the other connection */ sub->next->cxmode = MGCP_CX_RECVONLY; transmit_modify_request(sub->next); } transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name); ast_setstate(ast, AST_STATE_RINGING); if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { /* Put the connection back in sendrecv */ sub->next->cxmode = MGCP_CX_SENDRECV; transmit_modify_request(sub->next); } } else { ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); res = -1; } ast_mutex_unlock(&sub->lock); ast_queue_control(ast, AST_CONTROL_RINGING); return res; }
static int mgcp_devicestate | ( | void * | data | ) | [static] |
mgcp_devicestate: channel callback for device status monitoring
data | tech/resource name of MGCP device to query |
Callback for device state management in channel subsystem to obtain device status (up/down) of a specific MGCP endpoint
Definition at line 1346 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.
{ struct mgcp_gateway *g; struct mgcp_endpoint *e = NULL; char *tmp, *endpt, *gw; int ret = AST_DEVICE_INVALID; endpt = ast_strdupa(data); if ((tmp = strchr(endpt, '@'))) { *tmp++ = '\0'; gw = tmp; } else goto error; ast_mutex_lock(&gatelock); g = gateways; while (g) { if (strcasecmp(g->name, gw) == 0) { e = g->endpoints; break; } g = g->next; } if (!e) goto error; while (e) { if (strcasecmp(e->name, endpt) == 0) break; e = e->next; } if (!e) goto error; /* * As long as the gateway/endpoint is valid, we'll * assume that the device is available and its state * can be tracked. */ ret = AST_DEVICE_UNKNOWN; error: ast_mutex_unlock(&gatelock); return ret; }
static int mgcp_fixup | ( | struct ast_channel * | oldchan, |
struct ast_channel * | newchan | ||
) | [static] |
Definition at line 1273 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.
{ struct mgcp_subchannel *sub = newchan->tech_pvt; ast_mutex_lock(&sub->lock); ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name); if (sub->owner != oldchan) { ast_mutex_unlock(&sub->lock); ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); return -1; } sub->owner = newchan; ast_mutex_unlock(&sub->lock); return 0; }
static enum ast_rtp_get_result mgcp_get_rtp_peer | ( | struct ast_channel * | chan, |
struct ast_rtp ** | rtp | ||
) | [static] |
Definition at line 3947 of file chan_mgcp.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, mgcp_endpoint::directmedia, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
{ struct mgcp_subchannel *sub = NULL; if (!(sub = chan->tech_pvt) || !(sub->rtp)) return AST_RTP_GET_FAILED; *rtp = sub->rtp; if (sub->parent->directmedia) return AST_RTP_TRY_NATIVE; else return AST_RTP_TRY_PARTIAL; }
static int mgcp_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 936 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_bridged_channel(), ast_debug, ast_dsp_free(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_strlen_zero(), ast_verb, mgcp_subchannel::callid, mgcp_endpoint::callwaiting, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::dsp, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, has_voicemail(), mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, mgcp_endpoint::hookstate, mgcp_subchannel::lock, mgcp_subchannel::magic, MGCP_CX_INACTIVE, MGCP_CX_RECVONLY, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_OFFHOOK, MGCP_ONHOOK, MGCP_SUBCHANNEL_MAGIC, 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, ast_module_info::self, 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().
{ struct mgcp_subchannel *sub = ast->tech_pvt; struct mgcp_endpoint *p = sub->parent; ast_debug(1, "mgcp_hangup(%s)\n", ast->name); if (!ast->tech_pvt) { ast_debug(1, "Asked to hangup channel not connected\n"); return 0; } if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) { ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n"); return 0; } ast_mutex_lock(&sub->lock); if (mgcpdebug) { ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name); } if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) { /* check whether other channel is active. */ if (!sub->next->owner) { if (p->dtmfmode & MGCP_DTMF_HYBRID) p->dtmfmode &= ~MGCP_DTMF_INBAND; if (mgcpdebug) { ast_verb(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name); } ast_dsp_free(p->dsp); p->dsp = NULL; } } sub->owner = NULL; if (!ast_strlen_zero(sub->cxident)) { transmit_connection_del(sub); } sub->cxident[0] = '\0'; if ((sub == p->sub) && sub->next->owner) { if (p->hookstate == MGCP_OFFHOOK) { if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 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); } } else { /* set our other connection as the primary and swith over to it */ p->sub = sub->next; p->sub->cxmode = MGCP_CX_RECVONLY; transmit_modify_request(p->sub); if (sub->next->owner && ast_bridged_channel(sub->next->owner)) { 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); } } } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) { transmit_notify_request(sub, "L/v"); } else if (p->hookstate == MGCP_OFFHOOK) { transmit_notify_request(sub, "L/ro"); } else { transmit_notify_request(sub, ""); } ast->tech_pvt = NULL; sub->alreadygone = 0; sub->outgoing = 0; sub->cxmode = MGCP_CX_INACTIVE; sub->callid[0] = '\0'; if (p) { memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); } /* Reset temporary destination */ memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); if (sub->rtp) { ast_rtp_destroy(sub->rtp); sub->rtp = NULL; } ast_module_unref(ast_module_info->self); if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) { p->hidecallerid = 0; if (p->hascallwaiting && !p->callwaiting) { ast_verb(3, "Enabling call waiting on %s\n", ast->name); p->callwaiting = -1; } if (has_voicemail(p)) { if (mgcpdebug) { ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", ast->name, p->name, p->parent->name); } transmit_notify_request(sub, "L/vmwi(+)"); } else { if (mgcpdebug) { ast_verb(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", ast->name, p->name, p->parent->name); } transmit_notify_request(sub, "L/vmwi(-)"); } } ast_mutex_unlock(&sub->lock); return 0; }
static int mgcp_indicate | ( | struct ast_channel * | ast, |
int | ind, | ||
const void * | data, | ||
size_t | datalen | ||
) | [static] |
Definition at line 1426 of file chan_mgcp.c.
References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_change_source(), ast_rtp_new_source(), ast_verb, control2str(), mgcp_subchannel::lock, LOG_WARNING, ast_channel::name, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_notify_request().
{ struct mgcp_subchannel *sub = ast->tech_pvt; int res = 0; if (mgcpdebug) { ast_verb(3, "MGCP asked to indicate %d '%s' condition on channel %s\n", ind, control2str(ind), ast->name); } ast_mutex_lock(&sub->lock); switch(ind) { case AST_CONTROL_RINGING: #ifdef DLINK_BUGGY_FIRMWARE transmit_notify_request(sub, "rt"); #else transmit_notify_request(sub, "G/rt"); #endif break; case AST_CONTROL_BUSY: transmit_notify_request(sub, "L/bz"); break; case AST_CONTROL_CONGESTION: transmit_notify_request(sub, "G/cg"); break; case AST_CONTROL_HOLD: ast_moh_start(ast, data, NULL); break; case AST_CONTROL_UNHOLD: ast_moh_stop(ast); break; case AST_CONTROL_SRCUPDATE: ast_rtp_new_source(sub->rtp); break; case AST_CONTROL_SRCCHANGE: ast_rtp_change_source(sub->rtp); break; case -1: transmit_notify_request(sub, ""); break; default: ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); res = -1; } ast_mutex_unlock(&sub->lock); return res; }
static struct ast_channel* mgcp_new | ( | struct mgcp_subchannel * | sub, |
int | state | ||
) | [static, read] |
Definition at line 1473 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_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtp_fd(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callgroup, ast_channel::callgroup, capability, mgcp_endpoint::capability, ast_channel::cid, ast_callerid::cid_ani, mgcp_endpoint::cid_name, mgcp_endpoint::cid_num, ast_channel::context, mgcp_endpoint::context, mgcp_endpoint::dsp, DSP_DIGITMODE_NOQUELCH, DSP_FEATURE_DIGIT_DETECT, mgcp_endpoint::dtmfmode, ast_channel::exten, mgcp_endpoint::exten, global_jbconf, mgcp_subchannel::id, mgcp_endpoint::language, LOG_WARNING, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, mgcp_tech, ast_channel::name, name, mgcp_gateway::name, mgcp_endpoint::name, ast_channel::nativeformats, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_endpoint::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, mgcp_subchannel::rtp, ast_module_info::self, mgcp_endpoint::sub, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by handle_hd_hf(), and mgcp_request().
{ struct ast_channel *tmp; struct mgcp_endpoint *i = sub->parent; int fmt; tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); if (tmp) { tmp->tech = &mgcp_tech; tmp->nativeformats = i->capability; if (!tmp->nativeformats) tmp->nativeformats = capability; fmt = ast_best_codec(tmp->nativeformats); ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id); if (sub->rtp) ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp)); if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) { i->dsp = ast_dsp_new(); ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT); /* this is to prevent clipping of dtmf tones during dsp processing */ ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH); } else { i->dsp = NULL; } if (state == AST_STATE_RING) tmp->rings = 1; tmp->writeformat = fmt; tmp->rawwriteformat = fmt; tmp->readformat = fmt; tmp->rawreadformat = fmt; tmp->tech_pvt = sub; if (!ast_strlen_zero(i->language)) ast_string_field_set(tmp, language, i->language); if (!ast_strlen_zero(i->accountcode)) ast_string_field_set(tmp, accountcode, i->accountcode); if (i->amaflags) tmp->amaflags = i->amaflags; sub->owner = tmp; ast_module_ref(ast_module_info->self); tmp->callgroup = i->callgroup; tmp->pickupgroup = i->pickupgroup; ast_string_field_set(tmp, call_forward, i->call_forward); ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); /* Don't use ast_set_callerid() here because it will * generate a needless NewCallerID event */ tmp->cid.cid_ani = ast_strdup(i->cid_num); if (!i->adsi) tmp->adsicpe = AST_ADSI_UNAVAILABLE; tmp->priority = 1; if (sub->rtp) ast_jb_configure(tmp, &global_jbconf); if (state != AST_STATE_DOWN) { if (ast_pbx_start(tmp)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); ast_hangup(tmp); tmp = NULL; } } ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n", tmp->name, ast_state2str(state)); } else { ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); } return tmp; }
static int mgcp_postrequest | ( | struct mgcp_endpoint * | p, |
struct mgcp_subchannel * | sub, | ||
char * | data, | ||
int | len, | ||
unsigned int | seqno | ||
) | [static] |
Definition at line 693 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, len(), 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().
{ struct mgcp_message *msg; struct mgcp_message *cur; struct mgcp_gateway *gw; struct timeval now; msg = ast_malloc(sizeof(*msg) + len); if (!msg) { return -1; } gw = ((p && p->parent) ? p->parent : NULL); if (!gw) { ast_free(msg); return -1; } /* SC time(&t); if (gw->messagepending && (gw->lastouttime + 20 < t)) { ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d, lastouttime: %ld, now: %ld. Dumping pending queue\n", gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t); dump_queue(sub->parent); } */ msg->owner_sub = sub; msg->owner_ep = p; msg->seqno = seqno; msg->next = NULL; msg->len = len; msg->retrans = 0; memcpy(msg->buf, data, msg->len); ast_mutex_lock(&gw->msgs_lock); cur = gw->msgs; if (cur) { while(cur->next) cur = cur->next; cur->next = msg; } else { gw->msgs = msg; } now = ast_tvnow(); msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS; if (gw->retransid == -1) gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw); ast_mutex_unlock(&gw->msgs_lock); /* SC if (!gw->messagepending) { gw->messagepending = 1; gw->lastout = seqno; gw->lastouttime = t; */ __mgcp_xmit(gw, msg->buf, msg->len); /* XXX Should schedule retransmission XXX */ /* SC } else ast_debug(1, "Deferring transmission of transaction %d\n", seqno); */ return 0; }
static void mgcp_queue_control | ( | struct mgcp_subchannel * | sub, |
int | control | ||
) | [static] |
Definition at line 624 of file chan_mgcp.c.
References AST_FRAME_CONTROL, mgcp_queue_frame(), and ast_frame::subclass.
Referenced by handle_hd_hf().
{ struct ast_frame f = { AST_FRAME_CONTROL, }; f.subclass = control; return mgcp_queue_frame(sub, &f); }
static void mgcp_queue_frame | ( | struct mgcp_subchannel * | sub, |
struct ast_frame * | f | ||
) | [static] |
Definition at line 592 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().
{ for(;;) { if (sub->owner) { if (!ast_channel_trylock(sub->owner)) { ast_queue_frame(sub->owner, f); ast_channel_unlock(sub->owner); break; } else { DEADLOCK_AVOIDANCE(&sub->lock); } } else break; } }
static void mgcp_queue_hangup | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 608 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().
{ for(;;) { if (sub->owner) { if (!ast_channel_trylock(sub->owner)) { ast_queue_hangup(sub->owner); ast_channel_unlock(sub->owner); break; } else { DEADLOCK_AVOIDANCE(&sub->lock); } } else break; } }
static struct ast_frame * mgcp_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 1233 of file chan_mgcp.c.
References ast_mutex_lock(), ast_mutex_unlock(), f, mgcp_subchannel::lock, mgcp_rtp_read(), and ast_channel::tech_pvt.
{ struct ast_frame *f; struct mgcp_subchannel *sub = ast->tech_pvt; ast_mutex_lock(&sub->lock); f = mgcp_rtp_read(sub); ast_mutex_unlock(&sub->lock); return f; }
static char * mgcp_reload | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 4292 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().
{ static int deprecated = 0; if (e) { switch (cmd) { case CLI_INIT: e->command = "mgcp reload"; e->usage = "Usage: mgcp reload\n" " 'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"; return NULL; case CLI_GENERATE: return NULL; } } if (!deprecated && a && a->argc > 0) { ast_log(LOG_WARNING, "'mgcp reload' is deprecated. Please use 'reload chan_mgcp.so' instead.\n"); deprecated = 1; } ast_mutex_lock(&mgcp_reload_lock); if (mgcp_reloading) { ast_verbose("Previous mgcp reload not yet done\n"); } else mgcp_reloading = 1; ast_mutex_unlock(&mgcp_reload_lock); restart_monitor(); return CLI_SUCCESS; }
static struct ast_channel * mgcp_request | ( | const char * | type, |
int | format, | ||
void * | data, | ||
int * | cause | ||
) | [static, read] |
Definition at line 3501 of file chan_mgcp.c.
References AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_log(), ast_mutex_unlock(), AST_STATE_DOWN, ast_strlen_zero(), ast_verb, mgcp_endpoint::call_forward, mgcp_endpoint::callwaiting, capability, ast_channel::data, mgcp_endpoint::dnd, find_subchannel_and_lock(), format, has_voicemail(), mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_new(), MGCP_ONHOOK, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, restart_monitor(), and transmit_notify_request().
{ int oldformat; struct mgcp_subchannel *sub; struct ast_channel *tmpc = NULL; char tmp[256]; char *dest = data; oldformat = format; format &= capability; if (!format) { ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); return NULL; } ast_copy_string(tmp, dest, sizeof(tmp)); if (ast_strlen_zero(tmp)) { ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n"); return NULL; } sub = find_subchannel_and_lock(tmp, 0, NULL); if (!sub) { ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp); *cause = AST_CAUSE_UNREGISTERED; return NULL; } ast_verb(3, "MGCP mgcp_request(%s)\n", tmp); ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0); /* Must be busy */ if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) || ((!sub->parent->callwaiting) && (sub->owner)) || (sub->parent->dnd && (ast_strlen_zero(sub->parent->call_forward)))) { if (sub->parent->hookstate == MGCP_ONHOOK) { if (has_voicemail(sub->parent)) { transmit_notify_request(sub,"L/vmwi(+)"); } else { transmit_notify_request(sub,"L/vmwi(-)"); } } *cause = AST_CAUSE_BUSY; ast_mutex_unlock(&sub->lock); return NULL; } tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN); ast_mutex_unlock(&sub->lock); if (!tmpc) ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp); restart_monitor(); return tmpc; }
static struct ast_frame* mgcp_rtp_read | ( | struct mgcp_subchannel * | sub | ) | [static, read] |
Definition at line 1202 of file chan_mgcp.c.
References ast_debug, ast_dsp_process(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), mgcp_endpoint::dsp, mgcp_endpoint::dtmfmode, f, 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().
{ /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */ struct ast_frame *f; f = ast_rtp_read(sub->rtp); /* Don't send RFC2833 if we're not supposed to */ if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833)) return &ast_null_frame; if (sub->owner) { /* We already hold the channel lock */ if (f->frametype == AST_FRAME_VOICE) { if (f->subclass != sub->owner->nativeformats) { ast_debug(1, "Oooh, format changed to %d\n", f->subclass); sub->owner->nativeformats = f->subclass; ast_set_read_format(sub->owner, sub->owner->readformat); ast_set_write_format(sub->owner, sub->owner->writeformat); } /* Courtesy fearnor aka alex@pilosoft.com */ if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) { #if 0 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n"); #endif f = ast_dsp_process(sub->owner, sub->parent->dsp, f); } } } return f; }
static int mgcp_senddigit_begin | ( | struct ast_channel * | ast, |
char | digit | ||
) | [static] |
Definition at line 1289 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_begin(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt.
{ struct mgcp_subchannel *sub = ast->tech_pvt; struct mgcp_endpoint *p = sub->parent; int res = 0; ast_mutex_lock(&sub->lock); if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { ast_log(LOG_DEBUG, "Sending DTMF using inband/hybrid\n"); res = -1; /* Let asterisk play inband indications */ } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { ast_log(LOG_DEBUG, "Sending DTMF using RFC2833"); ast_rtp_senddigit_begin(sub->rtp, digit); } else { ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); } ast_mutex_unlock(&sub->lock); return res; }
static int mgcp_senddigit_end | ( | struct ast_channel * | ast, |
char | digit, | ||
unsigned int | duration | ||
) | [static] |
Definition at line 1310 of file chan_mgcp.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_end(), mgcp_endpoint::dtmfmode, mgcp_subchannel::lock, LOG_DEBUG, LOG_ERROR, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, MGCP_DTMF_RFC2833, mgcp_subchannel::parent, mgcp_subchannel::rtp, ast_channel::tech_pvt, and transmit_notify_request().
{ struct mgcp_subchannel *sub = ast->tech_pvt; struct mgcp_endpoint *p = sub->parent; int res = 0; char tmp[4]; ast_mutex_lock(&sub->lock); if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) { ast_log(LOG_DEBUG, "Stopping DTMF using inband/hybrid\n"); res = -1; /* Tell Asterisk to stop inband indications */ } else if (p->dtmfmode & MGCP_DTMF_RFC2833) { ast_log(LOG_DEBUG, "Stopping DTMF using RFC2833\n"); tmp[0] = 'D'; tmp[1] = '/'; tmp[2] = digit; tmp[3] = '\0'; transmit_notify_request(sub, tmp); ast_rtp_senddigit_end(sub->rtp, digit); } else { ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode); } ast_mutex_unlock(&sub->lock); return res; }
static int mgcp_set_rtp_peer | ( | struct ast_channel * | chan, |
struct ast_rtp * | rtp, | ||
struct ast_rtp * | vrtp, | ||
struct ast_rtp * | trtp, | ||
int | codecs, | ||
int | nat_active | ||
) | [static] |
Definition at line 3962 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_channel::tech_pvt, and transmit_modify_with_sdp().
{ /* XXX Is there such thing as video support with MGCP? XXX */ struct mgcp_subchannel *sub; sub = chan->tech_pvt; if (sub && !sub->alreadygone) { transmit_modify_with_sdp(sub, rtp, codecs); return 0; } return -1; }
static void* mgcp_ss | ( | void * | data | ) | [static] |
Definition at line 2640 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, ast_channel::data, mgcp_endpoint::dnd, mgcp_endpoint::dtmf_buf, mgcp_endpoint::dtmfmode, exten, ast_channel::exten, firstdigittimeout, gendigittimeout, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hidecallerid, ast_channel::language, mgcp_endpoint::lastcallerid, len(), LOG_WARNING, matchdigittimeout, MGCP_DTMF_HYBRID, MGCP_DTMF_INBAND, ast_channel::name, mgcp_subchannel::next, mgcp_subchannel::owner, mgcp_subchannel::parent, ast_channel::rings, start_rtp(), ast_channel::tech_pvt, and transmit_notify_request().
Referenced by handle_hd_hf().
{ struct ast_channel *chan = data; struct mgcp_subchannel *sub = chan->tech_pvt; struct mgcp_endpoint *p = sub->parent; /* char exten[AST_MAX_EXTENSION] = ""; */ int len = 0; int timeout = firstdigittimeout; int res= 0; int getforward = 0; int loop_pause = 100; len = strlen(p->dtmf_buf); while(len < AST_MAX_EXTENSION-1) { res = 1; /* Assume that we will get a digit */ while (strlen(p->dtmf_buf) == len){ ast_safe_sleep(chan, loop_pause); timeout -= loop_pause; if (timeout <= 0){ res = 0; break; } res = 1; } timeout = 0; len = strlen(p->dtmf_buf); if (!ast_ignore_pattern(chan->context, p->dtmf_buf)) { /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ ast_indicate(chan, -1); } else { /* XXX Redundant? We should already be playing dialtone */ /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ transmit_notify_request(sub, "L/dl"); } if (ast_exists_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { if (!res || !ast_matchmore_extension(chan, chan->context, p->dtmf_buf, 1, p->cid_num)) { if (getforward) { /* Record this as the forwarding extension */ ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward)); ast_verb(3, "Setting call forward to '%s' on channel %s\n", p->call_forward, chan->name); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); if (res) break; usleep(500000); /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ ast_indicate(chan, -1); sleep(1); memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/ transmit_notify_request(sub, "L/dl"); len = 0; getforward = 0; } else { /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ ast_indicate(chan, -1); ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten)); memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); ast_set_callerid(chan, p->hidecallerid ? "" : p->cid_num, p->hidecallerid ? "" : p->cid_name, chan->cid.cid_ani ? NULL : p->cid_num); ast_setstate(chan, AST_STATE_RING); /*dahdi_enable_ec(p);*/ if (p->dtmfmode & MGCP_DTMF_HYBRID) { p->dtmfmode |= MGCP_DTMF_INBAND; ast_indicate(chan, -1); } res = ast_pbx_run(chan); if (res) { ast_log(LOG_WARNING, "PBX exited non-zero\n"); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ /*transmit_notify_request(p, "nbz", 1);*/ transmit_notify_request(sub, "G/cg"); } return NULL; } } else { /* It's a match, but they just typed a digit, and there is an ambiguous match, so just set the timeout to matchdigittimeout and wait some more */ timeout = matchdigittimeout; } } else if (res == 0) { ast_debug(1, "not enough digits (and no ambiguous match)...\n"); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ transmit_notify_request(sub, "G/cg"); /*dahdi_wait_event(p->subs[index].zfd);*/ ast_hangup(chan); memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); return NULL; } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) { ast_verb(3, "Disabling call waiting on %s\n", chan->name); /* Disable call waiting if enabled */ p->callwaiting = 0; /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); len = 0; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); timeout = firstdigittimeout; } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) { /* Scan all channels and see if any there * ringing channqels with that have call groups * that equal this channels pickup group */ if (ast_pickup_call(chan)) { ast_log(LOG_WARNING, "No call pickup possible...\n"); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/ transmit_notify_request(sub, "G/cg"); } memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); ast_hangup(chan); return NULL; } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) { ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); /* Disable Caller*ID if enabled */ p->hidecallerid = 1; ast_set_callerid(chan, "", "", NULL); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); len = 0; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); timeout = firstdigittimeout; } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) { res = 0; if (!ast_strlen_zero(p->lastcallerid)) { res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language); } if (!res) /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); break; } else if (!strcmp(p->dtmf_buf, "*78")) { /* Do not disturb */ ast_verb(3, "Enabled DND on channel %s\n", chan->name); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); p->dnd = 1; getforward = 0; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); len = 0; } else if (!strcmp(p->dtmf_buf, "*79")) { /* Do not disturb */ ast_verb(3, "Disabled DND on channel %s\n", chan->name); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); p->dnd = 0; getforward = 0; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); len = 0; } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) { /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); getforward = 1; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); len = 0; } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) { ast_verb(3, "Cancelling call forwarding on channel %s\n", chan->name); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); memset(p->call_forward, 0, sizeof(p->call_forward)); getforward = 0; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); len = 0; } else if (!strcmp(p->dtmf_buf, ast_parking_ext()) && sub->next->owner && ast_bridged_channel(sub->next->owner)) { /* This is a three way call, the main call being a real channel, and we're parking the first call. */ ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL); ast_verb(3, "Parking call to '%s'\n", chan->name); break; } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) { ast_verb(3, "Blacklisting number %s\n", p->lastcallerid); res = ast_db_put("blacklist", p->lastcallerid, "1"); if (!res) { /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); len = 0; } } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) { ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); /* Enable Caller*ID if enabled */ p->hidecallerid = 0; ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/ transmit_notify_request(sub, "L/sl"); len = 0; memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); timeout = firstdigittimeout; } else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) { 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); break; } if (!timeout) timeout = gendigittimeout; if (len && !ast_ignore_pattern(chan->context, p->dtmf_buf)) /*tone_zone_play_tone(p->subs[index].zfd, -1);*/ ast_indicate(chan, -1); } #if 0 for (;;) { res = ast_waitfordigit(chan, to); if (!res) { ast_debug(1, "Timeout...\n"); break; } if (res < 0) { ast_debug(1, "Got hangup...\n"); ast_hangup(chan); break; } exten[pos++] = res; if (!ast_ignore_pattern(chan->context, exten)) ast_indicate(chan, -1); if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) { if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) to = 3000; else to = 8000; } else break; } if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) { ast_copy_string(chan->exten, exten, sizeof(chan->exten)1); if (!p->rtp) { start_rtp(p); } ast_setstate(chan, AST_STATE_RING); chan->rings = 1; if (ast_pbx_run(chan)) { ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name); } else { memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); return NULL; } } #endif ast_hangup(chan); memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); return NULL; }
static int mgcp_write | ( | struct ast_channel * | ast, |
struct ast_frame * | frame | ||
) | [static] |
Definition at line 1243 of file chan_mgcp.c.
References AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, mgcp_subchannel::lock, LOG_WARNING, ast_channel::nativeformats, mgcp_subchannel::parent, ast_channel::readformat, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, mgcp_endpoint::sub, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.
{ struct mgcp_subchannel *sub = ast->tech_pvt; int res = 0; if (frame->frametype != AST_FRAME_VOICE) { if (frame->frametype == AST_FRAME_IMAGE) return 0; else { ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype); return 0; } } else { if (!(frame->subclass & ast->nativeformats)) { ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat); return -1; } } if (sub) { ast_mutex_lock(&sub->lock); if ((sub->parent->sub == sub) || !sub->parent->singlepath) { if (sub->rtp) { res = ast_rtp_write(sub->rtp, frame); } } ast_mutex_unlock(&sub->lock); } return res; }
static int mgcpsock_read | ( | int * | id, |
int | fd, | ||
short | events, | ||
void * | ignore | ||
) | [static] |
Definition at line 3297 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().
{ struct mgcp_request req; struct sockaddr_in sin; struct mgcp_subchannel *sub; int res; socklen_t len; int result; int ident; len = sizeof(sin); memset(&req, 0, sizeof(req)); res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len); if (res < 0) { if (errno != ECONNREFUSED) ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); return 1; } req.data[res] = '\0'; req.len = res; if (mgcpdebug) { ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); } parse(&req); if (req.headers < 1) { /* Must have at least one header */ return 1; } if (ast_strlen_zero(req.identifier)) { ast_log(LOG_NOTICE, "Message from %s missing identifier\n", ast_inet_ntoa(sin.sin_addr)); return 1; } if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) { /* Try to find who this message is for, if it's important */ sub = find_subchannel_and_lock(NULL, ident, &sin); if (sub) { struct mgcp_gateway *gw = sub->parent->parent; struct mgcp_message *cur, *prev; ast_mutex_unlock(&sub->lock); ast_mutex_lock(&gw->msgs_lock); for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) { if (cur->seqno == ident) { ast_debug(1, "Got response back on transaction %d\n", ident); if (prev) prev->next = cur->next; else gw->msgs = cur->next; break; } } /* stop retrans timer if the queue is empty */ if (!gw->msgs) { AST_SCHED_DEL(sched, gw->retransid); } ast_mutex_unlock(&gw->msgs_lock); if (cur) { handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req); ast_free(cur); return 1; } ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", gw->name, ident); } } else { if (ast_strlen_zero(req.endpoint) || ast_strlen_zero(req.version) || ast_strlen_zero(req.verb)) { ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n"); return 1; } /* Process request, with iflock held */ sub = find_subchannel_and_lock(req.endpoint, 0, &sin); if (sub) { /* look first to find a matching response in the queue */ if (!find_and_retrans(sub, &req)) /* pass the request off to the currently mastering subchannel */ handle_request(sub, &req, &sin); ast_mutex_unlock(&sub->lock); } } return 1; }
static void mwi_event_cb | ( | const struct ast_event * | event, |
void * | userdata | ||
) | [static] |
Definition at line 454 of file chan_mgcp.c.
Referenced by build_gateway().
{ /* This module does not handle MWI in an event-based manner. However, it * subscribes to MWI for each mailbox that is configured so that the core * knows that we care about it. Then, chan_mgcp will get the MWI from the * event cache instead of checking the mailbox directly. */ }
static void parse | ( | struct mgcp_request * | req | ) | [static] |
Definition at line 1740 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_meetme_info(), add_agent(), app_exec(), aqm_exec(), ast_parse_allow_disallow(), astman_get_variables(), conf_exec(), conf_run(), confbridge_exec(), config_function_read(), cut_internal(), dial_exec_full(), dictate_exec(), directory_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enum_query_read(), enum_result_read(), execif_exec(), find_conf(), function_agent(), get_in_brackets(), handle_statechange(), iconv_read(), isAnsweringMachine(), isexten_function_read(), log_exec(), login_exec(), mgcpsock_read(), misdn_check_l2l1(), misdn_facility_exec(), misdn_set_opt_exec(), mixmonitor_exec(), 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_agents(), 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().
{ /* Divide fields by NULL's */ char *c; int f = 0; c = req->data; /* First header starts immediately */ req->header[f] = c; while(*c) { if (*c == '\n') { /* We've got a new header */ *c = 0; #if 0 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f])); #endif if (ast_strlen_zero(req->header[f])) { /* Line by itself means we're now in content */ c++; break; } if (f >= MGCP_MAX_HEADERS - 1) { ast_log(LOG_WARNING, "Too many MGCP headers...\n"); } else f++; req->header[f] = c + 1; } else if (*c == '\r') { /* Ignore but eliminate \r's */ *c = 0; } c++; } /* Check for last header */ if (!ast_strlen_zero(req->header[f])) f++; req->headers = f; /* Now we process any mime content */ f = 0; req->line[f] = c; while(*c) { if (*c == '\n') { /* We've got a new line */ *c = 0; #if 0 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f])); #endif if (f >= MGCP_MAX_LINES - 1) { ast_log(LOG_WARNING, "Too many SDP lines...\n"); } else f++; req->line[f] = c + 1; } else if (*c == '\r') { /* Ignore and eliminate \r's */ *c = 0; } c++; } /* Check for last line */ if (!ast_strlen_zero(req->line[f])) f++; req->lines = f; /* Parse up the initial header */ c = req->header[0]; while(*c && *c < 33) c++; /* First the verb */ req->verb = c; while(*c && (*c > 32)) c++; if (*c) { *c = '\0'; c++; while(*c && (*c < 33)) c++; req->identifier = c; while(*c && (*c > 32)) c++; if (*c) { *c = '\0'; c++; while(*c && (*c < 33)) c++; req->endpoint = c; while(*c && (*c > 32)) c++; if (*c) { *c = '\0'; c++; while(*c && (*c < 33)) c++; req->version = c; while(*c && (*c > 32)) c++; while(*c && (*c < 33)) c++; while(*c && (*c > 32)) c++; *c = '\0'; } } } if (mgcpdebug) { ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n", req->verb, req->identifier, req->endpoint, req->version); ast_verbose("%d headers, %d lines\n", req->headers, req->lines); } if (*c) ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c); }
static int process_sdp | ( | struct mgcp_subchannel * | sub, |
struct mgcp_request * | req | ||
) | [static] |
Definition at line 1841 of file chan_mgcp.c.
References ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_rtp_get_current_formats(), ast_rtp_pt_clear(), ast_rtp_set_m_type(), ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_strdupa, ast_strlen_zero(), ast_verbose(), 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_response().
{ char *m; char *c; char *a; char host[258]; int len; int portno; int peercapability, peerNonCodecCapability; struct sockaddr_in sin; char *codecs; struct ast_hostent ahp; struct hostent *hp; int codec, codec_count=0; int iterator; struct mgcp_endpoint *p = sub->parent; /* Get codec and RTP info from SDP */ m = get_sdp(req, "m"); c = get_sdp(req, "c"); if (ast_strlen_zero(m) || ast_strlen_zero(c)) { ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); return -1; } if (sscanf(c, "IN IP4 %256s", host) != 1) { ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); return -1; } /* XXX This could block for a long time, and block the main thread! XXX */ hp = ast_gethostbyname(host, &ahp); if (!hp) { ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); return -1; } if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) { ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); return -1; } sin.sin_family = AF_INET; memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); sin.sin_port = htons(portno); ast_rtp_set_peer(sub->rtp, &sin); #if 0 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); #endif /* Scan through the RTP payload types specified in a "m=" line: */ ast_rtp_pt_clear(sub->rtp); codecs = ast_strdupa(m + len); while (!ast_strlen_zero(codecs)) { if (sscanf(codecs, "%30d%n", &codec, &len) != 1) { if (codec_count) break; ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs); return -1; } ast_rtp_set_m_type(sub->rtp, codec); codec_count++; codecs += len; } /* Next, scan through each "a=rtpmap:" line, noting each */ /* specified RTP payload type (with corresponding MIME subtype): */ sdpLineNum_iterator_init(&iterator); while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */ if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2) continue; /* Note: should really look at the 'freq' and '#chans' params too */ ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0); } /* Now gather all of the codecs that were asked for: */ ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability); p->capability = capability & peercapability; if (mgcpdebug) { ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n", capability, peercapability, p->capability); ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n", nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability); } if (!p->capability) { ast_log(LOG_WARNING, "No compatible codecs!\n"); return -1; } return 0; }
static void prune_gateways | ( | void | ) | [static] |
Definition at line 4036 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().
{ struct mgcp_gateway *g, *z, *r; struct mgcp_endpoint *e, *p, *t; ast_mutex_lock(&gatelock); /* prune gateways */ for (z = NULL, g = gateways; g;) { /* prune endpoints */ for (p = NULL, e = g->endpoints; e; ) { if (e->delme || g->delme) { t = e; e = e->next; if (!p) g->endpoints = e; else p->next = e; destroy_endpoint(t); } else { p = e; e = e->next; } } if (g->delme) { r = g; g = g->next; if (!z) gateways = g; else z->next = g; destroy_gateway(r); } else { z = g; g = g->next; } } ast_mutex_unlock(&gatelock); }
static int reload | ( | void | ) | [static] |
Definition at line 4324 of file chan_mgcp.c.
References mgcp_reload().
{ mgcp_reload(NULL, 0, NULL); return 0; }
static int reload_config | ( | int | reload | ) | [static] |
Definition at line 4079 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.
Referenced by do_monitor(), and load_module().
{ struct ast_config *cfg; struct ast_variable *v; struct mgcp_gateway *g; struct mgcp_endpoint *e; char *cat; struct ast_hostent ahp; struct hostent *hp; int format; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; if (gethostname(ourhost, sizeof(ourhost)-1)) { ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n"); return 0; } cfg = ast_config_load(config, config_flags); /* We *must* have a config file otherwise stop immediately */ if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config); return 0; } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { return 0; } else if (cfg == CONFIG_STATUS_FILEINVALID) { ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); return 0; } memset(&bindaddr, 0, sizeof(bindaddr)); dtmfmode = 0; /* Copy the default jb config over global_jbconf */ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); v = ast_variable_browse(cfg, "general"); while (v) { /* handle jb conf */ if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) { v = v->next; continue; } /* Create the interface list */ if (!strcasecmp(v->name, "bindaddr")) { if (!(hp = ast_gethostbyname(v->value, &ahp))) { ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); } else { memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); } } else if (!strcasecmp(v->name, "allow")) { format = ast_getformatbyname(v->value); if (format < 1) ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value); else capability |= format; } else if (!strcasecmp(v->name, "disallow")) { format = ast_getformatbyname(v->value); if (format < 1) ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value); else capability &= ~format; } else if (!strcasecmp(v->name, "tos")) { if (ast_str2tos(v->value, &qos.tos)) ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno); } else if (!strcasecmp(v->name, "tos_audio")) { if (ast_str2tos(v->value, &qos.tos_audio)) ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); } else if (!strcasecmp(v->name, "cos")) { if (ast_str2cos(v->value, &qos.cos)) ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno); } else if (!strcasecmp(v->name, "cos_audio")) { if (ast_str2cos(v->value, &qos.cos_audio)) ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); } else if (!strcasecmp(v->name, "port")) { if (sscanf(v->value, "%5d", &ourport) == 1) { bindaddr.sin_port = htons(ourport); } else { ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); } } v = v->next; } /* mark existing entries for deletion */ ast_mutex_lock(&gatelock); g = gateways; while (g) { g->delme = 1; e = g->endpoints; while (e) { e->delme = 1; e = e->next; } g = g->next; } ast_mutex_unlock(&gatelock); cat = ast_category_browse(cfg, NULL); while(cat) { if (strcasecmp(cat, "general")) { ast_mutex_lock(&gatelock); g = build_gateway(cat, ast_variable_browse(cfg, cat)); if (g) { ast_verb(3, "Added gateway '%s'\n", g->name); g->next = gateways; gateways = g; } ast_mutex_unlock(&gatelock); /* FS: process queue and IO */ if (monitor_thread == pthread_self()) { if (sched) ast_sched_runq(sched); if (io) ast_io_wait(io, 10); } } cat = ast_category_browse(cfg, cat); } /* prune deleted entries etc. */ prune_gateways(); if (ntohl(bindaddr.sin_addr.s_addr)) { memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip)); } else { hp = ast_gethostbyname(ourhost, &ahp); if (!hp) { ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n"); ast_config_destroy(cfg); return 0; } memcpy(&__ourip, hp->h_addr, sizeof(__ourip)); } if (!ntohs(bindaddr.sin_port)) bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT); bindaddr.sin_family = AF_INET; ast_mutex_lock(&netlock); if (mgcpsock > -1) close(mgcpsock); if (mgcpsock_read_id != NULL) ast_io_remove(io, mgcpsock_read_id); mgcpsock_read_id = NULL; mgcpsock = socket(AF_INET, SOCK_DGRAM, 0); if (mgcpsock < 0) { ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno)); } else { if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), strerror(errno)); close(mgcpsock); mgcpsock = -1; } else { ast_verb(2, "MGCP Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); ast_netsock_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP"); } } ast_mutex_unlock(&netlock); ast_config_destroy(cfg); /* send audit only to the new endpoints */ g = gateways; while (g) { e = g->endpoints; while (e && e->needaudit) { e->needaudit = 0; transmit_audit_endpoint(e); ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name); e = e->next; } g = g->next; } return 0; }
static int reqprep | ( | struct mgcp_request * | req, |
struct mgcp_endpoint * | p, | ||
char * | verb | ||
) | [static] |
Definition at line 2018 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_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
static int resend_response | ( | struct mgcp_subchannel * | sub, |
struct mgcp_response * | resp | ||
) | [static] |
Definition at line 528 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().
{ struct mgcp_endpoint *p = sub->parent; int res; if (mgcpdebug) { 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)); } res = __mgcp_xmit(p->parent, resp->buf, resp->len); if (res > 0) res = 0; return res; }
static int respprep | ( | struct mgcp_request * | resp, |
struct mgcp_endpoint * | p, | ||
char * | msg, | ||
struct mgcp_request * | req, | ||
char * | msgrest | ||
) | [static] |
Definition at line 2011 of file chan_mgcp.c.
References init_resp().
Referenced by transmit_response().
static int restart_monitor | ( | void | ) | [static] |
Definition at line 3472 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.
Referenced by load_module(), mgcp_reload(), and mgcp_request().
{ /* If we're supposed to be stopped -- stay stopped */ if (monitor_thread == AST_PTHREADT_STOP) return 0; if (ast_mutex_lock(&monlock)) { ast_log(LOG_WARNING, "Unable to lock monitor\n"); return -1; } if (monitor_thread == pthread_self()) { ast_mutex_unlock(&monlock); ast_log(LOG_WARNING, "Cannot kill myself\n"); return -1; } if (monitor_thread != AST_PTHREADT_NULL) { /* Wake up the thread */ pthread_kill(monitor_thread, SIGURG); } else { /* Start a new monitor */ if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { ast_mutex_unlock(&monlock); ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); return -1; } } ast_mutex_unlock(&monlock); return 0; }
static int retrans_pkt | ( | const void * | data | ) | [static] |
Definition at line 631 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 mgcp_postrequest().
{ struct mgcp_gateway *gw = (struct mgcp_gateway *)data; struct mgcp_message *cur, *exq = NULL, *w, *prev; int res = 0; /* find out expired msgs */ ast_mutex_lock(&gw->msgs_lock); prev = NULL, cur = gw->msgs; while (cur) { if (cur->retrans < MAX_RETRANS) { cur->retrans++; if (mgcpdebug) { ast_verbose("Retransmitting #%d transaction %u on [%s]\n", cur->retrans, cur->seqno, gw->name); } __mgcp_xmit(gw, cur->buf, cur->len); prev = cur; cur = cur->next; } else { if (prev) prev->next = cur->next; else gw->msgs = cur->next; ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", cur->seqno, gw->name); w = cur; cur = cur->next; if (exq) { w->next = exq; } else { w->next = NULL; } exq = w; } } if (!gw->msgs) { gw->retransid = -1; res = 0; } else { res = 1; } ast_mutex_unlock(&gw->msgs_lock); while (exq) { cur = exq; /* time-out transaction */ handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); exq = exq->next; ast_free(cur); } return res; }
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 758 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_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
{ int res = 0; struct mgcp_request **queue, *q, *r, *t; ast_mutex_t *l; ast_debug(1, "Slow sequence is %d\n", p->slowsequence); if (p->slowsequence) { queue = &p->cmd_queue; l = &p->cmd_queue_lock; ast_mutex_lock(l); } else { switch (req->cmd) { case MGCP_CMD_DLCX: queue = &sub->cx_queue; l = &sub->cx_queue_lock; ast_mutex_lock(l); q = sub->cx_queue; /* delete pending cx cmds */ while (q) { r = q->next; ast_free(q); q = r; } *queue = NULL; break; case MGCP_CMD_CRCX: case MGCP_CMD_MDCX: queue = &sub->cx_queue; l = &sub->cx_queue_lock; ast_mutex_lock(l); break; case MGCP_CMD_RQNT: queue = &p->rqnt_queue; l = &p->rqnt_queue_lock; ast_mutex_lock(l); break; default: queue = &p->cmd_queue; l = &p->cmd_queue_lock; ast_mutex_lock(l); break; } } r = ast_malloc(sizeof(*r)); if (!r) { ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n"); ast_mutex_unlock(l); return -1; } memcpy(r, req, sizeof(*r)); if (!(*queue)) { if (mgcpdebug) { ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); } res = mgcp_postrequest(p, sub, req->data, req->len, seqno); } else { if (mgcpdebug) { ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); } } /* XXX find tail. We could also keep tail in the data struct for faster access */ for (t = *queue; t && t->next; t = t->next); r->next = NULL; if (t) t->next = r; else *queue = r; ast_mutex_unlock(l); return res; }
static int send_response | ( | struct mgcp_subchannel * | sub, |
struct mgcp_request * | req | ||
) | [static] |
Definition at line 541 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().
{ struct mgcp_endpoint *p = sub->parent; int res; if (mgcpdebug) { 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)); } res = __mgcp_xmit(p->parent, req->data, req->len); if (res > 0) res = 0; return res; }
static void start_rtp | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2613 of file chan_mgcp.c.
References ast_channel_set_fd(), ast_mutex_lock(), ast_mutex_unlock(), ast_random(), ast_rtp_destroy(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_callback(), ast_rtp_set_data(), ast_rtp_setnat(), ast_rtp_setqos(), bindaddr, mgcp_subchannel::callid, 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_response(), mgcp_answer(), mgcp_call(), and mgcp_ss().
{ ast_mutex_lock(&sub->lock); /* check again to be on the safe side */ if (sub->rtp) { ast_rtp_destroy(sub->rtp); sub->rtp = NULL; } /* Allocate the RTP now */ sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); if (sub->rtp && sub->owner) ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp)); if (sub->rtp) { ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP"); ast_rtp_setnat(sub->rtp, sub->nat); } #if 0 ast_rtp_set_callback(p->rtp, rtpready); ast_rtp_set_data(p->rtp, p); #endif /* Make a call*ID */ snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident); /* Transmit the connection create */ transmit_connect_with_sdp(sub, NULL); ast_mutex_unlock(&sub->lock); }
static int transmit_audit_endpoint | ( | struct mgcp_endpoint * | p | ) | [static] |
Definition at line 2332 of file chan_mgcp.c.
References add_header(), mgcp_request::cmd, MGCP_CMD_AUEP, oseq, reqprep(), send_request(), and mgcp_request::trid.
Referenced by handle_mgcp_audit_endpoint(), handle_request(), and reload_config().
{ struct mgcp_request resp; reqprep(&resp, p, "AUEP"); /* removed unknown param VS */ /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/ add_header(&resp, "F", "A"); /* fill in new fields */ resp.cmd = MGCP_CMD_AUEP; resp.trid = oseq; return send_request(p, NULL, &resp, oseq); /* SC */ }
static int transmit_connect_with_sdp | ( | struct mgcp_subchannel * | sub, |
struct ast_rtp * | rtp | ||
) | [static] |
Definition at line 2179 of file chan_mgcp.c.
References add_header(), add_sdp(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_lookup_mime_subtype(), 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, oseq, mgcp_endpoint::parent, mgcp_subchannel::parent, reqprep(), send_request(), mgcp_request::trid, and mgcp_subchannel::txident.
Referenced by start_rtp().
{ struct mgcp_request resp; char local[256]; char tmp[80]; int x; struct mgcp_endpoint *p = sub->parent; ast_copy_string(local, "p:20", sizeof(local)); for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { if (p->capability & x) { snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0)); strncat(local, tmp, sizeof(local) - strlen(local) - 1); } } if (mgcpdebug) { ast_verb(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); } reqprep(&resp, p, "CRCX"); add_header(&resp, "C", sub->callid); add_header(&resp, "L", local); add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); /* X header should not be sent. kept for compatibility */ add_header(&resp, "X", sub->txident); /*add_header(&resp, "S", "");*/ add_sdp(&resp, sub, rtp); /* fill in new fields */ resp.cmd = MGCP_CMD_CRCX; resp.trid = oseq; return send_request(p, sub, &resp, oseq); /* SC */ }
static int transmit_connection_del | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2345 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, oseq, 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().
{ struct mgcp_endpoint *p = sub->parent; struct mgcp_request resp; if (mgcpdebug) { ast_verb(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); } reqprep(&resp, p, "DLCX"); /* check if call id is avail */ if (sub->callid[0]) add_header(&resp, "C", sub->callid); /* X header should not be sent. kept for compatibility */ add_header(&resp, "X", sub->txident); /* check if cxident is avail */ if (sub->cxident[0]) add_header(&resp, "I", sub->cxident); /* fill in new fields */ resp.cmd = MGCP_CMD_DLCX; resp.trid = oseq; return send_request(p, sub, &resp, oseq); /* SC */ }
static int transmit_connection_del_w_params | ( | struct mgcp_endpoint * | p, |
char * | callid, | ||
char * | cxident | ||
) | [static] |
Definition at line 2369 of file chan_mgcp.c.
References add_header(), ast_verb, mgcp_request::cmd, MGCP_CMD_DLCX, mgcp_gateway::name, mgcp_endpoint::name, oseq, mgcp_endpoint::parent, reqprep(), send_request(), mgcp_endpoint::sub, and mgcp_request::trid.
Referenced by handle_response().
{ struct mgcp_request resp; if (mgcpdebug) { ast_verb(3, "Delete connection %s %s@%s on callid: %s\n", cxident ? cxident : "", p->name, p->parent->name, callid ? callid : ""); } reqprep(&resp, p, "DLCX"); /* check if call id is avail */ if (callid && *callid) add_header(&resp, "C", callid); /* check if cxident is avail */ if (cxident && *cxident) add_header(&resp, "I", cxident); /* fill in new fields */ resp.cmd = MGCP_CMD_DLCX; resp.trid = oseq; return send_request(p, p->sub, &resp, oseq); }
static int transmit_modify_request | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 2287 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, oseq, 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().
{ struct mgcp_request resp; struct mgcp_endpoint *p = sub->parent; if (ast_strlen_zero(sub->cxident)) { /* We don't have a CXident yet, store the destination and wait a bit */ return 0; } if (mgcpdebug) { ast_verb(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n", p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid); } reqprep(&resp, p, "MDCX"); add_header(&resp, "C", sub->callid); add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); /* X header should not be sent. kept for compatibility */ add_header(&resp, "X", sub->txident); add_header(&resp, "I", sub->cxident); switch (sub->parent->hookstate) { case MGCP_ONHOOK: add_header(&resp, "R", "L/hd(N)"); break; case MGCP_OFFHOOK: add_header_offhook(sub, &resp); break; } /* fill in new fields */ resp.cmd = MGCP_CMD_MDCX; resp.trid = oseq; return send_request(p, sub, &resp, oseq); /* SC */ }
static int transmit_modify_with_sdp | ( | struct mgcp_subchannel * | sub, |
struct ast_rtp * | rtp, | ||
int | codecs | ||
) | [static] |
Definition at line 2143 of file chan_mgcp.c.
References add_header(), add_sdp(), ast_copy_string(), AST_FORMAT_AUDIO_MASK, ast_rtp_get_peer(), ast_rtp_lookup_mime_subtype(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_endpoint::capability, mgcp_request::cmd, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, MGCP_CMD_MDCX, oseq, 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().
{ struct mgcp_request resp; char local[256]; char tmp[80]; int x; struct mgcp_endpoint *p = sub->parent; if (ast_strlen_zero(sub->cxident) && rtp) { /* We don't have a CXident yet, store the destination and wait a bit */ ast_rtp_get_peer(rtp, &sub->tmpdest); return 0; } ast_copy_string(local, "p:20", sizeof(local)); for (x = 1; x <= AST_FORMAT_AUDIO_MASK; x <<= 1) { if (p->capability & x) { snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0)); strncat(local, tmp, sizeof(local) - strlen(local) - 1); } } reqprep(&resp, p, "MDCX"); add_header(&resp, "C", sub->callid); add_header(&resp, "L", local); add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]); /* X header should not be sent. kept for compatibility */ add_header(&resp, "X", sub->txident); add_header(&resp, "I", sub->cxident); /*add_header(&resp, "S", "");*/ add_sdp(&resp, sub, rtp); /* fill in new fields */ resp.cmd = MGCP_CMD_MDCX; resp.trid = oseq; return send_request(p, sub, &resp, oseq); /* SC */ }
static int transmit_notify_request | ( | struct mgcp_subchannel * | sub, |
char * | tone | ||
) | [static] |
Definition at line 2212 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, oseq, 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().
{ struct mgcp_request resp; struct mgcp_endpoint *p = sub->parent; if (mgcpdebug) { ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); } ast_copy_string(p->curtone, tone, sizeof(p->curtone)); reqprep(&resp, p, "RQNT"); add_header(&resp, "X", p->rqnt_ident); /* SC */ switch (p->hookstate) { case MGCP_ONHOOK: add_header(&resp, "R", "L/hd(N)"); break; case MGCP_OFFHOOK: add_header_offhook(sub, &resp); break; } if (!ast_strlen_zero(tone)) { add_header(&resp, "S", tone); } /* fill in new fields */ resp.cmd = MGCP_CMD_RQNT; resp.trid = oseq; return send_request(p, NULL, &resp, oseq); /* SC */ }
static int transmit_notify_request_with_callerid | ( | struct mgcp_subchannel * | sub, |
char * | tone, | ||
char * | callernum, | ||
char * | callername | ||
) | [static] |
Definition at line 2241 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, oseq, 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().
{ struct mgcp_request resp; char tone2[256]; char *l, *n; struct timeval t = ast_tvnow(); struct ast_tm tm; struct mgcp_endpoint *p = sub->parent; ast_localtime(&t, &tm, NULL); n = callername; l = callernum; if (!n) n = ""; if (!l) l = ""; /* Keep track of last callerid for blacklist and callreturn */ ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid)); snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n); ast_copy_string(p->curtone, tone, sizeof(p->curtone)); reqprep(&resp, p, "RQNT"); add_header(&resp, "X", p->rqnt_ident); /* SC */ switch (p->hookstate) { case MGCP_ONHOOK: add_header(&resp, "R", "L/hd(N)"); break; case MGCP_OFFHOOK: add_header_offhook(sub, &resp); break; } if (!ast_strlen_zero(tone2)) { add_header(&resp, "S", tone2); } if (mgcpdebug) { ast_verb(3, "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n", tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]); } /* fill in new fields */ resp.cmd = MGCP_CMD_RQNT; resp.trid = oseq; return send_request(p, NULL, &resp, oseq); /* SC */ }
static int transmit_response | ( | struct mgcp_subchannel * | sub, |
char * | msg, | ||
struct mgcp_request * | req, | ||
char * | msgrest | ||
) | [static] |
Definition at line 2028 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_request().
{ struct mgcp_request resp; struct mgcp_endpoint *p = sub->parent; struct mgcp_response *mgr; respprep(&resp, p, msg, req, msgrest); mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1); if (mgr) { /* Store MGCP response in case we have to retransmit */ sscanf(req->identifier, "%30d", &mgr->seqno); time(&mgr->whensent); mgr->len = resp.len; memcpy(mgr->buf, resp.data, resp.len); mgr->buf[resp.len] = '\0'; mgr->next = p->parent->responses; p->parent->responses = mgr; } return send_response(sub, &resp); }
static int unalloc_sub | ( | struct mgcp_subchannel * | sub | ) | [static] |
Definition at line 487 of file chan_mgcp.c.
References mgcp_subchannel::alreadygone, ast_debug, ast_log(), ast_rtp_destroy(), ast_strlen_zero(), mgcp_subchannel::callid, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, dump_cmd_queues(), mgcp_subchannel::id, LOG_WARNING, MGCP_CX_INACTIVE, mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::outgoing, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, mgcp_endpoint::sub, mgcp_subchannel::tmpdest, and transmit_connection_del().
Referenced by attempt_transfer().
{ struct mgcp_endpoint *p = sub->parent; if (p->sub == sub) { ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name); return -1; } ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name); sub->owner = NULL; if (!ast_strlen_zero(sub->cxident)) { transmit_connection_del(sub); } sub->cxident[0] = '\0'; sub->callid[0] = '\0'; sub->cxmode = MGCP_CX_INACTIVE; sub->outgoing = 0; sub->alreadygone = 0; memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); if (sub->rtp) { ast_rtp_destroy(sub->rtp); sub->rtp = NULL; } dump_cmd_queues(NULL, sub); /* SC */ return 0; }
static int unload_module | ( | void | ) | [static] |
Definition at line 4330 of file chan_mgcp.c.
References ast_channel_register(), ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), 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().
{ struct mgcp_endpoint *e; struct mgcp_gateway *g; /* Check to see if we're reloading */ if (ast_mutex_trylock(&mgcp_reload_lock)) { ast_log(LOG_WARNING, "MGCP is currently reloading. Unable to remove module.\n"); return -1; } else { mgcp_reloading = 1; ast_mutex_unlock(&mgcp_reload_lock); } /* First, take us out of the channel loop */ ast_channel_unregister(&mgcp_tech); /* Shut down the monitoring thread */ if (!ast_mutex_lock(&monlock)) { if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { pthread_cancel(monitor_thread); pthread_kill(monitor_thread, SIGURG); pthread_join(monitor_thread, NULL); } monitor_thread = AST_PTHREADT_STOP; ast_mutex_unlock(&monlock); } else { ast_log(LOG_WARNING, "Unable to lock the monitor\n"); /* We always want to leave this in a consistent state */ ast_channel_register(&mgcp_tech); mgcp_reloading = 0; mgcp_reload(NULL, 0, NULL); return -1; } if (!ast_mutex_lock(&gatelock)) { for (g = gateways; g; g = g->next) { g->delme = 1; for (e = g->endpoints; e; e = e->next) e->delme = 1; } prune_gateways(); ast_mutex_unlock(&gatelock); } else { ast_log(LOG_WARNING, "Unable to lock the gateways list.\n"); /* We always want to leave this in a consistent state */ ast_channel_register(&mgcp_tech); /* Allow the monitor to restart */ monitor_thread = AST_PTHREADT_NULL; mgcp_reloading = 0; mgcp_reload(NULL, 0, NULL); return -1; } close(mgcpsock); ast_rtp_proto_unregister(&mgcp_rtp); ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry)); sched_context_destroy(sched); return 0; }
struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Media Gateway Control Protocol (MGCP)" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 4397 of file chan_mgcp.c.
struct in_addr __ourip [static] |
Definition at line 218 of file chan_mgcp.c.
Referenced by build_gateway(), find_subchannel_and_lock(), and reload_config().
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.
Referenced by build_gateway().
int amaflags = 0 [static] |
Definition at line 187 of file chan_mgcp.c.
Referenced by build_gateway().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4397 of file chan_mgcp.c.
struct sockaddr_in bindaddr [static] |
Definition at line 405 of file chan_mgcp.c.
Referenced by reload_config(), and start_rtp().
int callreturn = 0 [static] |
Definition at line 168 of file chan_mgcp.c.
Referenced by build_gateway().
int callwaiting = 0 [static] |
Definition at line 166 of file chan_mgcp.c.
Referenced by build_gateway().
int cancallforward = 0 [static] |
Definition at line 177 of file chan_mgcp.c.
Referenced by build_gateway().
int capability = AST_FORMAT_ULAW [static] |
Definition at line 214 of file chan_mgcp.c.
Referenced by ast_iax2_new(), build_gateway(), build_setup(), iax2_call(), mgcp_new(), mgcp_request(), 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 __oh323_new(), apply_outgoing(), ast_pbx_outgoing_exten(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_peer_defaults(), set_pvt_defaults(), sip_call(), sla_ring_station(), and store_callerid().
char cid_num[AST_MAX_EXTENSION] = "" [static] |
Definition at line 148 of file chan_mgcp.c.
Referenced by __oh323_new(), apply_outgoing(), ast_pbx_outgoing_exten(), build_peer(), build_user(), check_access(), check_peer_ok(), check_user_full(), dahdi_handle_event(), dial_trunk(), misdn_new(), replace_cid(), set_peer_defaults(), set_pvt_defaults(), sla_ring_station(), socket_process(), and store_callerid().
struct ast_cli_entry cli_mgcp[] [static] |
Definition at line 1170 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.
Referenced by build_gateway().
ast_group_t cur_pickupgroup = 0 [static] |
Definition at line 155 of file chan_mgcp.c.
Referenced by build_gateway().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 90 of file chan_mgcp.c.
int directmedia = DIRECTMEDIA [static] |
Definition at line 181 of file chan_mgcp.c.
Referenced by build_gateway().
int dtmfmode = 0 [static] |
Definition at line 151 of file chan_mgcp.c.
Referenced by build_gateway(), and set_local_capabilities().
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic)
Definition at line 194 of file chan_mgcp.c.
Referenced by mgcp_ss().
ast_mutex_t gatelock = AST_MUTEX_INIT_VALUE [static] |
gatelock: mutex for gateway/endpoint lists
Definition at line 401 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.
Referenced by mgcp_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 98 of file chan_mgcp.c.
Referenced by mgcp_new(), and reload_config().
int immediate = 0 [static] |
Definition at line 164 of file chan_mgcp.c.
Referenced by build_gateway().
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(), 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.
Referenced by mgcp_ss().
char* mgcp_cxmodes[] [static] |
}
Definition at line 123 of file chan_mgcp.c.
ast_mutex_t mgcp_reload_lock = AST_MUTEX_INIT_VALUE [static] |
Definition at line 397 of file chan_mgcp.c.
Referenced by do_monitor(), mgcp_reload(), and unload_module().
int mgcp_reloading = 0 [static] |
Definition at line 398 of file chan_mgcp.c.
Referenced by do_monitor().
struct ast_rtp_protocol mgcp_rtp [static] |
{ .type = "MGCP", .get_rtp_info = mgcp_get_rtp_peer, .set_rtp_peer = mgcp_set_rtp_peer, }
Definition at line 3974 of file chan_mgcp.c.
struct ast_channel_tech mgcp_tech [static] |
Definition at line 435 of file chan_mgcp.c.
Referenced by mgcp_new().
int mgcpdebug = 0 [static] |
Definition at line 221 of file chan_mgcp.c.
int mgcpsock = -1 [static] |
Definition at line 403 of file chan_mgcp.c.
int* mgcpsock_read_id = NULL [static] |
Definition at line 3384 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_INIT_VALUE [static] |
Definition at line 206 of file chan_mgcp.c.
Referenced by do_monitor(), restart_monitor(), and unload_module().
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_real(), 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.
Referenced by ast_rtp_setnat(), ast_udptl_setnat(), and build_gateway().
ast_mutex_t netlock = AST_MUTEX_INIT_VALUE [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 do_monitor(), and reload_config().
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.
Referenced by transmit_audit_endpoint(), transmit_connect_with_sdp(), transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_request(), transmit_modify_with_sdp(), transmit_notify_request(), and transmit_notify_request_with_callerid().
char ourhost[MAXHOSTNAMELEN] [static] |
Definition at line 217 of file chan_mgcp.c.
Referenced by ast_find_ourip().
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] |
Referenced by reload_config(), and start_rtp().
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.
Referenced by build_gateway().
int slowsequence = 0 [static] |
Definition at line 170 of file chan_mgcp.c.
Referenced by build_gateway().
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.
Referenced by build_gateway().
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 build_gateway(), iax2_send(), leave_voicemail(), and send_packet().