![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_mgcp.c File Reference
Definition in file chan_mgcp.c.
#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.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/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
Include dependency graph for chan_mgcp.c:

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 | CANREINVITE 1 |
| #define | DEFAULT_EXPIRY 120 |
| #define | DEFAULT_MGCP_CA_PORT 2727 |
| #define | DEFAULT_MGCP_GW_PORT 2427 |
| #define | DEFAULT_RETRANS 1000 |
| #define | INADDR_NONE (in_addr_t)(-1) |
| #define | IPTOS_MINCOST 0x02 |
| #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 int | add_header (struct mgcp_request *req, char *var, char *value) |
| 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) |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Media Gateway Control Protocol (MGCP)",.load=load_module,.unload=unload_module,.reload=reload,) | |
| AST_MUTEX_DEFINE_STATIC (gatelock) | |
| gatelock: mutex for gateway/endpoint lists | |
| AST_MUTEX_DEFINE_STATIC (mgcp_reload_lock) | |
| AST_MUTEX_DEFINE_STATIC (monlock) | |
| AST_MUTEX_DEFINE_STATIC (netlock) | |
| 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 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_audit_endpoint (int fd, int argc, char *argv[]) |
| 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_do_debug (int fd, int argc, char *argv[]) |
| static int | mgcp_do_reload (void) |
| mgcp_do_reload: Reload module | |
| 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_no_debug (int fd, int argc, char *argv[]) |
| 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 int | mgcp_reload (int fd, int argc, char *argv[]) |
| 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, int codecs, int nat_active) |
| static int | mgcp_show_endpoints (int fd, int argc, char *argv[]) |
| 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 | 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 (void) |
| 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) |
| Start the channel monitor thread. | |
| static int | retrans_pkt (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 in_addr | __ourip |
| static char | accountcode [AST_MAX_ACCOUNT_CODE] = "" |
| static int | adsi = 0 |
| static int | amaflags = 0 |
| static const char | audit_endpoint_usage [] |
| static struct sockaddr_in | bindaddr |
| static int | callreturn = 0 |
| static int | callwaiting = 0 |
| static int | cancallforward = 0 |
| static int | canreinvite = CANREINVITE |
| 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 const char | debug_usage [] |
| static struct ast_jb_conf | default_jbconf |
| static int | dtmfmode = 0 |
| static int | firstdigittimeout = 16000 |
| 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 const char | mgcp_reload_usage [] |
| static int | mgcp_reloading = 0 |
| static struct ast_rtp_protocol | mgcp_rtp |
| static const 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 char | musicclass [MAX_MUSICCLASS] = "" |
| static int | nat = 0 |
| static const char | no_debug_usage [] |
| static int | nonCodecCapability = AST_RTP_DTMF |
| static unsigned int | oseq |
| static char | ourhost [MAXHOSTNAMELEN] |
| static int | ourport |
| static struct sched_context * | sched |
| static const char | show_endpoints_usage [] |
| static int | singlepath = 0 |
| static int | slowsequence = 0 |
| static const char | tdesc [] = "Media Gateway Control Protocol (MGCP)" |
| static int | threewaycalling = 0 |
| static int | tos = 0 |
| static int | transfer = 0 |
|
|
Definition at line 93 of file chan_mgcp.c. Referenced by build_gateway(). |
|
|
Definition at line 91 of file chan_mgcp.c. Referenced by reload_config(). |
|
|
From RFC 2705 Definition at line 117 of file chan_mgcp.c. Referenced by reload_config(). |
|
|
From RFC 2705 Definition at line 116 of file chan_mgcp.c. |
|
|
How frequently to retransmit Definition at line 119 of file chan_mgcp.c. Referenced by __sip_reliable_xmit(), mgcp_postrequest(), and retrans_pkt(). |
|
|
Definition at line 96 of file chan_mgcp.c. Referenced by build_gateway(). |
|
|
Definition at line 81 of file chan_mgcp.c. |
|
|
Definition at line 92 of file chan_mgcp.c. |
|
|
Try only 5 times for retransmissions Definition at line 120 of file chan_mgcp.c. Referenced by retrans_pkt(). |
|
|
Definition at line 272 of file chan_mgcp.c. Referenced by build_gateway(), and destroy_endpoint(). |
|
|
Definition at line 126 of file chan_mgcp.c. Referenced by handle_request(). |
|
|
Definition at line 127 of file chan_mgcp.c. |
|
|
Definition at line 129 of file chan_mgcp.c. Referenced by build_gateway(), mgcp_hangup(), and unalloc_sub(). |
|
|
Definition at line 128 of file chan_mgcp.c. Referenced by handle_request(). |
|
|
Definition at line 124 of file chan_mgcp.c. Referenced by handle_request(), mgcp_call(), and mgcp_hangup(). |
|
|
MGCP rtp stream modes { Definition at line 123 of file chan_mgcp.c. |
|
|
Definition at line 125 of file chan_mgcp.c. Referenced by handle_hd_hf(), handle_request(), mgcp_answer(), and mgcp_call(). |
|
|
Definition at line 114 of file chan_mgcp.c. Referenced by build_gateway(), mgcp_hangup(), mgcp_new(), and mgcp_ss(). |
|
|
Definition at line 113 of file chan_mgcp.c. Referenced by build_gateway(), mgcp_hangup(), mgcp_new(), mgcp_rtp_read(), mgcp_ss(), transmit_modify_request(), transmit_notify_request(), and transmit_notify_request_with_callerid(). |
|
|
Definition at line 112 of file chan_mgcp.c. Referenced by build_gateway(), and mgcp_rtp_read(). |
|
|
The private structures of the mgcp channels are linked for ! selecting outgoing channels Definition at line 231 of file chan_mgcp.c. Referenced by add_header(), init_req(), init_resp(), and parse(). |
|
|
Definition at line 232 of file chan_mgcp.c. Referenced by add_line(), and parse(). |
|
|
Also from RFC 2543, should sub headers tho Definition at line 118 of file chan_mgcp.c. |
|
|
Definition at line 306 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(). |
|
|
Definition at line 305 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(). |
|
|
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 283 of file chan_mgcp.c. Referenced by build_gateway(), and mgcp_hangup(). |
|
|
Definition at line 90 of file chan_mgcp.c. |
|
|
in seconds Definition at line 262 of file chan_mgcp.c. Referenced by find_and_retrans(). |
|
|
Definition at line 275 of file chan_mgcp.c. |
|
|
Definition at line 274 of file chan_mgcp.c. |
|
|
Definition at line 309 of file chan_mgcp.c. Referenced by build_device(), build_gateway(), do_monitor(), mgcp_call(), and skinny_hangup(). |
|
|
Definition at line 308 of file chan_mgcp.c. Referenced by build_device(), and build_gateway(). |
|
|
Definition at line 140 of file chan_mgcp.c. 00140 { 00141 MGCP_CMD_EPCF, 00142 MGCP_CMD_CRCX, 00143 MGCP_CMD_MDCX, 00144 MGCP_CMD_DLCX, 00145 MGCP_CMD_RQNT, 00146 MGCP_CMD_NTFY, 00147 MGCP_CMD_AUEP, 00148 MGCP_CMD_AUCX, 00149 MGCP_CMD_RSIP 00150 };
|
|
||||||||||||||||
|
Definition at line 1543 of file chan_mgcp.c. References mgcp_request::header, mgcp_request::headers, and len. Referenced by build_route(), copy_all_header(), copy_via_headers(), func_header_read(), get_header(), and handle_response_register(). 01544 { 01545 int x; 01546 int len = strlen(name); 01547 char *r; 01548 for (x=*start;x<req->headers;x++) { 01549 if (!strncasecmp(req->header[x], name, len) && 01550 (req->header[x][len] == ':')) { 01551 r = req->header[x] + len + 1; 01552 while(*r && (*r < 33)) 01553 r++; 01554 *start = x+1; 01555 return r; 01556 } 01557 } 01558 /* Don't return NULL, so get_header is always a valid pointer */ 01559 return ""; 01560 }
|
|
||||||||||||||||
|
Definition at line 487 of file chan_mgcp.c. References mgcp_gateway::addr, ast_log(), mgcp_gateway::defaddr, and LOG_WARNING. Referenced by mgcp_postrequest(), resend_response(), retrans_pkt(), and send_response(). 00488 { 00489 int res; 00490 if (gw->addr.sin_addr.s_addr) 00491 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in)); 00492 else 00493 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in)); 00494 if (res != len) { 00495 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno)); 00496 } 00497 return res; 00498 }
|
|
||||||||||||||||
|
||||||||||||
|
Definition at line 1916 of file chan_mgcp.c. References ast_log(), mgcp_request::data, mgcp_request::len, mgcp_request::line, mgcp_request::lines, LOG_WARNING, and MGCP_MAX_LINES. Referenced by add_digit(), add_t38_sdp(), add_text(), add_vidupdate(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), and transmit_state_notify(). 01917 { 01918 if (req->len >= sizeof(req->data) - 4) { 01919 ast_log(LOG_WARNING, "Out of space, can't add anymore\n"); 01920 return -1; 01921 } 01922 if (!req->lines) { 01923 /* Add extra empty return */ 01924 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n"); 01925 req->len += strlen(req->data + req->len); 01926 } 01927 req->line[req->lines] = req->data + req->len; 01928 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line); 01929 req->len += strlen(req->line[req->lines]); 01930 if (req->lines < MGCP_MAX_LINES) 01931 req->lines++; 01932 else { 01933 ast_log(LOG_WARNING, "Out of line space\n"); 01934 return -1; 01935 } 01936 return 0; 01937 }
|
|
||||||||||||||||
|
Definition at line 2018 of file chan_mgcp.c. References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), ast_verbose(), mgcp_endpoint::capability, len, LOG_WARNING, mgcpdebug, mgcp_gateway::ourip, mgcp_endpoint::parent, mgcp_subchannel::parent, mgcp_subchannel::rtp, s, mgcp_endpoint::sub, and mgcp_subchannel::tmpdest. Referenced by transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_attachment(), and transmit_response_with_sdp(). 02019 { 02020 int len; 02021 int codec; 02022 char costr[80]; 02023 struct sockaddr_in sin; 02024 char v[256]; 02025 char s[256]; 02026 char o[256]; 02027 char c[256]; 02028 char t[256]; 02029 char m[256] = ""; 02030 char a[1024] = ""; 02031 int x; 02032 struct sockaddr_in dest; 02033 struct mgcp_endpoint *p = sub->parent; 02034 /* XXX We break with the "recommendation" and send our IP, in order that our 02035 peer doesn't have to ast_gethostbyname() us XXX */ 02036 len = 0; 02037 if (!sub->rtp) { 02038 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 02039 return -1; 02040 } 02041 ast_rtp_get_us(sub->rtp, &sin); 02042 if (rtp) { 02043 ast_rtp_get_peer(rtp, &dest); 02044 } else { 02045 if (sub->tmpdest.sin_addr.s_addr) { 02046 dest.sin_addr = sub->tmpdest.sin_addr; 02047 dest.sin_port = sub->tmpdest.sin_port; 02048 /* Reset temporary destination */ 02049 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest)); 02050 } else { 02051 dest.sin_addr = p->parent->ourip; 02052 dest.sin_port = sin.sin_port; 02053 } 02054 } 02055 if (mgcpdebug) { 02056 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 02057 } 02058 snprintf(v, sizeof(v), "v=0\r\n"); 02059 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(dest.sin_addr)); 02060 snprintf(s, sizeof(s), "s=session\r\n"); 02061 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 02062 snprintf(t, sizeof(t), "t=0 0\r\n"); 02063 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 02064 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) { 02065 if (p->capability & x) { 02066 if (mgcpdebug) { 02067 ast_verbose("Answering with capability %d\n", x); 02068 } 02069 codec = ast_rtp_lookup_code(sub->rtp, 1, x); 02070 if (codec > -1) { 02071 snprintf(costr, sizeof(costr), " %d", codec); 02072 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02073 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0)); 02074 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02075 } 02076 } 02077 } 02078 for (x = 1; x <= AST_RTP_MAX; x <<= 1) { 02079 if (p->nonCodecCapability & x) { 02080 if (mgcpdebug) { 02081 ast_verbose("Answering with non-codec capability %d\n", x); 02082 } 02083 codec = ast_rtp_lookup_code(sub->rtp, 0, x); 02084 if (codec > -1) { 02085 snprintf(costr, sizeof(costr), " %d", codec); 02086 strncat(m, costr, sizeof(m) - strlen(m) - 1); 02087 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0)); 02088 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02089 if (x == AST_RTP_DTMF) { 02090 /* Indicate we support DTMF... Not sure about 16, 02091 but MSN supports it so dang it, we will too... */ 02092 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec); 02093 strncat(a, costr, sizeof(a) - strlen(a) - 1); 02094 } 02095 } 02096 } 02097 } 02098 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1); 02099 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a); 02100 snprintf(costr, sizeof(costr), "%d", len); 02101 add_line(resp, v); 02102 add_line(resp, o); 02103 add_line(resp, s); 02104 add_line(resp, c); 02105 add_line(resp, t); 02106 add_line(resp, m); 02107 add_line(resp, a); 02108 return 0; 02109 }
|
|
||||||||||||||||||||||||||||
|
|
|
|
gatelock: mutex for gateway/endpoint lists
|
|
|
|
|
|
|
|
|
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. |
|
|
Definition at line 2870 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_indicate(), ast_log(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RINGING, ast_verbose(), mgcp_subchannel::id, LOG_DEBUG, LOG_WARNING, mgcp_queue_hangup(), mgcp_gateway::name, mgcp_endpoint::name, mgcp_subchannel::next, option_verbose, mgcp_subchannel::owner, mgcp_endpoint::parent, mgcp_endpoint::sub, unalloc_sub(), and VERBOSE_PREFIX_3. Referenced by handle_onhook_message(), handle_request(), handle_soft_key_event_message(), local_attended_transfer(), and zt_handle_event(). 02871 { 02872 /* ************************* 02873 * I hope this works. 02874 * Copied out of chan_zap 02875 * Cross your fingers 02876 * *************************/ 02877 02878 /* In order to transfer, we need at least one of the channels to 02879 actually be in a call bridge. We can't conference two applications 02880 together (but then, why would we want to?) */ 02881 if (ast_bridged_channel(p->sub->owner)) { 02882 /* The three-way person we're about to transfer to could still be in MOH, so 02883 stop if now if appropriate */ 02884 if (ast_bridged_channel(p->sub->next->owner)) 02885 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 02886 if (p->sub->owner->_state == AST_STATE_RINGING) { 02887 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 02888 } 02889 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) { 02890 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 02891 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name); 02892 return -1; 02893 } 02894 /* Orphan the channel */ 02895 unalloc_sub(p->sub->next); 02896 } else if (ast_bridged_channel(p->sub->next->owner)) { 02897 if (p->sub->owner->_state == AST_STATE_RINGING) { 02898 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING); 02899 } 02900 ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD); 02901 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) { 02902 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 02903 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name); 02904 return -1; 02905 } 02906 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/ 02907 if (option_verbose > 2) { 02908 ast_verbose(VERBOSE_PREFIX_3 "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 02909 } 02910 p->sub = p->sub->next; 02911 unalloc_sub(p->sub->next); 02912 /* Tell the caller not to hangup */ 02913 return 1; 02914 } else { 02915 if (option_debug) 02916 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 02917 p->sub->owner->name, p->sub->next->owner->name); 02918 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02919 if (p->sub->next->owner) { 02920 p->sub->next->alreadygone = 1; 02921 mgcp_queue_hangup(p->sub->next); 02922 } 02923 } 02924 return 0; 02925 }
|
|
||||||||||||
|
build_gateway: parse mgcp.conf and create gateway/endpoint structures
Definition at line 3569 of file chan_mgcp.c. References mgcp_endpoint::accountcode, accountcode, mgcp_gateway::addr, mgcp_endpoint::adsi, adsi, mgcp_endpoint::amaflags, amaflags, ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_destroy(), ast_mutex_init(), ast_random(), ast_sched_del(), ast_strlen_zero(), ast_true(), ast_verbose(), mgcp_endpoint::callgroup, mgcp_endpoint::callreturn, callreturn, mgcp_endpoint::callwaiting, callwaiting, mgcp_endpoint::cancallforward, cancallforward, mgcp_endpoint::canreinvite, CANREINVITE, canreinvite, capability, mgcp_endpoint::capability, mgcp_endpoint::cid_name, cid_name, mgcp_endpoint::cid_num, cid_num, mgcp_endpoint::context, context, cur_callergroup, cur_pickupgroup, mgcp_subchannel::cx_queue_lock, mgcp_subchannel::cxmode, mgcp_gateway::defaddr, mgcp_endpoint::delme, mgcp_gateway::delme, mgcp_endpoint::dtmfmode, dtmfmode, mgcp_gateway::dynamic, mgcp_gateway::endpoints, mgcp_gateway::expire, free, gateways, mgcp_gateway::ha, mgcp_endpoint::hascallwaiting, mgcp_endpoint::hookstate, mgcp_subchannel::id, mgcp_endpoint::immediate, immediate, INADDR_NONE, mgcp_endpoint::language, language, ast_variable::lineno, mgcp_subchannel::lock, LOG_WARNING, mgcp_subchannel::magic, mgcp_endpoint::mailbox, mailbox, malloc, MAX_SUBS, 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, musicclass, mgcp_endpoint::name, ast_variable::name, mgcp_gateway::name, mgcp_subchannel::nat, nat, mgcp_subchannel::next, mgcp_endpoint::next, mgcp_gateway::next, mgcp_endpoint::onhooktime, mgcp_subchannel::parent, mgcp_endpoint::parent, mgcp_endpoint::pickupgroup, mgcp_endpoint::rqnt_ident, mgcp_subchannel::rtp, mgcp_endpoint::singlepath, singlepath, mgcp_endpoint::slowsequence, slowsequence, mgcp_endpoint::sub, mgcp_endpoint::threewaycalling, threewaycalling, mgcp_endpoint::transfer, transfer, mgcp_subchannel::txident, mgcp_endpoint::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, VERBOSE_PREFIX_3, and mgcp_gateway::wcardep. Referenced by reload_config(). 03570 { 03571 struct mgcp_gateway *gw; 03572 struct mgcp_endpoint *e; 03573 struct mgcp_subchannel *sub; 03574 /*char txident[80];*/ 03575 int i=0, y=0; 03576 int gw_reload = 0; 03577 int ep_reload = 0; 03578 canreinvite = CANREINVITE; 03579 03580 /* locate existing gateway */ 03581 gw = gateways; 03582 while (gw) { 03583 if (!strcasecmp(cat, gw->name)) { 03584 /* gateway already exists */ 03585 gw->delme = 0; 03586 gw_reload = 1; 03587 break; 03588 } 03589 gw = gw->next; 03590 } 03591 03592 if (!gw) 03593 gw = malloc(sizeof(struct mgcp_gateway)); 03594 03595 if (gw) { 03596 if (!gw_reload) { 03597 memset(gw, 0, sizeof(struct mgcp_gateway)); 03598 gw->expire = -1; 03599 gw->retransid = -1; /* SC */ 03600 ast_mutex_init(&gw->msgs_lock); 03601 ast_copy_string(gw->name, cat, sizeof(gw->name)); 03602 /* check if the name is numeric ip */ 03603 if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE) 03604 gw->isnamedottedip = 1; 03605 } 03606 while(v) { 03607 if (!strcasecmp(v->name, "host")) { 03608 if (!strcasecmp(v->value, "dynamic")) { 03609 /* They'll register with us */ 03610 gw->dynamic = 1; 03611 memset(&gw->addr.sin_addr, 0, 4); 03612 if (gw->addr.sin_port) { 03613 /* If we've already got a port, make it the default rather than absolute */ 03614 gw->defaddr.sin_port = gw->addr.sin_port; 03615 gw->addr.sin_port = 0; 03616 } 03617 } else { 03618 /* Non-dynamic. Make sure we become that way if we're not */ 03619 if (gw->expire > -1) 03620 ast_sched_del(sched, gw->expire); 03621 gw->expire = -1; 03622 gw->dynamic = 0; 03623 if (ast_get_ip(&gw->addr, v->value)) { 03624 if (!gw_reload) { 03625 ast_mutex_destroy(&gw->msgs_lock); 03626 free(gw); 03627 } 03628 return NULL; 03629 } 03630 } 03631 } else if (!strcasecmp(v->name, "defaultip")) { 03632 if (ast_get_ip(&gw->defaddr, v->value)) { 03633 if (!gw_reload) { 03634 ast_mutex_destroy(&gw->msgs_lock); 03635 free(gw); 03636 } 03637 return NULL; 03638 } 03639 } else if (!strcasecmp(v->name, "permit") || 03640 !strcasecmp(v->name, "deny")) { 03641 gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL); 03642 } else if (!strcasecmp(v->name, "port")) { 03643 gw->addr.sin_port = htons(atoi(v->value)); 03644 } else if (!strcasecmp(v->name, "context")) { 03645 ast_copy_string(context, v->value, sizeof(context)); 03646 } else if (!strcasecmp(v->name, "dtmfmode")) { 03647 if (!strcasecmp(v->value, "inband")) 03648 dtmfmode = MGCP_DTMF_INBAND; 03649 else if (!strcasecmp(v->value, "rfc2833")) 03650 dtmfmode = MGCP_DTMF_RFC2833; 03651 else if (!strcasecmp(v->value, "hybrid")) 03652 dtmfmode = MGCP_DTMF_HYBRID; 03653 else if (!strcasecmp(v->value, "none")) 03654 dtmfmode = 0; 03655 else 03656 ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno); 03657 } else if (!strcasecmp(v->name, "nat")) { 03658 nat = ast_true(v->value); 03659 } else if (!strcasecmp(v->name, "callerid")) { 03660 if (!strcasecmp(v->value, "asreceived")) { 03661 cid_num[0] = '\0'; 03662 cid_name[0] = '\0'; 03663 } else { 03664 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 03665 } 03666 } else if (!strcasecmp(v->name, "language")) { 03667 ast_copy_string(language, v->value, sizeof(language)); 03668 } else if (!strcasecmp(v->name, "accountcode")) { 03669 ast_copy_string(accountcode, v->value, sizeof(accountcode)); 03670 } else if (!strcasecmp(v->name, "amaflags")) { 03671 y = ast_cdr_amaflags2int(v->value); 03672 if (y < 0) { 03673 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 03674 } else { 03675 amaflags = y; 03676 } 03677 } else if (!strcasecmp(v->name, "musiconhold")) { 03678 ast_copy_string(musicclass, v->value, sizeof(musicclass)); 03679 } else if (!strcasecmp(v->name, "callgroup")) { 03680 cur_callergroup = ast_get_group(v->value); 03681 } else if (!strcasecmp(v->name, "pickupgroup")) { 03682 cur_pickupgroup = ast_get_group(v->value); 03683 } else if (!strcasecmp(v->name, "immediate")) { 03684 immediate = ast_true(v->value); 03685 } else if (!strcasecmp(v->name, "cancallforward")) { 03686 cancallforward = ast_true(v->value); 03687 } else if (!strcasecmp(v->name, "singlepath")) { 03688 singlepath = ast_true(v->value); 03689 } else if (!strcasecmp(v->name, "canreinvite")) { 03690 canreinvite = ast_true(v->value); 03691 } else if (!strcasecmp(v->name, "mailbox")) { 03692 ast_copy_string(mailbox, v->value, sizeof(mailbox)); 03693 } else if (!strcasecmp(v->name, "adsi")) { 03694 adsi = ast_true(v->value); 03695 } else if (!strcasecmp(v->name, "callreturn")) { 03696 callreturn = ast_true(v->value); 03697 } else if (!strcasecmp(v->name, "callwaiting")) { 03698 callwaiting = ast_true(v->value); 03699 } else if (!strcasecmp(v->name, "slowsequence")) { 03700 slowsequence = ast_true(v->value); 03701 } else if (!strcasecmp(v->name, "transfer")) { 03702 transfer = ast_true(v->value); 03703 } else if (!strcasecmp(v->name, "threewaycalling")) { 03704 threewaycalling = ast_true(v->value); 03705 } else if (!strcasecmp(v->name, "wcardep")) { 03706 /* locate existing endpoint */ 03707 e = gw->endpoints; 03708 while (e) { 03709 if (!strcasecmp(v->value, e->name)) { 03710 /* endpoint already exists */ 03711 e->delme = 0; 03712 ep_reload = 1; 03713 break; 03714 } 03715 e = e->next; 03716 } 03717 03718 if (!e) { 03719 /* Allocate wildcard endpoint */ 03720 e = malloc(sizeof(struct mgcp_endpoint)); 03721 ep_reload = 0; 03722 } 03723 03724 if (e) { 03725 if (!ep_reload) { 03726 memset(e, 0, sizeof(struct mgcp_endpoint)); 03727 ast_mutex_init(&e->lock); 03728 ast_mutex_init(&e->rqnt_queue_lock); 03729 ast_mutex_init(&e->cmd_queue_lock); 03730 ast_copy_string(e->name, v->value, sizeof(e->name)); 03731 e->needaudit = 1; 03732 } 03733 ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep)); 03734 /* XXX Should we really check for uniqueness?? XXX */ 03735 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 03736 ast_copy_string(e->context, context, sizeof(e->context)); 03737 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 03738 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 03739 ast_copy_string(e->language, language, sizeof(e->language)); 03740 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 03741 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 03742 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 03743 e->msgstate = -1; 03744 e->amaflags = amaflags; 03745 e->capability = capability; 03746 e->parent = gw; 03747 e->dtmfmode = dtmfmode; 03748 if (!ep_reload && e->sub && e->sub->rtp) 03749 e->dtmfmode |= MGCP_DTMF_INBAND; 03750 e->adsi = adsi; 03751 e->type = TYPE_LINE; 03752 e->immediate = immediate; 03753 e->callgroup=cur_callergroup; 03754 e->pickupgroup=cur_pickupgroup; 03755 e->callreturn = callreturn; 03756 e->cancallforward = cancallforward; 03757 e->singlepath = singlepath; 03758 e->canreinvite = canreinvite; 03759 e->callwaiting = callwaiting; 03760 e->hascallwaiting = callwaiting; 03761 e->slowsequence = slowsequence; 03762 e->transfer = transfer; 03763 e->threewaycalling = threewaycalling; 03764 e->onhooktime = time(NULL); 03765 /* ASSUME we're onhook */ 03766 e->hookstate = MGCP_ONHOOK; 03767 if (!ep_reload) { 03768 /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/ 03769 for (i = 0; i < MAX_SUBS; i++) { 03770 sub = malloc(sizeof(struct mgcp_subchannel)); 03771 if (sub) { 03772 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 03773 memset(sub, 0, sizeof(struct mgcp_subchannel)); 03774 ast_mutex_init(&sub->lock); 03775 ast_mutex_init(&sub->cx_queue_lock); 03776 sub->parent = e; 03777 sub->id = i; 03778 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 03779 /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/ 03780 sub->cxmode = MGCP_CX_INACTIVE; 03781 sub->nat = nat; 03782 sub->next = e->sub; 03783 e->sub = sub; 03784 } else { 03785 /* XXX Should find a way to clean up our memory */ 03786 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 03787 return NULL; 03788 } 03789 } 03790 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 03791 sub = e->sub; 03792 /* find the end of the list */ 03793 while(sub->next){ 03794 sub = sub->next; 03795 } 03796 /* set the last sub->next to the first sub */ 03797 sub->next = e->sub; 03798 03799 e->next = gw->endpoints; 03800 gw->endpoints = e; 03801 } 03802 } 03803 } else if (!strcasecmp(v->name, "trunk") || 03804 !strcasecmp(v->name, "line")) { 03805 03806 /* locate existing endpoint */ 03807 e = gw->endpoints; 03808 while (e) { 03809 if (!strcasecmp(v->value, e->name)) { 03810 /* endpoint already exists */ 03811 e->delme = 0; 03812 ep_reload = 1; 03813 break; 03814 } 03815 e = e->next; 03816 } 03817 03818 if (!e) { 03819 e = malloc(sizeof(struct mgcp_endpoint)); 03820 ep_reload = 0; 03821 } 03822 03823 if (e) { 03824 if (!ep_reload) { 03825 memset(e, 0, sizeof(struct mgcp_endpoint)); 03826 ast_mutex_init(&e->lock); 03827 ast_mutex_init(&e->rqnt_queue_lock); 03828 ast_mutex_init(&e->cmd_queue_lock); 03829 ast_copy_string(e->name, v->value, sizeof(e->name)); 03830 e->needaudit = 1; 03831 } 03832 /* XXX Should we really check for uniqueness?? XXX */ 03833 ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode)); 03834 ast_copy_string(e->context, context, sizeof(e->context)); 03835 ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num)); 03836 ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name)); 03837 ast_copy_string(e->language, language, sizeof(e->language)); 03838 ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass)); 03839 ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox)); 03840 if (!ast_strlen_zero(mailbox)) { 03841 ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name); 03842 } 03843 if (!ep_reload) { 03844 /* XXX potential issue due to reload */ 03845 e->msgstate = -1; 03846 e->parent = gw; 03847 } 03848 e->amaflags = amaflags; 03849 e->capability = capability; 03850 e->dtmfmode = dtmfmode; 03851 e->adsi = adsi; 03852 if (!strcasecmp(v->name, "trunk")) 03853 e->type = TYPE_TRUNK; 03854 else 03855 e->type = TYPE_LINE; 03856 03857 e->immediate = immediate; 03858 e->callgroup=cur_callergroup; 03859 e->pickupgroup=cur_pickupgroup; 03860 e->callreturn = callreturn; 03861 e->cancallforward = cancallforward; 03862 e->canreinvite = canreinvite; 03863 e->singlepath = singlepath; 03864 e->callwaiting = callwaiting; 03865 e->hascallwaiting = callwaiting; 03866 e->slowsequence = slowsequence; 03867 e->transfer = transfer; 03868 e->threewaycalling = threewaycalling; 03869 if (!ep_reload) { 03870 e->onhooktime = time(NULL); 03871 /* ASSUME we're onhook */ 03872 e->hookstate = MGCP_ONHOOK; 03873 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random()); 03874 } 03875 03876 for (i = 0, sub = NULL; i < MAX_SUBS; i++) { 03877 if (!ep_reload) { 03878 sub = malloc(sizeof(struct mgcp_subchannel)); 03879 } else { 03880 if (!sub) 03881 sub = e->sub; 03882 else 03883 sub = sub->next; 03884 } 03885 03886 if (sub) { 03887 if (!ep_reload) { 03888 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name); 03889 memset(sub, 0, sizeof(struct mgcp_subchannel)); 03890 ast_mutex_init(&sub->lock); 03891 ast_mutex_init(&sub->cx_queue_lock); 03892 ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic)); 03893 sub->parent = e; 03894 sub->id = i; 03895 snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random()); 03896 sub->cxmode = MGCP_CX_INACTIVE; 03897 sub->next = e->sub; 03898 e->sub = sub; 03899 } 03900 sub->nat = nat; 03901 } else { 03902 /* XXX Should find a way to clean up our memory */ 03903 ast_log(LOG_WARNING, "Out of memory allocating subchannel\n"); 03904 return NULL; 03905 } 03906 } 03907 if (!ep_reload) { 03908 /* Make out subs a circular linked list so we can always sping through the whole bunch */ 03909 sub = e->sub; 03910 /* find the end of the list */ 03911 while (sub->next) { 03912 sub = sub->next; 03913 } 03914 /* set the last sub->next to the first sub */ 03915 sub->next = e->sub; 03916 03917 e->next = gw->endpoints; 03918 gw->endpoints = e; 03919 } 03920 } 03921 } else 03922 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno); 03923 v = v->next; 03924 } 03925 } 03926 if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) { 03927 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name); 03928 if (!gw_reload) { 03929 ast_mutex_destroy(&gw->msgs_lock); 03930 free(gw); 03931 } 03932 return NULL; 03933 } 03934 gw->defaddr.sin_family = AF_INET; 03935 gw->addr.sin_family = AF_INET; 03936 if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 03937 gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 03938 if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) 03939 gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT); 03940 if (gw->addr.sin_addr.s_addr) 03941 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip)) 03942 memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip)); 03943 03944 return (gw_reload ? NULL : gw); 03945 }
|
|
|
Definition at line 1357 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(), and skinny_indicate(). 01357 { 01358 switch (ind) { 01359 case AST_CONTROL_HANGUP: 01360 return "Other end has hungup"; 01361 case AST_CONTROL_RING: 01362 return "Local ring"; 01363 case AST_CONTROL_RINGING: 01364 return "Remote end is ringing"; 01365 case AST_CONTROL_ANSWER: 01366 return "Remote end has answered"; 01367 case AST_CONTROL_BUSY: 01368 return "Remote end is busy"; 01369 case AST_CONTROL_TAKEOFFHOOK: 01370 return "Make it go off hook"; 01371 case AST_CONTROL_OFFHOOK: 01372 return "Line is off hook"; 01373 case AST_CONTROL_CONGESTION: 01374 return "Congestion (circuits busy)"; 01375 case AST_CONTROL_FLASH: 01376 return "Flash hook"; 01377 case AST_CONTROL_WINK: 01378 return "Wink"; 01379 case AST_CONTROL_OPTION: 01380 return "Set a low-level option"; 01381 case AST_CONTROL_RADIO_KEY: 01382 return "Key Radio"; 01383 case AST_CONTROL_RADIO_UNKEY: 01384 return "Un-Key Radio"; 01385 } 01386 return "UNKNOWN"; 01387 }
|
|
|
Definition at line 3980 of file chan_mgcp.c. References ast_mutex_lock(), ast_strlen_zero(), mgcp_subchannel::cxident, mgcp_subchannel::lock, MAX_SUBS, mgcp_subchannel::next, s, mgcp_endpoint::sub, and transmit_connection_del(). Referenced by prune_gateways(). 03981 { 03982 struct mgcp_subchannel *sub = e->sub->next, *s; 03983 int i; 03984 03985 for (i = 0; i < MAX_SUBS; i++) { 03986 ast_mutex_lock(&sub->lock); 03987 if (!ast_strlen_zero(sub->cxident)) { 03988 transmit_connection_del(sub); 03989 } 03990 if (sub->rtp) { 03991 ast_rtp_destroy(sub->rtp); 03992 sub->rtp = NULL; 03993 } 03994 memset(sub->magic, 0, sizeof(sub->magic)); 03995 mgcp_queue_hangup(sub); 03996 dump_cmd_queues(NULL, sub); 03997 ast_mutex_unlock(&sub->lock); 03998 sub = sub->next; 03999 } 04000 04001 if (e->dsp) { 04002 ast_dsp_free(e->dsp); 04003 } 04004 04005 dump_queue(e->parent, e); 04006 dump_cmd_queues(e, NULL); 04007 04008 sub = e->sub; 04009 for (i = 0; (i < MAX_SUBS) && sub; i++) { 04010 s = sub; 04011 sub = sub->next; 04012 ast_mutex_destroy(&s->lock); 04013 ast_mutex_destroy(&s->cx_queue_lock); 04014 free(s); 04015 } 04016 ast_mutex_destroy(&e->lock); 04017 ast_mutex_destroy(&e->rqnt_queue_lock); 04018 ast_mutex_destroy(&e->cmd_queue_lock); 04019 free(e); 04020 }
|
|
|
Definition at line 4022 of file chan_mgcp.c. References ast_free_ha(), dump_queue(), free, and mgcp_gateway::ha. 04023 { 04024 if (g->ha) 04025 ast_free_ha(g->ha); 04026 04027 dump_queue(g, NULL); 04028 04029 free (g); 04030 }
|
|
|
Definition at line 3398 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_verbose(), mgcp_gateway::endpoints, gateways, has_voicemail(), io, mgcp_do_reload(), MGCP_ONHOOK, mgcp_reloading, mgcpsock, mgcpsock_read(), option_verbose, transmit_notify_request(), TYPE_LINE, and VERBOSE_PREFIX_1. 03399 { 03400 int res; 03401 int reloading; 03402 /*struct mgcp_gateway *g;*/ 03403 /*struct mgcp_endpoint *e;*/ 03404 /*time_t thispass = 0, lastpass = 0;*/ 03405 03406 /* Add an I/O event to our UDP socket */ 03407 if (mgcpsock > -1) 03408 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03409 03410 /* This thread monitors all the frame relay interfaces which are not yet in use 03411 (and thus do not have a separate thread) indefinitely */ 03412 /* From here on out, we die whenever asked */ 03413 for(;;) { 03414 /* Check for a reload request */ 03415 ast_mutex_lock(&mgcp_reload_lock); 03416 reloading = mgcp_reloading; 03417 mgcp_reloading = 0; 03418 ast_mutex_unlock(&mgcp_reload_lock); 03419 if (reloading) { 03420 if (option_verbose > 0) 03421 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n"); 03422 mgcp_do_reload(); 03423 /* Add an I/O event to our UDP socket */ 03424 if (mgcpsock > -1) 03425 mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL); 03426 } 03427 03428 /* Check for interfaces needing to be killed */ 03429 /* Don't let anybody kill us right away. Nobody should lock the interface list 03430 and wait for the monitor list, but the other way around is okay. */ 03431 ast_mutex_lock(&monlock); 03432 /* Lock the network interface */ 03433 ast_mutex_lock(&netlock); 03434 03435 #if 0 03436 /* XXX THIS IS COMPLETELY HOSED */ 03437 /* The gateway goes into a state of panic */ 03438 /* If the vmwi indicator is sent while it is reseting interfaces */ 03439 lastpass = thispass; 03440 thispass = time(NULL); 03441 g = gateways; 03442 while(g) { 03443 if (thispass != lastpass) { 03444 e = g->endpoints; 03445 while(e) { 03446 if (e->type == TYPE_LINE) { 03447 res = has_voicemail(e); 03448 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){ 03449 if (res) { 03450 transmit_notify_request(e, "L/vmwi(+)"); 03451 } else { 03452 transmit_notify_request(e, "L/vmwi(-)"); 03453 } 03454 e->msgstate = res; 03455 e->onhooktime = thispass; 03456 } 03457 } 03458 e = e->next; 03459 } 03460 } 03461 g = g->next; 03462 } 03463 #endif 03464 /* Okay, now that we know what to do, release the network lock */ 03465 ast_mutex_unlock(&netlock); 03466 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 03467 ast_mutex_unlock(&monlock); 03468 pthread_testcancel(); 03469 /* Wait for sched or io */ 03470 res = ast_sched_wait(sched); 03471 /* copied from chan_sip.c */ 03472 if ((res < 0) || (res > 1000)) 03473 res = 1000; 03474 res = ast_io_wait(io, res); 03475 ast_mutex_lock(&monlock); 03476 if (res >= 0) 03477 ast_sched_runq(sched); 03478 ast_mutex_unlock(&monlock); 03479 } 03480 /* Never reached */ 03481 return NULL; 03482 }
|
|
||||||||||||
|
||||||||||||
|
Definition at line 527 of file chan_mgcp.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), free, LOG_NOTICE, mgcp_gateway::msgs, mgcp_gateway::msgs_lock, mgcp_gateway::name, and mgcp_message::next. Referenced by destroy_gateway(), and handle_request(). 00528 { 00529 struct mgcp_message *cur, *q = NULL, *w, *prev; 00530 00531 ast_mutex_lock(&gw->msgs_lock); 00532 prev = NULL, cur = gw->msgs; 00533 while (cur) { 00534 if (!p || cur->owner_ep == p) { 00535 if (prev) 00536 prev->next = cur->next; 00537 else 00538 gw->msgs = cur->next; 00539 00540 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 00541 gw->name, cur->seqno); 00542 00543 w = cur; 00544 cur = cur->next; 00545 if (q) { 00546 w->next = q; 00547 } else { 00548 w->next = NULL; 00549 } 00550 q = w; 00551 } else { 00552 prev = cur, cur=cur->next; 00553 } 00554 } 00555 ast_mutex_unlock(&gw->msgs_lock); 00556 00557 while (q) { 00558 cur = q; 00559 q = q->next; 00560 free(cur); 00561 } 00562 }
|
|
||||||||||||
|
Definition at line 3275 of file chan_mgcp.c. References answer, 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(). 03276 { 03277 int seqno=0; 03278 time_t now; 03279 struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL; 03280 time(&now); 03281 if (sscanf(req->identifier, "%d", &seqno) != 1) 03282 seqno = 0; 03283 cur = sub->parent->parent->responses; 03284 while(cur) { 03285 next = cur->next; 03286 if (now - cur->whensent > RESPONSE_TIMEOUT) { 03287 /* Delete this entry */ 03288 if (prev) 03289 prev->next = next; 03290 else 03291 sub->parent->parent->responses = next; 03292 free(cur); 03293 } else { 03294 if (seqno == cur->seqno) 03295 answer = cur; 03296 prev = cur; 03297 } 03298 cur = next; 03299 } 03300 if (answer) { 03301 resend_response(sub, answer); 03302 return 1; 03303 } 03304 return 0; 03305 }
|
|
||||||||||||||||||||||||
|
find_command: (SC:) remove command transaction from queue
Definition at line 2388 of file chan_mgcp.c. References mgcp_gateway::addr, ast_inet_ntoa(), ast_mutex_lock(), ast_verbose(), mgcp_request::next, and mgcp_endpoint::parent. Referenced by agi_handle_command(), handle_response(), and handle_showagi(). 02390 { 02391 struct mgcp_request *prev, *req; 02392 02393 ast_mutex_lock(l); 02394 for (prev = NULL, req = *queue; req; prev = req, req = req->next) { 02395 if (req->trid == ident) { 02396 /* remove from queue */ 02397 if (!prev) 02398 *queue = req->next; 02399 else 02400 prev->next = req->next; 02401 02402 /* send next pending command */ 02403 if (*queue) { 02404 if (mgcpdebug) { 02405 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 02406 ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port)); 02407 } 02408 02409 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid); 02410 } 02411 break; 02412 } 02413 } 02414 ast_mutex_unlock(l); 02415 return req; 02416 }
|
|
||||||||||||||||
|
Definition at line 1590 of file chan_mgcp.c. References __ourip, mgcp_gateway::addr, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_ouraddrfor(), ast_verbose(), mgcp_gateway::defaddr, mgcp_gateway::dynamic, mgcp_gateway::endpoints, gateways, mgcp_subchannel::id, mgcp_subchannel::lock, LOG_DEBUG, LOG_NOTICE, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, mgcp_subchannel::next, mgcp_gateway::next, option_debug, option_verbose, mgcp_gateway::ourip, mgcp_endpoint::sub, and VERBOSE_PREFIX_3. Referenced by mgcp_request(), and mgcpsock_read(). 01591 { 01592 struct mgcp_endpoint *p = NULL; 01593 struct mgcp_subchannel *sub = NULL; 01594 struct mgcp_gateway *g; 01595 char tmp[256] = ""; 01596 char *at = NULL, *c; 01597 int found = 0; 01598 if (name) { 01599 ast_copy_string(tmp, name, sizeof(tmp)); 01600 at = strchr(tmp, '@'); 01601 if (!at) { 01602 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name); 01603 return NULL; 01604 } 01605 *at++ = '\0'; 01606 } 01607 ast_mutex_lock(&gatelock); 01608 if (at && (at[0] == '[')) { 01609 at++; 01610 c = strrchr(at, ']'); 01611 if (c) 01612 *c = '\0'; 01613 } 01614 g = gateways; 01615 while(g) { 01616 if ((!name || !strcasecmp(g->name, at)) && 01617 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) { 01618 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */ 01619 if (sin && g->dynamic && name) { 01620 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01621 (g->addr.sin_port != sin->sin_port)) { 01622 memcpy(&g->addr, sin, sizeof(g->addr)); 01623 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip)) 01624 memcpy(&g->ourip, &__ourip, sizeof(g->ourip)); 01625 if (option_verbose > 2) 01626 ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port)); 01627 } 01628 } 01629 /* not dynamic, check if the name matches */ 01630 else if (name) { 01631 if (strcasecmp(g->name, at)) { 01632 g = g->next; 01633 continue; 01634 } 01635 } 01636 /* not dynamic, no name, check if the addr matches */ 01637 else if (!name && sin) { 01638 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) || 01639 (g->addr.sin_port != sin->sin_port)) { 01640 g = g->next; 01641 continue; 01642 } 01643 } else { 01644 g = g->next; 01645 continue; 01646 } 01647 /* SC */ 01648 p = g->endpoints; 01649 while(p) { 01650 if (option_debug) 01651 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n", 01652 p->name, g->name); 01653 if (msgid) { 01654 #if 0 /* new transport mech */ 01655 sub = p->sub; 01656 do { 01657 if (option_debug) 01658 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n", 01659 p->name, g->name, sub->id, msgid); 01660 if (sub->lastout == msgid) { 01661 if (option_debug) 01662 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", 01663 sub->id, msgid, sub->lastout); 01664 found = 1; 01665 break; 01666 } 01667 sub = sub->next; 01668 } while (sub != p->sub); 01669 if (found) { 01670 break; 01671 } 01672 #endif 01673 /* SC */ 01674 sub = p->sub; 01675 found = 1; 01676 /* SC */ 01677 break; 01678 } else if (name && !strcasecmp(p->name, tmp)) { 01679 if (option_debug) 01680 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 01681 p->name, g->name, p->sub->id); 01682 sub = p->sub; 01683 found = 1; 01684 break; 01685 } 01686 p = p->next; 01687 } 01688 if (sub && found) { 01689 ast_mutex_lock(&sub->lock); 01690 break; 01691 } 01692 } 01693 g = g->next; 01694 } 01695 ast_mutex_unlock(&gatelock); 01696 if (!sub) { 01697 if (name) { 01698 if (g) 01699 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at); 01700 else 01701 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp); 01702 } 01703 } 01704 return sub; 01705 }
|
|
||||||||||||||||
|
get_csv: (SC:) get comma separated value
Definition at line 1569 of file chan_mgcp.c. References s. Referenced by handle_response(). 01570 { 01571 char *s; 01572 01573 *next = NULL, *len = 0; 01574 if (!c) return NULL; 01575 01576 while (*c && (*c < 33 || *c == ',')) 01577 c++; 01578 01579 s = c; 01580 while (*c && (*c >= 33 && *c != ',')) 01581 c++, (*len)++; 01582 *next = c; 01583 01584 if (*len == 0) 01585 s = NULL, *next = NULL; 01586 01587 return s; 01588 }
|
|
||||||||||||
|
||||||||||||
|
Definition at line 1514 of file chan_mgcp.c. References get_sdp_by_line(), len, mgcp_request::line, and mgcp_request::lines. Referenced by process_sdp(). 01515 { 01516 int x; 01517 int len = strlen(name); 01518 char *r; 01519 01520 for (x=0; x<req->lines; x++) { 01521 r = get_sdp_by_line(req->line[x], name, len); 01522 if (r[0] != '\0') return r; 01523 } 01524 return ""; 01525 }
|
|
||||||||||||||||
|
Definition at line 1504 of file chan_mgcp.c. Referenced by get_sdp(), and get_sdp_iterate(). 01505 { 01506 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') { 01507 char* r = line + nameLen + 1; 01508 while (*r && (*r < 33)) ++r; 01509 return r; 01510 } 01511 return ""; 01512 }
|
|
||||||||||||||||
|
Definition at line 1532 of file chan_mgcp.c. References get_sdp_by_line(), len, and mgcp_request::line. Referenced by get_sdp(), and process_sdp(). 01533 { 01534 int len = strlen(name); 01535 char *r; 01536 while (*iterator < req->lines) { 01537 r = get_sdp_by_line(req->line[(*iterator)++], name, len); 01538 if (r[0] != '\0') return r; 01539 } 01540 return ""; 01541 }
|
|
||||||||||||
|
Definition at line 2927 of file chan_mgcp.c. References ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_UNHOLD, ast_hangup(), ast_log(), ast_pthread_create, ast_queue_control(), AST_STATE_DOWN, AST_STATE_RING, mgcp_subchannel::cxmode, 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(), mgcp_endpoint::sub, transmit_modify_request(), and transmit_notify_request(). Referenced by handle_request(). 02928 { 02929 struct mgcp_endpoint *p = sub->parent; 02930 struct ast_channel *c; 02931 pthread_t t; 02932 pthread_attr_t attr; 02933 pthread_attr_init(&attr); 02934 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 02935 02936 /* Off hook / answer */ 02937 if (sub->outgoing) { 02938 /* Answered */ 02939 if (sub->owner) { 02940 if (ast_bridged_channel(sub->owner)) 02941 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 02942 sub->cxmode = MGCP_CX_SENDRECV; 02943 if (!sub->rtp) { 02944 start_rtp(sub); 02945 } else { 02946 transmit_modify_request(sub); 02947 } 02948 /*transmit_notify_request(sub, "aw");*/ 02949 transmit_notify_request(sub, ""); 02950 mgcp_queue_control(sub, AST_CONTROL_ANSWER); 02951 } 02952 } else { 02953 /* Start switch */ 02954 /*sub->cxmode = MGCP_CX_SENDRECV;*/ 02955 if (!sub->owner) { 02956 if (!sub->rtp) { 02957 start_rtp(sub); 02958 } else { 02959 transmit_modify_request(sub); 02960 } 02961 if (p->immediate) { 02962 /* The channel is immediately up. Start right away */ 02963 #ifdef DLINK_BUGGY_FIRMWARE 02964 transmit_notify_request(sub, "rt"); 02965 #else 02966 transmit_notify_request(sub, "G/rt"); 02967 #endif 02968 c = mgcp_new(sub, AST_STATE_RING); 02969 if (!c) { 02970 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name); 02971 transmit_notify_request(sub, "G/cg"); 02972 ast_hangup(c); 02973 } 02974 } else { 02975 if (has_voicemail(p)) { 02976 transmit_notify_request(sub, "L/sl"); 02977 } else { 02978 transmit_notify_request(sub, "L/dl"); 02979 } 02980 c = mgcp_new(sub, AST_STATE_DOWN); 02981 if (c) { 02982 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) { 02983 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno)); 02984 ast_hangup(c); 02985 } 02986 } else { 02987 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name); 02988 } 02989 } 02990 } else { 02991 if (p->hookstate == MGCP_OFFHOOK) { 02992 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name); 02993 } else { 02994 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); 02995 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); 02996 } 02997 if (ast_bridged_channel(sub->owner)) 02998 ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); 02999 sub->cxmode = MGCP_CX_SENDRECV; 03000 if (!sub->rtp) { 03001 start_rtp(sub); 03002 } else { 03003 transmit_modify_request(sub); 03004 } 03005 /*transmit_notify_request(sub, "aw");*/ 03006 transmit_notify_request(sub, ""); 03007 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/ 03008 } 03009 } 03010 }
|
|
||||||||||||||||
|
Definition at line 3012 of file chan_mgcp.c. References ast_channel::_state, mgcp_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_FRAME_DTMF, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_control(), AST_STATE_DOWN, ast_verbose(), attempt_transfer(), mgcp_endpoint::callwaiting, mgcp_endpoint::curtone, mgcp_subchannel::cxmode, 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_DEBUG, 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_subchannel::next, mgcp_endpoint::next, option_verbose, 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, VERBOSE_PREFIX_3, and mgcp_gateway::wcardep. Referenced by mgcpsock_read(), and process_sip_queue(). 03013 { 03014 char *ev, *s; 03015 struct ast_frame f = { 0, }; 03016 struct mgcp_endpoint *p = sub->parent; 03017 struct mgcp_gateway *g = NULL; 03018 int res; 03019 03020 if (mgcpdebug) { 03021 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name); 03022 } 03023 /* Clear out potential response */ 03024 if (!strcasecmp(req->verb, "RSIP")) { 03025 /* Test if this RSIP request is just a keepalive */ 03026 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) { 03027 if (option_verbose > 2) 03028 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name); 03029 transmit_response(sub, "200", req, "OK"); 03030 } else { 03031 dump_queue(p->parent, p); 03032 dump_cmd_queues(p, NULL); 03033 03034 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) { 03035 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name); 03036 } 03037 /* For RSIP on wildcard we reset all endpoints */ 03038 if (!strcmp(p->name, p->parent->wcardep)) { 03039 /* Reset all endpoints */ 03040 struct mgcp_endpoint *tmp_ep; 03041 03042 g = p->parent; 03043 tmp_ep = g->endpoints; 03044 while (tmp_ep) { 03045 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/ 03046 if (strcmp(tmp_ep->name, g->wcardep) != 0) { 03047 struct mgcp_subchannel *tmp_sub, *first_sub; 03048 if (option_verbose > 2) { 03049 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name); 03050 } 03051 03052 first_sub = tmp_ep->sub; 03053 tmp_sub = tmp_ep->sub; 03054 while (tmp_sub) { 03055 mgcp_queue_hangup(tmp_sub); 03056 tmp_sub = tmp_sub->next; 03057 if (tmp_sub == first_sub) 03058 break; 03059 } 03060 } 03061 tmp_ep = tmp_ep->next; 03062 } 03063 } else if (sub->owner) { 03064 mgcp_queue_hangup(sub); 03065 } 03066 transmit_response(sub, "200", req, "OK"); 03067 /* We dont send NTFY or AUEP to wildcard ep */ 03068 if (strcmp(p->name, p->parent->wcardep) != 0) { 03069 transmit_notify_request(sub, ""); 03070 /* Audit endpoint. 03071 Idea is to prevent lost lines due to race conditions 03072 */ 03073 transmit_audit_endpoint(p); 03074 } 03075 } 03076 } else if (!strcasecmp(req->verb, "NTFY")) { 03077 /* Acknowledge and be sure we keep looking for the same things */ 03078 transmit_response(sub, "200", req, "OK"); 03079 /* Notified of an event */ 03080 ev = get_header(req, "O"); 03081 s = strchr(ev, '/'); 03082 if (s) ev = s + 1; 03083 if (option_debug) 03084 ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev); 03085 /* Keep looking for events unless this was a hangup */ 03086 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) { 03087 transmit_notify_request(sub, p->curtone); 03088 } 03089 if (!strcasecmp(ev, "hd")) { 03090 p->hookstate = MGCP_OFFHOOK; 03091 sub->cxmode = MGCP_CX_SENDRECV; 03092 handle_hd_hf(sub, ev); 03093 } else if (!strcasecmp(ev, "hf")) { 03094 /* We can assume we are offhook if we received a hookflash */ 03095 /* First let's just do call wait and ignore threeway */ 03096 /* We're currently in charge */ 03097 if (p->hookstate != MGCP_OFFHOOK) { 03098 /* Cisco c7940 sends hf even if the phone is onhook */ 03099 /* Thanks to point on IRC for pointing this out */ 03100 return -1; 03101 } 03102 /* do not let * conference two down channels */ 03103 if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) 03104 return -1; 03105 03106 if (p->callwaiting || p->transfer || p->threewaycalling) { 03107 if (option_verbose > 2) { 03108 ast_verbose(VERBOSE_PREFIX_3 "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name); 03109 } 03110 p->sub = p->sub->next; 03111 03112 /* transfer control to our next subchannel */ 03113 if (!sub->next->owner) { 03114 /* plave the first call on hold and start up a new call */ 03115 sub->cxmode = MGCP_CX_MUTE; 03116 if (option_verbose > 2) { 03117 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03118 } 03119 transmit_modify_request(sub); 03120 if (sub->owner && ast_bridged_channel(sub->owner)) 03121 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03122 sub->next->cxmode = MGCP_CX_RECVONLY; 03123 handle_hd_hf(sub->next, ev); 03124 } else if (sub->owner && sub->next->owner) { 03125 /* We've got two active calls lets decide whether or not to conference or just flip flop */ 03126 if ((!sub->outgoing) && (!sub->next->outgoing)) { 03127 /* We made both calls lets conferenct */ 03128 if (option_verbose > 2) { 03129 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n", 03130 sub->id, sub->next->id, p->name, p->parent->name); 03131 } 03132 sub->cxmode = MGCP_CX_CONF; 03133 sub->next->cxmode = MGCP_CX_CONF; 03134 if (ast_bridged_channel(sub->next->owner)) 03135 ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); 03136 transmit_modify_request(sub); 03137 transmit_modify_request(sub->next); 03138 } else { 03139 /* Let's flipflop between calls */ 03140 /* XXX Need to check for state up ??? */ 03141 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */ 03142 if (option_verbose > 2) { 03143 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 03144 sub->id, sub->next->id, p->name, p->parent->name); 03145 } 03146 sub->cxmode = MGCP_CX_MUTE; 03147 if (option_verbose > 2) { 03148 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); 03149 } 03150 transmit_modify_request(sub); 03151 if (ast_bridged_channel(sub->owner)) 03152 ast_queue_control(sub->owner, AST_CONTROL_HOLD); 03153 03154 if (ast_bridged_channel(sub->next->owner)) 03155 ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); 03156 03157 handle_hd_hf(sub->next, ev); 03158 } 03159 } else { 03160 /* We've most likely lost one of our calls find an active call and bring it up */ 03161 if (sub->owner) { 03162 p->sub = sub; 03163 } else if (sub->next->owner) { 03164 p->sub = sub->next; 03165 } else { 03166 /* We seem to have lost both our calls */ 03167 /* XXX - What do we do now? */ 03168 return -1; 03169 } 03170 if (ast_bridged_channel(p->sub->owner)) 03171 ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); 03172 p->sub->cxmode = MGCP_CX_SENDRECV; 03173 transmit_modify_request(p->sub); 03174 } 03175 } else { 03176 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 03177 p->name, p->parent->name); 03178 } 03179 } else if (!strcasecmp(ev, "hu")) { 03180 p->hookstate = MGCP_ONHOOK; 03181 sub->cxmode = MGCP_CX_RECVONLY; 03182 if (option_debug) 03183 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name); 03184 /* Do we need to send MDCX before a DLCX ? 03185 if (sub->rtp) { 03186 transmit_modify_request(sub); 03187 } 03188 */ 03189 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) { 03190 /* We're allowed to transfer, we have two avtive calls and */ 03191 /* we made at least one of the calls. Let's try and transfer */ 03192 ast_mutex_lock(&p->sub->next->lock); 03193 res = attempt_transfer(p); 03194 if (res < 0) { 03195 if (p->sub->next->owner) { 03196 sub->next->alreadygone = 1; 03197 mgcp_queue_hangup(sub->next); 03198 } 03199 } else if (res) { 03200 ast_log(LOG_WARNING, "Transfer attempt failed\n"); 03201 ast_mutex_unlock(&p->sub->next->lock); 03202 return -1; 03203 } 03204 ast_mutex_unlock(&p->sub->next->lock); 03205 } else { 03206 /* Hangup the current call */ 03207 /* If there is another active call, mgcp_hangup will ring the phone with the other call */ 03208 if (sub->owner) { 03209 sub->alreadygone = 1; 03210 mgcp_queue_hangup(sub); 03211 } else { 03212 /* verbose level check */ 03213 if (option_verbose > 2) { 03214 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n", 03215 p->name, p->parent->name, sub->id); 03216 } 03217 /* Instruct the other side to remove the connection since it apparently * 03218 * still thinks the channel is active. * 03219 * For Cisco IAD2421 /BAK/ */ 03220 transmit_connection_del(sub); 03221 } 03222 } 03223 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) { 03224 p->hidecallerid = 0; 03225 if (p->hascallwaiting && !p->callwaiting) { 03226 if (option_verbose > 2) 03227 ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id); 03228 p->callwaiting = -1; 03229 } 03230 if (has_voicemail(p)) { 03231 if (option_verbose > 2) { 03232 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name); 03233 } 03234 transmit_notify_request(sub, "L/vmwi(+)"); 03235 } else { 03236 if (option_verbose > 2) { 03237 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name); 03238 } 03239 transmit_notify_request(sub, "L/vmwi(-)"); 03240 } 03241 } 03242 } else if ((strlen(ev) == 1) && 03243 (((ev[0] >= '0') && (ev[0] <= '9')) || 03244 ((ev[0] >= 'A') && (ev[0] <= 'D')) || 03245 (ev[0] == '*') || (ev[0] == '#'))) { 03246 f.frametype = AST_FRAME_DTMF; 03247 f.subclass = ev[0]; 03248 f.src = "mgcp"; 03249 if (sub->owner) { 03250 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */ 03251 mgcp_queue_frame(sub, &f); 03252 ast_mutex_lock(&sub->next->lock); 03253 if (sub->next->owner) { 03254 mgcp_queue_frame(sub->next, &f); 03255 } 03256 ast_mutex_unlock(&sub->next->lock); 03257 } 03258 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) { 03259 memset(p->curtone, 0, sizeof(p->curtone)); 03260 } 03261 } else if (!strcasecmp(ev, "T")) { 03262 /* Digit timeout -- unimportant */ 03263 } else if (!strcasecmp(ev, "ping")) { 03264 /* ping -- unimportant */ 03265 } else { 03266 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name); 03267 } 03268 } else { 03269 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, ast_inet_ntoa(sin->sin_addr)); 03270 transmit_response(sub, "510", req, "Unknown verb"); 03271 } 03272 return 0; 03273 }
|
|
||||||||||||||||||||||||
|
Definition at line 2419 of file chan_mgcp.c. References ast_log(), ast_strlen_zero(), ast_verbose(), 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(), free, 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, option_verbose, mgcp_subchannel::owner, mgcp_endpoint::parent, process_sdp(), mgcp_endpoint::rqnt_queue, mgcp_endpoint::rqnt_queue_lock, mgcp_subchannel::rtp, mgcp_endpoint::slowsequence, start_rtp(), mgcp_endpoint::sub, mgcp_subchannel::tmpdest, transmit_connection_del(), transmit_connection_del_w_params(), transmit_modify_with_sdp(), transmit_notify_request(), and VERBOSE_PREFIX_3. Referenced by handle_request(), mgcpsock_read(), and retrans_pkt(). 02421 { 02422 char *c; 02423 struct mgcp_request *req; 02424 struct mgcp_gateway *gw = p->parent; 02425 02426 if (result < 200) { 02427 /* provisional response */ 02428 return; 02429 } 02430 02431 if (p->slowsequence) 02432 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02433 else if (sub) 02434 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident); 02435 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident))) 02436 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident); 02437 02438 if (!req) { 02439 if (option_verbose > 2) { 02440 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n", 02441 gw->name, ident); 02442 } 02443 return; 02444 } 02445 02446 if (p && (result >= 400) && (result <= 599)) { 02447 switch (result) { 02448 case 401: 02449 p->hookstate = MGCP_OFFHOOK; 02450 break; 02451 case 402: 02452 p->hookstate = MGCP_ONHOOK; 02453 break; 02454 case 406: 02455 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident); 02456 break; 02457 case 407: 02458 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident); 02459 break; 02460 } 02461 if (sub) { 02462 if (sub->owner) { 02463 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02464 result, p->name, p->parent->name, sub ? sub->id:-1); 02465 mgcp_queue_hangup(sub); 02466 } 02467 } else { 02468 if (p->sub->next->owner) { 02469 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02470 result, p->name, p->parent->name, sub ? sub->id:-1); 02471 mgcp_queue_hangup(p->sub); 02472 } 02473 02474 if (p->sub->owner) { 02475 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 02476 result, p->name, p->parent->name, sub ? sub->id:-1); 02477 mgcp_queue_hangup(p->sub); 02478 } 02479 02480 dump_cmd_queues(p, NULL); 02481 } 02482 } 02483 02484 if (resp) { 02485 if (req->cmd == MGCP_CMD_CRCX) { 02486 if ((c = get_header(resp, "I"))) { 02487 if (!ast_strlen_zero(c) && sub) { 02488 /* if we are hanging up do not process this conn. */ 02489 if (sub->owner) { 02490 if (!ast_strlen_zero(sub->cxident)) { 02491 if (strcasecmp(c, sub->cxident)) { 02492 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c); 02493 } 02494 } 02495 ast_copy_string(sub->cxident, c, sizeof(sub->cxident)); 02496 if (sub->tmpdest.sin_addr.s_addr) { 02497 transmit_modify_with_sdp(sub, NULL, 0); 02498 } 02499 } else { 02500 /* XXX delete this one 02501 callid and conn id may already be lost. 02502 so the following del conn may have a side effect of 02503 cleaning up the next subchannel */ 02504 transmit_connection_del(sub); 02505 } 02506 } 02507 } 02508 } 02509 02510 if (req->cmd == MGCP_CMD_AUEP) { 02511 /* check stale connection ids */ 02512 if ((c = get_header(resp, "I"))) { 02513 char *v, *n; 02514 int len; 02515 while ((v = get_csv(c, &len, &n))) { 02516 if (len) { 02517 if (strncasecmp(v, p->sub->cxident, len) && 02518 strncasecmp(v, p->sub->next->cxident, len)) { 02519 /* connection id not found. delete it */ 02520 char cxident[80] = ""; 02521 02522 if (len > (sizeof(cxident) - 1)) 02523 len = sizeof(cxident) - 1; 02524 ast_copy_string(cxident, v, len); 02525 if (option_verbose > 2) { 02526 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n", 02527 cxident, p->name, gw->name); 02528 } 02529 transmit_connection_del_w_params(p, NULL, cxident); 02530 } 02531 } 02532 c = n; 02533 } 02534 } 02535 02536 /* Try to determine the hookstate returned from an audit endpoint command */ 02537 if ((c = get_header(resp, "ES"))) { 02538 if (!ast_strlen_zero(c)) { 02539 if (strstr(c, "hu")) { 02540 if (p->hookstate != MGCP_ONHOOK) { 02541 /* XXX cleanup if we think we are offhook XXX */ 02542 if ((p->sub->owner || p->sub->next->owner ) && 02543 p->hookstate == MGCP_OFFHOOK) 02544 mgcp_queue_hangup(sub); 02545 p->hookstate = MGCP_ONHOOK; 02546 02547 /* update the requested events according to the new hookstate */ 02548 transmit_notify_request(p->sub, ""); 02549 02550 /* verbose level check */ 02551 if (option_verbose > 2) { 02552 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name); 02553 } 02554 } 02555 } else if (strstr(c, "hd")) { 02556 if (p->hookstate != MGCP_OFFHOOK) { 02557 p->hookstate = MGCP_OFFHOOK; 02558 02559 /* update the requested events according to the new hookstate */ 02560 transmit_notify_request(p->sub, ""); 02561 02562 /* verbose level check */ 02563 if (option_verbose > 2) { 02564 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name); 02565 } 02566 } 02567 } 02568 } 02569 } 02570 } 02571 02572 if (resp && resp->lines) { 02573 /* do not process sdp if we are hanging up. this may be a late response */ 02574 if (sub && sub->owner) { 02575 if (!sub->rtp) 02576 start_rtp(sub); 02577 if (sub->rtp) 02578 process_sdp(sub, resp); 02579 } 02580 } 02581 } 02582 02583 free(req); 02584 }
|
|
|
Definition at line 453 of file chan_mgcp.c. References ast_app_has_voicemail(), and mgcp_endpoint::mailbox. Referenced by do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), mgcp_hangup(), mgcp_request(), and zt_handle_event(). 00454 { 00455 return ast_app_has_voicemail(p->mailbox, NULL); 00456 }
|
|
||||||||||||||||
|
Definition at line 1956 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, oseq, and mgcp_endpoint::parent. Referenced by reqprep(), and transmit_register(). 01957 { 01958 /* Initialize a response */ 01959 if (req->headers || req->len) { 01960 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 01961 return -1; 01962 } 01963 req->header[req->headers] = req->data + req->len; 01964 /* check if we need brackets around the gw name */ 01965 if (p->parent->isnamedottedip) 01966 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); 01967 else 01968 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); 01969 req->len += strlen(req->header[req->headers]); 01970 if (req->headers < MGCP_MAX_HEADERS) 01971 req->headers++; 01972 else 01973 ast_log(LOG_WARNING, "Out of header space\n"); 01974 return 0; 01975 }
|
|
||||||||||||||||||||
|
Definition at line 1939 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(). 01940 { 01941 /* Initialize a response */ 01942 if (req->headers || req->len) { 01943 ast_log(LOG_WARNING, "Request already initialized?!?\n"); 01944 return -1; 01945 } 01946 req->header[req->headers] = req->data + req->len; 01947 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest); 01948 req->len += strlen(req->header[req->headers]); 01949 if (req->headers < MGCP_MAX_HEADERS) 01950 req->headers++; 01951 else 01952 ast_log(LOG_WARNING, "Out of header space\n"); 01953 return 0; 01954 }
|
|
|
|
||||||||||||||||
|
Definition at line 1069 of file chan_mgcp.c. References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_gateway::endpoints, gateways, mgcpdebug, mgcp_endpoint::name, mgcp_gateway::name, mgcp_gateway::next, mgcp_endpoint::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, and transmit_audit_endpoint(). 01070 { 01071 struct mgcp_gateway *g; 01072 struct mgcp_endpoint *e; 01073 int found = 0; 01074 char *ename,*gname, *c; 01075 01076 if (!mgcpdebug) { 01077 return RESULT_SHOWUSAGE; 01078 } 01079 if (argc != 4) 01080 return RESULT_SHOWUSAGE; 01081 /* split the name into parts by null */ 01082 ename = argv[3]; 01083 gname = ename; 01084 while (*gname) { 01085 if (*gname == '@') { 01086 *gname = 0; 01087 gname++; 01088 break; 01089 } 01090 gname++; 01091 } 01092 if (gname[0] == '[') 01093 gname++; 01094 if ((c = strrchr(gname, ']'))) 01095 *c = '\0'; 01096 ast_mutex_lock(&gatelock); 01097 g = gateways; 01098 while(g) { 01099 if (!strcasecmp(g->name, gname)) { 01100 e = g->endpoints; 01101 while(e) { 01102 if (!strcasecmp(e->name, ename)) { 01103 found = 1; 01104 transmit_audit_endpoint(e); 01105 break; 01106 } 01107 e = e->next; 01108 } 01109 if (found) { 01110 break; 01111 } 01112 } 01113 g = g->next; 01114 } 01115 if (!found) { 01116 ast_cli(fd, " << Could not find endpoint >> "); 01117 } 01118 ast_mutex_unlock(&gatelock); 01119 return RESULT_SUCCESS; 01120 }
|
|
||||||||||||||||
|
Definition at line 822 of file chan_mgcp.c. References ast_channel::_state, AST_CONTROL_RINGING, 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_verbose(), mgcp_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, mgcp_subchannel::cxident, mgcp_subchannel::cxmode, mgcp_endpoint::hookstate, mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, MGCP_CX_RECVONLY, MGCP_CX_SENDRECV, MGCP_OFFHOOK, MGCP_ONHOOK, mgcpdebug, 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, ast_channel::varshead, and VERBOSE_PREFIX_3. 00823 { 00824 int res; 00825 struct mgcp_endpoint *p; 00826 struct mgcp_subchannel *sub; 00827 char tone[50] = ""; 00828 const char *distinctive_ring = NULL; 00829 struct varshead *headp; 00830 struct ast_var_t *current; 00831 00832 if (mgcpdebug) { 00833 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name); 00834 } 00835 sub = ast->tech_pvt; 00836 p = sub->parent; 00837 headp = &ast->varshead; 00838 AST_LIST_TRAVERSE(headp,current,entries) { 00839 /* Check whether there is an ALERT_INFO variable */ 00840 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) { 00841 distinctive_ring = ast_var_value(current); 00842 } 00843 } 00844 00845 ast_mutex_lock(&sub->lock); 00846 switch (p->hookstate) { 00847 case MGCP_OFFHOOK: 00848 if (!ast_strlen_zero(distinctive_ring)) { 00849 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring); 00850 if (mgcpdebug) { 00851 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone); 00852 } 00853 } else { 00854 snprintf(tone, sizeof(tone), "L/wt"); 00855 if (mgcpdebug) { 00856 ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone); 00857 } 00858 } 00859 break; 00860 case MGCP_ONHOOK: 00861 default: 00862 if (!ast_strlen_zero(distinctive_ring)) { 00863 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring); 00864 if (mgcpdebug) { 00865 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone); 00866 } 00867 } else { 00868 snprintf(tone, sizeof(tone), "L/rg"); 00869 if (mgcpdebug) { 00870 ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n"); 00871 } 00872 } 00873 break; 00874 } 00875 00876 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00877 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name); 00878 ast_mutex_unlock(&sub->lock); 00879 return -1; 00880 } 00881 00882 res = 0; 00883 sub->outgoing = 1; 00884 sub->cxmode = MGCP_CX_RECVONLY; 00885 if (p->type == TYPE_LINE) { 00886 if (!sub->rtp) { 00887 start_rtp(sub); 00888 } else { 00889 transmit_modify_request(sub); 00890 } 00891 00892 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00893 /* try to prevent a callwait from disturbing the other connection */ 00894 sub->next->cxmode = MGCP_CX_RECVONLY; 00895 transmit_modify_request(sub->next); 00896 } 00897 00898 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name); 00899 ast_setstate(ast, AST_STATE_RINGING); 00900 00901 if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) { 00902 /* Put the connection back in sendrecv */ 00903 sub->next->cxmode = MGCP_CX_SENDRECV; 00904 transmit_modify_request(sub->next); 00905 } 00906 } else { 00907 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n"); 00908 res = -1; 00909 } 00910 ast_mutex_unlock(&sub->lock); 00911 ast_queue_control(ast, AST_CONTROL_RINGING); 00912 return res; 00913 }
|
|
|
mgcp_devicestate: channel callback for device status monitoring
Definition at line 1309 of file chan_mgcp.c. References AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, mgcp_gateway::endpoints, error(), gateways, mgcp_endpoint::name, mgcp_gateway::name, mgcp_endpoint::next, and mgcp_gateway::next. 01310 { 01311 struct mgcp_gateway *g; 01312 struct mgcp_endpoint *e = NULL; 01313 char *tmp, *endpt, *gw; 01314 int ret = AST_DEVICE_INVALID; 01315 01316 endpt = ast_strdupa(data); 01317 if ((tmp = strchr(endpt, '@'))) { 01318 *tmp++ = '\0'; 01319 gw = tmp; 01320 } else 01321 goto error; 01322 01323 ast_mutex_lock(&gatelock); 01324 g = gateways; 01325 while (g) { 01326 if (strcasecmp(g->name, gw) == 0) { 01327 e = g->endpoints; 01328 break; 01329 } 01330 g = g->next; 01331 } 01332 01333 if (!e) 01334 goto error; 01335 01336 while (e) { 01337 if (strcasecmp(e->name, endpt) == 0) 01338 break; 01339 e = e->next; 01340 } 01341 01342 if (!e) 01343 goto error; 01344 01345 /* 01346 * As long as the gateway/endpoint is valid, we'll 01347 * assume that the device is available and its state 01348 * can be tracked. 01349 */ 01350 ret = AST_DEVICE_UNKNOWN; 01351 01352 error: 01353 ast_mutex_unlock(&gatelock); 01354 return ret; 01355 }
|
|
||||||||||||||||
|
Definition at line 1122 of file chan_mgcp.c. References ast_cli(), mgcpdebug, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 01123 { 01124 if (argc != 3) 01125 return RESULT_SHOWUSAGE; 01126 mgcpdebug = 1; 01127 ast_cli(fd, "MGCP Debugging Enabled\n"); 01128 return RESULT_SUCCESS; 01129 }
|
|
|
mgcp_do_reload: Reload module
Definition at line 4291 of file chan_mgcp.c. References reload_config(). Referenced by do_monitor(). 04292 { 04293 reload_config(); 04294 return 0; 04295 }
|
|
||||||||||||
|
Definition at line 1263 of file chan_mgcp.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mgcp_subchannel::lock, LOG_NOTICE, LOG_WARNING, mgcp_subchannel::owner, and ast_channel::tech_pvt. 01264 { 01265 struct mgcp_subchannel *sub = newchan->tech_pvt; 01266 01267 ast_mutex_lock(&sub->lock); 01268 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name); 01269 if (sub->owner != oldchan) { 01270 ast_mutex_unlock(&sub->lock); 01271 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner); 01272 return -1; 01273 } 01274 sub->owner = newchan; 01275 ast_mutex_unlock(&sub->lock); 01276 return 0; 01277 }
|
|
||||||||||||
|
Definition at line 3947 of file chan_mgcp.c. References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, mgcp_endpoint::canreinvite, mgcp_subchannel::parent, mgcp_subchannel::rtp, and ast_channel::tech_pvt. 03948 { 03949 struct mgcp_subchannel *sub = NULL; 03950 03951 if (!(sub = chan->tech_pvt) || !(sub->rtp)) 03952 return AST_RTP_GET_FAILED; 03953 03954 *rtp = sub->rtp; 03955 03956 if (sub->parent->canreinvite) 03957 return AST_RTP_TRY_NATIVE; 03958 else 03959 return AST_RTP_TRY_PARTIAL; 03960 }
|
|