2 * Asterisk -- A telephony toolkit for Linux.
4 * Implementation of Media Gateway Control Protocol
6 * Copyright (C) 1999-2005, Digium, Inc.
8 * Mark Spencer <markster@digium.com>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
15 * -- add distinctive ring signalling (part of RFC 3660)
19 -- add support for the wildcard endpoint
20 -- seteable wildcard with wcardep on mgcp.conf
21 -- added package indicator on RQNT, i.e "dl" --> "L/dl"
22 -- removed MDCX just before DLCX, do we need this ?
26 -- reload for wildcard endpoint probably buggy
27 -- when hf is notified we're sending CRCX after MDCX, without waiting for
28 OK on the MDCX which fails on Cisco IAD 24XX
29 -- honour codec order, by now the lowest codec number in "allow" is the prefered
33 -- packet retransmit mechanism (simplistic)
34 -- per endpoint/subchannel mgcp command sequencing.
35 -- better transaction handling
36 -- fixed some mem leaks
37 -- run-time configuration reload
38 -- distinguish CA and GW default MGCP ports
39 -- prevent clipping of DTMF tones in an established call
40 -- fixed a few crash scenarios in 3-way
41 -- fix for a few cases where asterisk and MGW end-up in conflicting ep states
42 -- enclose numeric IP in [] for outgoing requests
47 -- responseAck support
48 -- enhance retransmit mechanism (RTO calc. etc.)
49 -- embedded command support
53 -- fixed reload_config() / do_monitor to stay responsive during reloads
58 #include <asterisk/lock.h>
59 #include <asterisk/channel.h>
60 #include <asterisk/config.h>
61 #include <asterisk/logger.h>
62 #include <asterisk/module.h>
63 #include <asterisk/pbx.h>
64 #include <asterisk/options.h>
65 #include <asterisk/lock.h>
66 #include <asterisk/sched.h>
67 #include <asterisk/io.h>
68 #include <asterisk/rtp.h>
69 #include <asterisk/acl.h>
70 #include <asterisk/callerid.h>
71 #include <asterisk/cli.h>
72 #include <asterisk/say.h>
73 #include <asterisk/cdr.h>
74 #include <asterisk/astdb.h>
75 #include <asterisk/features.h>
76 #include <asterisk/app.h>
77 #include <asterisk/musiconhold.h>
78 #include <asterisk/utils.h>
79 #include <asterisk/causes.h>
80 #include <sys/socket.h>
81 #include <sys/ioctl.h>
88 #include <arpa/inet.h>
89 #include <sys/signal.h>
91 #include <netinet/in_systm.h>
92 #include <netinet/ip.h>
94 #include <asterisk/dsp.h>
98 #define IPTOS_MINCOST 0x02
102 * Define to work around buggy dlink MGCP phone firmware which
103 * appears not to know that "rt" is part of the "G" package.
105 /* #define DLINK_BUGGY_FIRMWARE */
108 #define DEFAULT_EXPIRY 120
109 #define MAX_EXPIRY 3600
110 #define CANREINVITE 1
113 #define INADDR_NONE (in_addr_t)(-1)
116 static const char desc[] = "Media Gateway Control Protocol (MGCP)";
117 static const char type[] = "MGCP";
118 static const char tdesc[] = "Media Gateway Control Protocol (MGCP)";
119 static const char config[] = "mgcp.conf";
121 #define MGCP_DTMF_RFC2833 (1 << 0)
122 #define MGCP_DTMF_INBAND (1 << 1)
123 #define MGCP_DTMF_HYBRID (1 << 2)
125 #define DEFAULT_MGCP_GW_PORT 2427 /* From RFC 2705 */
126 #define DEFAULT_MGCP_CA_PORT 2727 /* From RFC 2705 */
127 #define MGCP_MAX_PACKET 1500 /* Also from RFC 2543, should sub headers tho */
128 #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */
129 #define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
131 /* MGCP rtp stream modes */
132 #define MGCP_CX_SENDONLY 0
133 #define MGCP_CX_RECVONLY 1
134 #define MGCP_CX_SENDRECV 2
135 #define MGCP_CX_CONF 3
136 #define MGCP_CX_CONFERENCE 3
137 #define MGCP_CX_MUTE 4
138 #define MGCP_CX_INACTIVE 4
140 static char *mgcp_cxmodes[] = {
148 /* SC: MGCP commands */
149 #define MGCP_CMD_EPCF 0
150 #define MGCP_CMD_CRCX 1
151 #define MGCP_CMD_MDCX 2
152 #define MGCP_CMD_DLCX 3
153 #define MGCP_CMD_RQNT 4
154 #define MGCP_CMD_NTFY 5
155 #define MGCP_CMD_AUEP 6
156 #define MGCP_CMD_AUCX 7
157 #define MGCP_CMD_RSIP 8
159 static char context[AST_MAX_EXTENSION] = "default";
161 static char language[MAX_LANGUAGE] = "";
162 static char musicclass[MAX_LANGUAGE] = "";
163 static char cid_num[AST_MAX_EXTENSION] = "";
164 static char cid_name[AST_MAX_EXTENSION] = "";
166 static int dtmfmode = 0;
169 /* Not used. Dosn't hurt for us to always send cid */
170 /* to the mgcp box. */
171 /*static int use_callerid = 1;*/
172 /*static int cur_signalling = -1;*/
174 /*static unsigned int cur_group = 0;*/
175 static ast_group_t cur_callergroup = 0;
176 static ast_group_t cur_pickupgroup = 0;
178 /* XXX Is this needed? */
179 /* Doesn't look like the dsp stuff for */
180 /* dtmfmode is actually hooked up. */
181 /*static int relaxdtmf = 0;*/
185 static int immediate = 0;
187 static int callwaiting = 0;
189 /* Not used. Dosn't hurt for us to always send cid */
190 /* to the mgcp box. */
191 /*static int callwaitingcallerid = 0;*/
193 /*static int hidecallerid = 0;*/
195 static int callreturn = 0;
197 static int slowsequence = 0;
199 static int threewaycalling = 0;
201 /* This is for flashhook transfers */
202 static int transfer = 0;
204 static int cancallforward = 0;
206 static int singlepath = 0;
208 static int canreinvite = CANREINVITE;
210 /*static int busycount = 3;*/
212 /*static int callprogress = 0;*/
214 static char accountcode[20] = "";
216 static char mailbox[AST_MAX_EXTENSION];
218 static int amaflags = 0;
222 static int usecnt =0;
223 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
224 /* SC: transaction id should always be positive */
225 static unsigned int oseq;
227 /* Wait up to 16 seconds for first digit (FXO logic) */
228 static int firstdigittimeout = 16000;
230 /* How long to wait for following digits (FXO logic) */
231 static int gendigittimeout = 8000;
233 /* How long to wait for an extra digit, if there is an ambiguous match */
234 static int matchdigittimeout = 3000;
236 /* Protect the monitoring thread, so only one process can kill or start it, and not
237 when it's doing something critical. */
238 AST_MUTEX_DEFINE_STATIC(netlock);
240 AST_MUTEX_DEFINE_STATIC(monlock);
242 /* This is the thread for the monitor which checks for input on the channels
243 which are not currently in use. */
244 static pthread_t monitor_thread = AST_PTHREADT_NULL;
246 static int restart_monitor(void);
248 static int capability = AST_FORMAT_ULAW;
249 static int nonCodecCapability = AST_RTP_DTMF;
251 static char ourhost[256];
252 static struct in_addr __ourip;
255 static int mgcpdebug = 0;
257 static struct sched_context *sched;
258 static struct io_context *io;
259 /* The private structures of the mgcp channels are linked for
260 selecting outgoing channels */
262 #define MGCP_MAX_HEADERS 64
263 #define MGCP_MAX_LINES 64
265 struct mgcp_request {
271 int headers; /* MGCP Headers */
272 char *header[MGCP_MAX_HEADERS];
273 int lines; /* SDP Content */
274 char *line[MGCP_MAX_LINES];
275 char data[MGCP_MAX_PACKET];
276 int cmd; /* SC: int version of verb = command */
277 unsigned int trid; /* SC: int version of identifier = transaction id */
278 struct mgcp_request *next; /* SC: next in the queue */
282 static struct mgcp_pkt {
284 struct mgcp_endpoint *owner;
286 char data[MGCP_MAX_PACKET];
287 struct mgcp_pkt *next;
291 /* MGCP message for queuing up */
292 struct mgcp_message {
293 struct mgcp_endpoint *owner_ep;
294 struct mgcp_subchannel *owner_sub;
296 unsigned long expire;
299 struct mgcp_message *next;
300 unsigned char buf[0];
303 #define RESPONSE_TIMEOUT 30 /* in seconds */
305 struct mgcp_response {
309 struct mgcp_response *next;
310 unsigned char buf[0];
318 struct mgcp_subchannel {
319 /* SC: subchannel magic string.
320 Needed to prove that any subchannel pointer passed by asterisk
321 really points to a valid subchannel memory area.
322 Ugly.. But serves the purpose for the time being.
324 #define MGCP_SUBCHANNEL_MAGIC "!978!"
328 struct ast_channel *owner;
329 struct mgcp_endpoint *parent;
331 struct sockaddr_in tmpdest;
332 char txident[80]; /* FIXME SC: txident is replaced by rqnt_ident in endpoint.
333 This should be obsoleted */
341 struct mgcp_request *cx_queue; /* SC: pending CX commands */
342 ast_mutex_t cx_queue_lock; /* SC: CX queue lock */
344 int iseq; /* Not used? RTP? */
349 struct mgcp_message *msgs;
351 struct mgcp_subchannel *next; /* for out circular linked list */
354 #define MGCP_ONHOOK 1
355 #define MGCP_OFFHOOK 2
360 struct mgcp_endpoint {
363 struct mgcp_subchannel *sub; /* pointer to our current connection, channel and stuff */
364 char accountcode[80];
365 char exten[AST_MAX_EXTENSION]; /* Extention where to start */
366 char context[AST_MAX_EXTENSION];
367 char language[MAX_LANGUAGE];
368 char cid_num[AST_MAX_EXTENSION]; /* Caller*ID */
369 char cid_name[AST_MAX_EXTENSION]; /* Caller*ID */
370 char lastcallerid[AST_MAX_EXTENSION]; /* Last Caller*ID */
371 char call_forward[AST_MAX_EXTENSION]; /* Last Caller*ID */
372 char mailbox[AST_MAX_EXTENSION];
373 char musicclass[MAX_LANGUAGE];
374 char curtone[80]; /* Current tone */
375 ast_group_t callgroup;
376 ast_group_t pickupgroup;
384 int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
390 int slowsequence; /* MS: Sequence the endpoint as a whole */
392 int iseq; /* Not used? */
393 int lastout; /* tracking this on the subchannels. Is it needed here? */
394 int needdestroy; /* Not used? */
396 int nonCodecCapability;
398 int msgstate; /* voicemail message state */
402 char rqnt_ident[80]; /* SC: request identifier */
403 struct mgcp_request *rqnt_queue; /* SC: pending RQNT commands */
404 ast_mutex_t rqnt_queue_lock;
405 struct mgcp_request *cmd_queue; /* SC: pending commands other than RQNT */
406 ast_mutex_t cmd_queue_lock;
407 int delme; /* SC: needed for reload */
408 int needaudit; /* SC: needed for reload */
409 struct ast_dsp *dsp; /* XXX Should there be a dsp/subchannel? XXX */
410 /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
411 /* struct ast_channel *owner; */
412 /* struct ast_rtp *rtp; */
413 /* struct sockaddr_in tmpdest; */
414 /* message go the the endpoint and not the channel so they stay here */
415 struct mgcp_endpoint *next;
416 struct mgcp_gateway *parent;
419 static struct mgcp_gateway {
420 /* A gateway containing one or more endpoints */
422 int isnamedottedip; /* SC: is the name FQDN or dotted ip */
423 struct sockaddr_in addr;
424 struct sockaddr_in defaddr;
425 struct in_addr ourip;
427 int expire; /* XXX Should we ever expire dynamic registrations? XXX */
428 struct mgcp_endpoint *endpoints;
435 /* JS: Wildcard endpoint name */
437 struct mgcp_message *msgs; /* SC: gw msg queue */
438 ast_mutex_t msgs_lock; /* SC: queue lock */
439 int retransid; /* SC: retrans timer id */
440 int delme; /* SC: needed for reload */
441 struct mgcp_response *responses;
442 struct mgcp_gateway *next;
445 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
446 static int mgcp_reloading = 0;
448 AST_MUTEX_DEFINE_STATIC(gatelock);
450 static int mgcpsock = -1;
452 static struct sockaddr_in bindaddr;
454 static struct ast_frame *mgcp_read(struct ast_channel *ast);
455 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
456 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
457 static int transmit_modify_request(struct mgcp_subchannel *sub);
458 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
459 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
460 static int transmit_connection_del(struct mgcp_subchannel *sub);
461 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
462 static void start_rtp(struct mgcp_subchannel *sub);
463 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
464 int result, unsigned int ident, struct mgcp_request *resp);
465 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
466 static int mgcp_do_reload(void);
467 static int mgcp_reload(int fd, int argc, char *argv[]);
469 static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause);
470 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
471 static int mgcp_hangup(struct ast_channel *ast);
472 static int mgcp_answer(struct ast_channel *ast);
473 static struct ast_frame *mgcp_read(struct ast_channel *ast);
474 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
475 static int mgcp_indicate(struct ast_channel *ast, int ind);
476 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
477 static int mgcp_senddigit(struct ast_channel *ast, char digit);
479 static const struct ast_channel_tech mgcp_tech = {
481 .description = tdesc,
482 .capabilities = AST_FORMAT_ULAW,
483 .properties = AST_CHAN_TP_WANTSJITTER,
484 .requester = mgcp_request,
486 .hangup = mgcp_hangup,
487 .answer = mgcp_answer,
490 .indicate = mgcp_indicate,
492 .send_digit = mgcp_senddigit,
493 .bridge = ast_rtp_bridge,
496 static int has_voicemail(struct mgcp_endpoint *p)
498 return ast_app_has_voicemail(p->mailbox, NULL);
501 static int unalloc_sub(struct mgcp_subchannel *sub)
503 struct mgcp_endpoint *p = sub->parent;
505 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
508 ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
511 if (strlen(sub->cxident)) {
512 transmit_connection_del(sub);
514 sub->cxident[0] = '\0';
515 sub->callid[0] = '\0';
516 sub->cxmode = MGCP_CX_INACTIVE;
518 sub->alreadygone = 0;
519 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
521 ast_rtp_destroy(sub->rtp);
524 dump_cmd_queues(NULL, sub); /* SC */
528 /* SC: modified for new transport mechanism */
529 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
532 if (gw->addr.sin_addr.s_addr)
533 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
535 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
537 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
542 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
544 struct mgcp_endpoint *p = sub->parent;
546 char iabuf[INET_ADDRSTRLEN];
548 ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
550 res = __mgcp_xmit(p->parent, resp->buf, resp->len);
556 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
558 struct mgcp_endpoint *p = sub->parent;
560 char iabuf[INET_ADDRSTRLEN];
562 ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
564 res = __mgcp_xmit(p->parent, req->data, req->len);
570 /* SC: modified for new transport framework */
571 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
573 struct mgcp_message *cur, *q = NULL, *w, *prev;
575 ast_mutex_lock(&gw->msgs_lock);
576 prev = NULL, cur = gw->msgs;
578 if (!p || cur->owner_ep == p) {
580 prev->next = cur->next;
582 gw->msgs = cur->next;
584 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
585 gw->name, cur->seqno);
596 prev = cur, cur=cur->next;
599 ast_mutex_unlock(&gw->msgs_lock);
608 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
612 if (!ast_mutex_trylock(&sub->owner->lock)) {
613 ast_queue_frame(sub->owner, f);
614 ast_mutex_unlock(&sub->owner->lock);
617 ast_mutex_unlock(&sub->lock);
619 ast_mutex_lock(&sub->lock);
626 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
630 if (!ast_mutex_trylock(&sub->owner->lock)) {
631 ast_queue_hangup(sub->owner);
632 ast_mutex_unlock(&sub->owner->lock);
635 ast_mutex_unlock(&sub->lock);
637 ast_mutex_lock(&sub->lock);
644 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
646 struct ast_frame f = { AST_FRAME_CONTROL, };
647 f.subclass = control;
648 return mgcp_queue_frame(sub, &f);
651 static int retrans_pkt(void *data)
653 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
654 struct mgcp_message *cur, *exq = NULL, *w, *prev;
659 if (gettimeofday(&tv, NULL) < 0) {
660 /* This shouldn't ever happen, but let's be sure */
661 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
665 t = tv.tv_sec * 1000 + tv.tv_usec / 1000;
667 /* find out expired msgs */
668 ast_mutex_lock(&gw->msgs_lock);
670 prev = NULL, cur = gw->msgs;
672 if (cur->retrans < MAX_RETRANS) {
675 ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
676 cur->retrans, cur->seqno, gw->name);
678 __mgcp_xmit(gw, cur->buf, cur->len);
684 prev->next = cur->next;
686 gw->msgs = cur->next;
688 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",
689 cur->seqno, gw->name);
709 ast_mutex_unlock(&gw->msgs_lock);
713 /* time-out transaction */
714 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
722 /* SC: modified for the new transaction mechanism */
723 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
724 unsigned char *data, int len, unsigned int seqno)
726 struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
727 struct mgcp_message *cur;
728 struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
739 if (gw->messagepending && (gw->lastouttime + 20 < t)) {
740 ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d, lastouttime: %ld, now: %ld. Dumping pending queue\n",
741 gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
742 dump_queue(sub->parent);
745 msg->owner_sub = sub;
751 memcpy(msg->buf, data, msg->len);
753 ast_mutex_lock(&gw->msgs_lock);
763 if (gettimeofday(&tv, NULL) < 0) {
764 /* This shouldn't ever happen, but let's be sure */
765 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
767 msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
769 if (gw->retransid == -1)
770 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
772 ast_mutex_unlock(&gw->msgs_lock);
774 if (!gw->messagepending) {
775 gw->messagepending = 1;
779 __mgcp_xmit(gw, msg->buf, msg->len);
780 /* XXX Should schedule retransmission XXX */
783 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
788 /* SC: modified for new transport */
789 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
790 struct mgcp_request *req, unsigned int seqno)
793 struct mgcp_request **queue, *q, *r, *t;
794 char iabuf[INET_ADDRSTRLEN];
797 ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
798 if (p->slowsequence) {
799 queue = &p->cmd_queue;
800 l = &p->cmd_queue_lock;
805 queue = &sub->cx_queue;
806 l = &sub->cx_queue_lock;
809 /* delete pending cx cmds */
820 queue = &sub->cx_queue;
821 l = &sub->cx_queue_lock;
826 queue = &p->rqnt_queue;
827 l = &p->rqnt_queue_lock;
832 queue = &p->cmd_queue;
833 l = &p->cmd_queue_lock;
839 r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
841 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
845 memcpy(r, req, sizeof(struct mgcp_request));
849 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
850 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
853 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
856 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
857 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
861 /* XXX SC: find tail. We could also keep tail in the data struct for faster access */
862 for (t = *queue; t && t->next; t = t->next);
875 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
878 struct mgcp_endpoint *p;
879 struct mgcp_subchannel *sub;
881 char *distinctive_ring = NULL;
882 struct varshead *headp;
883 struct ast_var_t *current;
886 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
890 headp = &ast->varshead;
891 AST_LIST_TRAVERSE(headp,current,entries) {
892 /* Check whether there is an ALERT_INFO variable */
893 if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {
894 distinctive_ring = ast_var_value(current);
898 ast_mutex_lock(&sub->lock);
899 switch (p->hookstate) {
901 if (distinctive_ring && !ast_strlen_zero(distinctive_ring)) {
902 snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
904 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);
907 snprintf(tone, sizeof(tone), "L/wt");
909 ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);
915 if (distinctive_ring && !ast_strlen_zero(distinctive_ring)) {
916 snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
918 ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);
921 snprintf(tone, sizeof(tone), "L/rg");
923 ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");
929 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
930 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
931 ast_mutex_unlock(&sub->lock);
937 sub->cxmode = MGCP_CX_RECVONLY;
938 if (p->type == TYPE_LINE) {
942 transmit_modify_request(sub);
945 if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
946 /* try to prevent a callwait from disturbing the other connection */
947 sub->next->cxmode = MGCP_CX_RECVONLY;
948 transmit_modify_request(sub->next);
951 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
952 ast_setstate(ast, AST_STATE_RINGING);
954 if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
955 /* Put the connection back in sendrecv */
956 sub->next->cxmode = MGCP_CX_SENDRECV;
957 transmit_modify_request(sub->next);
960 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
963 ast_mutex_unlock(&sub->lock);
964 ast_queue_control(ast, AST_CONTROL_RINGING);
968 static int mgcp_hangup(struct ast_channel *ast)
970 struct mgcp_subchannel *sub = ast->tech_pvt;
971 struct mgcp_endpoint *p = sub->parent;
974 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
976 if (!ast->tech_pvt) {
977 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
980 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
981 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
984 ast_mutex_lock(&sub->lock);
986 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
989 if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
990 /* SC: check whether other channel is active. */
991 if (!sub->next->owner) {
992 if (p->dtmfmode & MGCP_DTMF_HYBRID)
993 p->dtmfmode &= ~MGCP_DTMF_INBAND;
995 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
997 ast_dsp_free(p->dsp);
1003 if (strlen(sub->cxident)) {
1004 transmit_connection_del(sub);
1006 sub->cxident[0] = '\0';
1007 if ((sub == p->sub) && sub->next->owner) {
1008 if (p->hookstate == MGCP_OFFHOOK) {
1009 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
1010 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);
1013 /* set our other connection as the primary and swith over to it */
1015 p->sub->cxmode = MGCP_CX_RECVONLY;
1016 transmit_modify_request(p->sub);
1017 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
1018 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);
1022 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
1023 transmit_notify_request(sub, "L/v");
1024 } else if (p->hookstate == MGCP_OFFHOOK) {
1025 transmit_notify_request(sub, "L/ro");
1027 transmit_notify_request(sub, "");
1030 ast->tech_pvt = NULL;
1031 sub->alreadygone = 0;
1033 sub->cxmode = MGCP_CX_INACTIVE;
1034 sub->callid[0] = '\0';
1035 /* Reset temporary destination */
1036 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1038 ast_rtp_destroy(sub->rtp);
1042 /* SC: Decrement use count */
1043 ast_mutex_lock(&usecnt_lock);
1045 ast_mutex_unlock(&usecnt_lock);
1046 ast_update_use_count();
1047 /* SC: Decrement use count */
1049 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
1050 p->hidecallerid = 0;
1051 if (has_voicemail(p)) {
1053 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
1054 ast->name, p->name, p->parent->name);
1056 transmit_notify_request(sub, "L/vmwi(+)");
1059 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
1060 ast->name, p->name, p->parent->name);
1062 transmit_notify_request(sub, "L/vmwi(-)");
1065 ast_mutex_unlock(&sub->lock);
1069 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
1071 struct mgcp_gateway *g;
1072 struct mgcp_endpoint *e;
1073 int hasendpoints = 0;
1074 char iabuf[INET_ADDRSTRLEN];
1077 return RESULT_SHOWUSAGE;
1078 ast_mutex_lock(&gatelock);
1082 ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), g->addr.sin_addr) : ast_inet_ntoa(iabuf, sizeof(iabuf), g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
1084 /* JS: Don't show wilcard endpoint */
1085 if (strcmp(e->name, g->wcardep) !=0)
1086 ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
1090 if (!hasendpoints) {
1091 ast_cli(fd, " << No Endpoints Defined >> ");
1095 ast_mutex_unlock(&gatelock);
1096 return RESULT_SUCCESS;
1099 static char show_endpoints_usage[] =
1100 "Usage: mgcp show endpoints\n"
1101 " Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
1103 static struct ast_cli_entry cli_show_endpoints =
1104 { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage };
1106 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
1108 struct mgcp_gateway *g;
1109 struct mgcp_endpoint *e;
1111 char *ename,*gname, *c;
1114 return RESULT_SHOWUSAGE;
1117 return RESULT_SHOWUSAGE;
1118 /* split the name into parts by null */
1122 if (*gname == '@') {
1129 if (gname[0] == '[')
1131 if ((c = strrchr(gname, ']')))
1133 ast_mutex_lock(&gatelock);
1136 if (!strcasecmp(g->name, gname)) {
1139 if (!strcasecmp(e->name, ename)) {
1141 transmit_audit_endpoint(e);
1153 ast_cli(fd, " << Could not find endpoint >> ");
1155 ast_mutex_unlock(&gatelock);
1156 return RESULT_SUCCESS;
1159 static char audit_endpoint_usage[] =
1160 "Usage: mgcp audit endpoint <endpointid>\n"
1161 " Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
1162 " mgcp debug MUST be on to see the results of this command.\n";
1164 static struct ast_cli_entry cli_audit_endpoint =
1165 { { "mgcp", "audit", "endpoint", NULL }, mgcp_audit_endpoint, "Audit specified MGCP endpoint", audit_endpoint_usage };
1167 static int mgcp_answer(struct ast_channel *ast)
1170 struct mgcp_subchannel *sub = ast->tech_pvt;
1171 struct mgcp_endpoint *p = sub->parent;
1173 ast_mutex_lock(&sub->lock);
1174 sub->cxmode = MGCP_CX_SENDRECV;
1178 transmit_modify_request(sub);
1180 /* SC: verbose level check */
1181 if (option_verbose > 2) {
1182 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n",
1183 ast->name, p->name, p->parent->name, sub->id);
1185 if (ast->_state != AST_STATE_UP) {
1186 ast_setstate(ast, AST_STATE_UP);
1188 ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
1189 transmit_notify_request(sub, "");
1190 transmit_modify_request(sub);
1192 ast_mutex_unlock(&sub->lock);
1196 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
1198 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
1199 struct ast_frame *f;
1200 static struct ast_frame null_frame = { AST_FRAME_NULL, };
1202 f = ast_rtp_read(sub->rtp);
1203 /* Don't send RFC2833 if we're not supposed to */
1204 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
1207 /* We already hold the channel lock */
1208 if (f->frametype == AST_FRAME_VOICE) {
1209 if (f->subclass != sub->owner->nativeformats) {
1210 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1211 sub->owner->nativeformats = f->subclass;
1212 ast_set_read_format(sub->owner, sub->owner->readformat);
1213 ast_set_write_format(sub->owner, sub->owner->writeformat);
1215 /* Courtesy fearnor aka alex@pilosoft.com */
1216 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
1218 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1220 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1228 static struct ast_frame *mgcp_read(struct ast_channel *ast)
1230 struct ast_frame *f;
1231 struct mgcp_subchannel *sub = ast->tech_pvt;
1232 ast_mutex_lock(&sub->lock);
1233 f = mgcp_rtp_read(sub);
1234 ast_mutex_unlock(&sub->lock);
1238 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
1240 struct mgcp_subchannel *sub = ast->tech_pvt;
1242 if (frame->frametype != AST_FRAME_VOICE) {
1243 if (frame->frametype == AST_FRAME_IMAGE)
1246 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
1250 if (!(frame->subclass & ast->nativeformats)) {
1251 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
1252 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
1257 ast_mutex_lock(&sub->lock);
1258 if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
1260 res = ast_rtp_write(sub->rtp, frame);
1263 ast_mutex_unlock(&sub->lock);
1268 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1270 struct mgcp_subchannel *sub = newchan->tech_pvt;
1272 ast_mutex_lock(&sub->lock);
1273 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
1274 if (sub->owner != oldchan) {
1275 ast_mutex_unlock(&sub->lock);
1276 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1279 sub->owner = newchan;
1280 ast_mutex_unlock(&sub->lock);
1284 static int mgcp_senddigit(struct ast_channel *ast, char digit)
1286 struct mgcp_subchannel *sub = ast->tech_pvt;
1293 ast_mutex_lock(&sub->lock);
1294 transmit_notify_request(sub, tmp);
1295 ast_mutex_unlock(&sub->lock);
1299 static char *control2str(int ind) {
1301 case AST_CONTROL_HANGUP:
1302 return "Other end has hungup";
1303 case AST_CONTROL_RING:
1304 return "Local ring";
1305 case AST_CONTROL_RINGING:
1306 return "Remote end is ringing";
1307 case AST_CONTROL_ANSWER:
1308 return "Remote end has answered";
1309 case AST_CONTROL_BUSY:
1310 return "Remote end is busy";
1311 case AST_CONTROL_TAKEOFFHOOK:
1312 return "Make it go off hook";
1313 case AST_CONTROL_OFFHOOK:
1314 return "Line is off hook";
1315 case AST_CONTROL_CONGESTION:
1316 return "Congestion (circuits busy)";
1317 case AST_CONTROL_FLASH:
1318 return "Flash hook";
1319 case AST_CONTROL_WINK:
1321 case AST_CONTROL_OPTION:
1322 return "Set a low-level option";
1323 case AST_CONTROL_RADIO_KEY:
1325 case AST_CONTROL_RADIO_UNKEY:
1326 return "Un-Key Radio";
1331 static int mgcp_indicate(struct ast_channel *ast, int ind)
1333 struct mgcp_subchannel *sub = ast->tech_pvt;
1337 ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
1338 ind, control2str(ind), ast->name);
1340 ast_mutex_lock(&sub->lock);
1342 case AST_CONTROL_RINGING:
1343 #ifdef DLINK_BUGGY_FIRMWARE
1344 transmit_notify_request(sub, "rt");
1346 transmit_notify_request(sub, "G/rt");
1349 case AST_CONTROL_BUSY:
1350 transmit_notify_request(sub, "L/bz");
1352 case AST_CONTROL_CONGESTION:
1353 transmit_notify_request(sub, "G/cg");
1356 transmit_notify_request(sub, "");
1359 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1362 ast_mutex_unlock(&sub->lock);
1366 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
1368 struct ast_channel *tmp;
1369 struct mgcp_endpoint *i = sub->parent;
1373 tmp = ast_channel_alloc(1);
1375 tmp->tech = &mgcp_tech;
1376 tmp->nativeformats = i->capability;
1377 if (!tmp->nativeformats)
1378 tmp->nativeformats = capability;
1379 fmt = ast_best_codec(tmp->nativeformats);
1380 snprintf(tmp->name, sizeof(tmp->name), "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1382 tmp->fds[0] = ast_rtp_fd(sub->rtp);
1384 if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
1385 i->dsp = ast_dsp_new();
1386 ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
1387 /* SC: this is to prevent clipping of dtmf tones during dsp processing */
1388 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
1392 ast_setstate(tmp, state);
1393 if (state == AST_STATE_RING)
1395 tmp->writeformat = fmt;
1396 tmp->rawwriteformat = fmt;
1397 tmp->readformat = fmt;
1398 tmp->rawreadformat = fmt;
1399 tmp->tech_pvt = sub;
1400 if (strlen(i->language))
1401 strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
1402 if (strlen(i->accountcode))
1403 strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode)-1);
1405 tmp->amaflags = i->amaflags;
1407 ast_mutex_lock(&usecnt_lock);
1409 ast_mutex_unlock(&usecnt_lock);
1410 ast_update_use_count();
1411 tmp->callgroup = i->callgroup;
1412 tmp->pickupgroup = i->pickupgroup;
1413 strncpy(tmp->call_forward, i->call_forward, sizeof(tmp->call_forward) - 1);
1414 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
1415 strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
1416 if (!ast_strlen_zero(i->cid_num))
1417 tmp->cid.cid_num = strdup(i->cid_num);
1418 if (!ast_strlen_zero(i->cid_name))
1419 tmp->cid.cid_name = strdup(i->cid_name);
1421 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
1423 if (state != AST_STATE_DOWN) {
1424 if (ast_pbx_start(tmp)) {
1425 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
1430 /* SC: verbose level check */
1431 if (option_verbose > 2) {
1432 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
1433 tmp->name, ast_state2str(state));
1436 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1441 static char* get_sdp_by_line(char* line, char *name, int nameLen)
1443 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1444 char* r = line + nameLen + 1;
1445 while (*r && (*r < 33)) ++r;
1451 static char *get_sdp(struct mgcp_request *req, char *name)
1454 int len = strlen(name);
1457 for (x=0; x<req->lines; x++) {
1458 r = get_sdp_by_line(req->line[x], name, len);
1459 if (r[0] != '\0') return r;
1464 static void sdpLineNum_iterator_init(int* iterator)
1469 static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
1471 int len = strlen(name);
1473 while (*iterator < req->lines) {
1474 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1475 if (r[0] != '\0') return r;
1480 static char *__get_header(struct mgcp_request *req, char *name, int *start)
1483 int len = strlen(name);
1485 for (x=*start;x<req->headers;x++) {
1486 if (!strncasecmp(req->header[x], name, len) &&
1487 (req->header[x][len] == ':')) {
1488 r = req->header[x] + len + 1;
1489 while(*r && (*r < 33))
1495 /* Don't return NULL, so get_header is always a valid pointer */
1499 static char *get_header(struct mgcp_request *req, char *name)
1502 return __get_header(req, name, &start);
1505 /* SC: get comma separated value */
1506 static char *get_csv(char *c, int *len, char **next)
1510 *next = NULL, *len = 0;
1511 if (!c) return NULL;
1513 while (*c && (*c < 33 || *c == ','))
1517 while (*c && (*c >= 33 && *c != ','))
1522 s = NULL, *next = NULL;
1527 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
1529 struct mgcp_endpoint *p = NULL;
1530 struct mgcp_subchannel *sub = NULL;
1531 struct mgcp_gateway *g;
1532 char iabuf[INET_ADDRSTRLEN];
1534 char *at = NULL, *c;
1537 strncpy(tmp, name, sizeof(tmp) - 1);
1538 at = strchr(tmp, '@');
1540 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1546 ast_mutex_lock(&gatelock);
1547 if (at && (at[0] == '[')) {
1549 c = strrchr(at, ']');
1555 if ((!name || !strcasecmp(g->name, at)) &&
1556 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1557 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1558 if (sin && g->dynamic && name) {
1559 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1560 (g->addr.sin_port != sin->sin_port)) {
1561 memcpy(&g->addr, sin, sizeof(g->addr));
1562 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
1563 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1564 if (option_verbose > 2)
1565 ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(iabuf, sizeof(iabuf), g->addr.sin_addr), ntohs(g->addr.sin_port));
1568 /* SC: not dynamic, check if the name matches */
1570 if (strcasecmp(g->name, at)) {
1575 /* SC: not dynamic, no name, check if the addr matches */
1576 else if (!name && sin) {
1577 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1578 (g->addr.sin_port != sin->sin_port)) {
1590 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
1593 #if 0 /* SC: new transport mech */
1597 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
1598 p->name, g->name, sub->id, msgid);
1599 if (sub->lastout == msgid) {
1601 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
1602 sub->id, msgid, sub->lastout);
1607 } while (sub != p->sub);
1617 } else if (name && !strcasecmp(p->name, tmp)) {
1618 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1619 p->name, g->name, p->sub->id);
1627 ast_mutex_lock(&sub->lock);
1633 ast_mutex_unlock(&gatelock);
1637 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
1639 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1645 static void parse(struct mgcp_request *req)
1647 /* Divide fields by NULL's */
1652 /* First header starts immediately */
1656 /* We've got a new header */
1659 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
1661 if (!strlen(req->header[f])) {
1662 /* Line by itself means we're now in content */
1666 if (f >= MGCP_MAX_HEADERS - 1) {
1667 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1670 req->header[f] = c + 1;
1671 } else if (*c == '\r') {
1672 /* Ignore but eliminate \r's */
1677 /* Check for last header */
1678 if (strlen(req->header[f]))
1681 /* Now we process any mime content */
1686 /* We've got a new line */
1689 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
1691 if (f >= MGCP_MAX_LINES - 1) {
1692 ast_log(LOG_WARNING, "Too many SDP lines...\n");
1695 req->line[f] = c + 1;
1696 } else if (*c == '\r') {
1697 /* Ignore and eliminate \r's */
1702 /* Check for last line */
1703 if (strlen(req->line[f]))
1706 /* Parse up the initial header */
1708 while(*c && *c < 33) c++;
1709 /* First the verb */
1711 while(*c && (*c > 32)) c++;
1715 while(*c && (*c < 33)) c++;
1716 req->identifier = c;
1717 while(*c && (*c > 32)) c++;
1721 while(*c && (*c < 33)) c++;
1723 while(*c && (*c > 32)) c++;
1727 while(*c && (*c < 33)) c++;
1729 while(*c && (*c > 32)) c++;
1730 while(*c && (*c < 33)) c++;
1731 while(*c && (*c > 32)) c++;
1738 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1739 req->verb, req->identifier, req->endpoint, req->version);
1740 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
1743 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1746 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1754 int peercapability, peerNonCodecCapability;
1755 struct sockaddr_in sin;
1757 struct ast_hostent ahp; struct hostent *hp;
1760 struct mgcp_endpoint *p = sub->parent;
1762 /* Get codec and RTP info from SDP */
1763 m = get_sdp(req, "m");
1764 c = get_sdp(req, "c");
1765 if (!strlen(m) || !strlen(c)) {
1766 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1769 if (sscanf(c, "IN IP4 %256s", host) != 1) {
1770 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1773 /* XXX This could block for a long time, and block the main thread! XXX */
1774 hp = ast_gethostbyname(host, &ahp);
1776 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1779 if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
1780 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
1783 sin.sin_family = AF_INET;
1784 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1785 sin.sin_port = htons(portno);
1786 ast_rtp_set_peer(sub->rtp, &sin);
1788 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
1790 /* Scan through the RTP payload types specified in a "m=" line: */
1791 ast_rtp_pt_clear(sub->rtp);
1793 while(strlen(codecs)) {
1794 if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
1795 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
1798 ast_rtp_set_m_type(sub->rtp, codec);
1802 /* Next, scan through each "a=rtpmap:" line, noting each */
1803 /* specified RTP payload type (with corresponding MIME subtype): */
1804 sdpLineNum_iterator_init(&iterator);
1805 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
1806 char* mimeSubtype = strdup(a); /* ensures we have enough space */
1807 if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
1809 /* Note: should really look at the 'freq' and '#chans' params too */
1810 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
1814 /* Now gather all of the codecs that were asked for: */
1815 ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
1816 p->capability = capability & peercapability;
1818 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
1819 capability, peercapability, p->capability);
1820 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
1821 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
1823 if (!p->capability) {
1824 ast_log(LOG_WARNING, "No compatible codecs!\n");
1830 static int add_header(struct mgcp_request *req, char *var, char *value)
1832 if (req->len >= sizeof(req->data) - 4) {
1833 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1837 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
1840 req->header[req->headers] = req->data + req->len;
1841 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
1842 req->len += strlen(req->header[req->headers]);
1843 if (req->headers < MGCP_MAX_HEADERS)
1846 ast_log(LOG_WARNING, "Out of header space\n");
1852 static int add_line(struct mgcp_request *req, char *line)
1854 if (req->len >= sizeof(req->data) - 4) {
1855 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1859 /* Add extra empty return */
1860 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
1861 req->len += strlen(req->data + req->len);
1863 req->line[req->lines] = req->data + req->len;
1864 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
1865 req->len += strlen(req->line[req->lines]);
1866 if (req->lines < MGCP_MAX_LINES)
1869 ast_log(LOG_WARNING, "Out of line space\n");
1875 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1877 /* Initialize a response */
1878 if (req->headers || req->len) {
1879 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1882 req->header[req->headers] = req->data + req->len;
1883 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1884 req->len += strlen(req->header[req->headers]);
1885 if (req->headers < MGCP_MAX_HEADERS)
1888 ast_log(LOG_WARNING, "Out of header space\n");
1892 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1894 /* Initialize a response */
1895 if (req->headers || req->len) {
1896 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1899 req->header[req->headers] = req->data + req->len;
1900 /* SC: check if we need brackets around the gw name */
1901 if (p->parent->isnamedottedip)
1902 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);
1904 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);
1905 req->len += strlen(req->header[req->headers]);
1906 if (req->headers < MGCP_MAX_HEADERS)
1909 ast_log(LOG_WARNING, "Out of header space\n");
1914 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1916 memset(resp, 0, sizeof(*resp));
1917 init_resp(resp, msg, req, msgrest);
1921 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1923 memset(req, 0, sizeof(struct mgcp_request));
1925 if (oseq > 999999999)
1927 init_req(p, req, verb);
1931 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
1933 struct mgcp_request resp;
1934 struct mgcp_endpoint *p = sub->parent;
1935 struct mgcp_response *mgr;
1937 respprep(&resp, p, msg, req, msgrest);
1938 mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
1940 /* Store MGCP response in case we have to retransmit */
1941 memset(mgr, 0, sizeof(struct mgcp_response));
1942 sscanf(req->identifier, "%d", &mgr->seqno);
1943 time(&mgr->whensent);
1944 mgr->len = resp.len;
1945 memcpy(mgr->buf, resp.data, resp.len);
1946 mgr->buf[resp.len] = '\0';
1947 mgr->next = p->parent->responses;
1948 p->parent->responses = mgr;
1950 return send_response(sub, &resp);
1954 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1959 struct sockaddr_in sin;
1967 char iabuf[INET_ADDRSTRLEN];
1969 struct sockaddr_in dest;
1970 struct mgcp_endpoint *p = sub->parent;
1971 /* XXX We break with the "recommendation" and send our IP, in order that our
1972 peer doesn't have to ast_gethostbyname() us XXX */
1975 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1978 ast_rtp_get_us(sub->rtp, &sin);
1980 ast_rtp_get_peer(rtp, &dest);
1982 if (sub->tmpdest.sin_addr.s_addr) {
1983 dest.sin_addr = sub->tmpdest.sin_addr;
1984 dest.sin_port = sub->tmpdest.sin_port;
1985 /* Reset temporary destination */
1986 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1988 dest.sin_addr = p->parent->ourip;
1989 dest.sin_port = sin.sin_port;
1993 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->ourip), ntohs(sin.sin_port));
1995 snprintf(v, sizeof(v), "v=0\r\n");
1996 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
1997 snprintf(s, sizeof(s), "s=session\r\n");
1998 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
1999 snprintf(t, sizeof(t), "t=0 0\r\n");
2000 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
2001 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2002 if (p->capability & x) {
2004 ast_verbose("Answering with capability %d\n", x);
2006 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
2008 snprintf(costr, sizeof(costr), " %d", codec);
2009 strncat(m, costr, sizeof(m) - strlen(m) - 1);
2010 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
2011 strncat(a, costr, sizeof(a) - strlen(a) - 1);
2015 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
2016 if (p->nonCodecCapability & x) {
2018 ast_verbose("Answering with non-codec capability %d\n", x);
2020 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
2022 snprintf(costr, sizeof(costr), " %d", codec);
2023 strncat(m, costr, sizeof(m) - strlen(m) - 1);
2024 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
2025 strncat(a, costr, sizeof(a) - strlen(a) - 1);
2026 if (x == AST_RTP_DTMF) {
2027 /* Indicate we support DTMF... Not sure about 16,
2028 but MSN supports it so dang it, we will too... */
2029 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
2030 strncat(a, costr, sizeof(a) - strlen(a) - 1);
2035 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
2036 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
2037 snprintf(costr, sizeof(costr), "%d", len);
2048 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
2050 struct mgcp_request resp;
2055 struct mgcp_endpoint *p = sub->parent;
2057 capability = p->capability;
2059 capability = codecs;
2060 if (!strlen(sub->cxident) && rtp) {
2061 /* We don't have a CXident yet, store the destination and
2063 ast_rtp_get_peer(rtp, &sub->tmpdest);
2066 snprintf(local, sizeof(local), "p:20");
2067 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2068 if (p->capability & x) {
2069 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
2070 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2073 reqprep(&resp, p, "MDCX");
2074 add_header(&resp, "C", sub->callid);
2075 add_header(&resp, "L", local);
2076 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2077 /* SC: X header should not be sent. kept for compatibility */
2078 add_header(&resp, "X", sub->txident);
2079 add_header(&resp, "I", sub->cxident);
2080 /*add_header(&resp, "S", "");*/
2081 ast_rtp_offered_from_local(sub->rtp, 0);
2082 add_sdp(&resp, sub, rtp);
2083 /* SC: fill in new fields */
2084 resp.cmd = MGCP_CMD_MDCX;
2086 return send_request(p, sub, &resp, oseq); /* SC */
2089 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
2091 struct mgcp_request resp;
2095 struct mgcp_endpoint *p = sub->parent;
2097 snprintf(local, sizeof(local), "p:20");
2098 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2099 if (p->capability & x) {
2100 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
2101 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2105 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2106 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2108 reqprep(&resp, p, "CRCX");
2109 add_header(&resp, "C", sub->callid);
2110 add_header(&resp, "L", local);
2111 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2112 /* SC: X header should not be sent. kept for compatibility */
2113 add_header(&resp, "X", sub->txident);
2114 /*add_header(&resp, "S", "");*/
2115 ast_rtp_offered_from_local(sub->rtp, 1);
2116 add_sdp(&resp, sub, rtp);
2117 /* SC: fill in new fields */
2118 resp.cmd = MGCP_CMD_CRCX;
2120 return send_request(p, sub, &resp, oseq); /* SC */
2123 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
2125 struct mgcp_request resp;
2126 struct mgcp_endpoint *p = sub->parent;
2129 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2130 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2132 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
2133 reqprep(&resp, p, "RQNT");
2134 add_header(&resp, "X", p->rqnt_ident); /* SC */
2135 switch (p->hookstate) {
2137 add_header(&resp, "R", "L/hd(N)");
2140 add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
2144 add_header(&resp, "S", tone);
2146 /* SC: fill in new fields */
2147 resp.cmd = MGCP_CMD_RQNT;
2149 return send_request(p, NULL, &resp, oseq); /* SC */
2152 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
2154 struct mgcp_request resp;
2159 struct mgcp_endpoint *p = sub->parent;
2162 localtime_r(&t,&tm);
2170 /* Keep track of last callerid for blacklist and callreturn */
2171 strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
2173 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
2174 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
2175 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
2176 reqprep(&resp, p, "RQNT");
2177 add_header(&resp, "X", p->rqnt_ident); /* SC */
2178 switch (p->hookstate) {
2180 add_header(&resp, "R", "L/hd(N)");
2183 add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
2186 if (strlen(tone2)) {
2187 add_header(&resp, "S", tone2);
2190 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2191 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2193 /* SC: fill in new fields */
2194 resp.cmd = MGCP_CMD_RQNT;
2196 return send_request(p, NULL, &resp, oseq); /* SC */
2199 static int transmit_modify_request(struct mgcp_subchannel *sub)
2201 struct mgcp_request resp;
2202 struct mgcp_endpoint *p = sub->parent;
2204 if (!strlen(sub->cxident)) {
2205 /* We don't have a CXident yet, store the destination and
2210 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
2211 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2213 reqprep(&resp, p, "MDCX");
2214 add_header(&resp, "C", sub->callid);
2215 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2216 /* SC: X header should not be sent. kept for compatibility */
2217 add_header(&resp, "X", sub->txident);
2218 add_header(&resp, "I", sub->cxident);
2219 switch (sub->parent->hookstate) {
2221 add_header(&resp, "R", "L/hd(N)");
2224 add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
2227 /* SC: fill in new fields */
2228 resp.cmd = MGCP_CMD_MDCX;
2230 return send_request(p, sub, &resp, oseq); /* SC */
2234 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
2236 struct mgcp_request resp;
2237 reqprep(&resp, p, "AUEP");
2238 /* SC: removed unknown param VS */
2239 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
2240 add_header(&resp, "F", "A");
2241 /* SC: fill in new fields */
2242 resp.cmd = MGCP_CMD_AUEP;
2244 return send_request(p, NULL, &resp, oseq); /* SC */
2247 static int transmit_connection_del(struct mgcp_subchannel *sub)
2249 struct mgcp_endpoint *p = sub->parent;
2250 struct mgcp_request resp;
2253 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2254 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2256 reqprep(&resp, p, "DLCX");
2257 /* SC: check if call id is avail */
2259 add_header(&resp, "C", sub->callid);
2260 /* SC: X header should not be sent. kept for compatibility */
2261 add_header(&resp, "X", sub->txident);
2262 /* SC: check if cxident is avail */
2263 if (sub->cxident[0])
2264 add_header(&resp, "I", sub->cxident);
2265 /* SC: fill in new fields */
2266 resp.cmd = MGCP_CMD_DLCX;
2268 return send_request(p, sub, &resp, oseq); /* SC */
2271 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
2273 struct mgcp_request resp;
2276 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
2277 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2279 reqprep(&resp, p, "DLCX");
2280 /* SC: check if call id is avail */
2281 if (callid && *callid)
2282 add_header(&resp, "C", callid);
2283 /* SC: check if cxident is avail */
2284 if (cxident && *cxident)
2285 add_header(&resp, "I", cxident);
2286 /* SC: fill in new fields */
2287 resp.cmd = MGCP_CMD_DLCX;
2289 return send_request(p, p->sub, &resp, oseq);
2292 /* SC: cleanup pending commands */
2293 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
2295 struct mgcp_request *t, *q;
2298 ast_mutex_lock(&p->rqnt_queue_lock);
2299 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
2300 p->rqnt_queue = NULL;
2301 ast_mutex_unlock(&p->rqnt_queue_lock);
2303 ast_mutex_lock(&p->cmd_queue_lock);
2304 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
2305 p->cmd_queue = NULL;
2306 ast_mutex_unlock(&p->cmd_queue_lock);
2308 ast_mutex_lock(&p->sub->cx_queue_lock);
2309 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
2310 p->sub->cx_queue = NULL;
2311 ast_mutex_unlock(&p->sub->cx_queue_lock);
2313 ast_mutex_lock(&p->sub->next->cx_queue_lock);
2314 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
2315 p->sub->next->cx_queue = NULL;
2316 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
2318 ast_mutex_lock(&sub->cx_queue_lock);
2319 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
2320 sub->cx_queue = NULL;
2321 ast_mutex_unlock(&sub->cx_queue_lock);
2326 /* SC: remove command transaction from queue */
2327 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2328 struct mgcp_request **queue, ast_mutex_t *l, int ident)
2330 struct mgcp_request *prev, *req;
2331 char iabuf[INET_ADDRSTRLEN];
2334 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2335 if (req->trid == ident) {
2336 /* remove from queue */
2340 prev->next = req->next;
2342 /* send next pending command */
2345 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2346 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2349 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2354 ast_mutex_unlock(l);
2358 /* SC: modified for new transport mechanism */
2359 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2360 int result, unsigned int ident, struct mgcp_request *resp)
2363 struct mgcp_request *req;
2364 struct mgcp_gateway *gw = p->parent;
2367 /* provisional response */
2371 if (p->slowsequence)
2372 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2374 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2375 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2376 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2379 if (option_verbose > 2) {
2380 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
2386 if (p && (result >= 400) && (result <= 599)) {
2389 p->hookstate = MGCP_OFFHOOK;
2392 p->hookstate = MGCP_ONHOOK;
2395 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
2398 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
2403 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2404 result, p->name, p->parent->name, sub ? sub->id:-1);
2405 mgcp_queue_hangup(sub);
2408 if (p->sub->next->owner) {
2409 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2410 result, p->name, p->parent->name, sub ? sub->id:-1);
2411 mgcp_queue_hangup(p->sub);
2414 if (p->sub->owner) {
2415 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2416 result, p->name, p->parent->name, sub ? sub->id:-1);
2417 mgcp_queue_hangup(p->sub);
2420 dump_cmd_queues(p, NULL);
2425 if (req->cmd == MGCP_CMD_CRCX) {
2426 if ((c = get_header(resp, "I"))) {
2427 if (strlen(c) && sub) {
2428 /* SC: if we are hanging up do not process this conn. */
2430 if (strlen(sub->cxident)) {
2431 if (strcasecmp(c, sub->cxident)) {
2432 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2435 strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
2436 if (sub->tmpdest.sin_addr.s_addr) {
2437 transmit_modify_with_sdp(sub, NULL, 0);
2440 /* XXX SC: delete this one
2441 callid and conn id may already be lost.
2442 so the following del conn may have a side effect of
2443 cleaning up the next subchannel */
2444 transmit_connection_del(sub);
2450 if (req->cmd == MGCP_CMD_AUEP) {
2451 /* SC: check stale connection ids */
2452 if ((c = get_header(resp, "I"))) {
2455 while ((v = get_csv(c, &len, &n))) {
2457 if (strncasecmp(v, p->sub->cxident, len) &&
2458 strncasecmp(v, p->sub->next->cxident, len)) {
2459 /* connection id not found. delete it */
2461 memcpy(cxident, v, len);
2462 cxident[len] = '\0';
2463 if (option_verbose > 2) {
2464 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
2465 cxident, p->name, gw->name);
2467 transmit_connection_del_w_params(p, NULL, cxident);
2474 /* Try to determine the hookstate returned from an audit endpoint command */
2475 if ((c = get_header(resp, "ES"))) {
2477 if (strstr(c, "hu")) {
2478 if (p->hookstate != MGCP_ONHOOK) {
2479 /* SC: XXX cleanup if we think we are offhook XXX */
2480 if ((p->sub->owner || p->sub->next->owner ) &&
2481 p->hookstate == MGCP_OFFHOOK)
2482 mgcp_queue_hangup(sub);
2483 p->hookstate = MGCP_ONHOOK;
2485 /* SC: update the requested events according to the new hookstate */
2486 transmit_notify_request(p->sub, "");
2488 /* SC: verbose level check */
2489 if (option_verbose > 2) {
2490 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2493 } else if (strstr(c, "hd")) {
2494 if (p->hookstate != MGCP_OFFHOOK) {
2495 p->hookstate = MGCP_OFFHOOK;
2497 /* SC: update the requested events according to the new hookstate */
2498 transmit_notify_request(p->sub, "");
2500 /* SC: verbose level check */
2501 if (option_verbose > 2) {
2502 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2510 if (resp && resp->lines) {
2511 /* SC: do not process sdp if we are hanging up. this may be a late response */
2512 if (sub && sub->owner) {
2516 process_sdp(sub, resp);
2524 static void start_rtp(struct mgcp_subchannel *sub)
2526 ast_mutex_lock(&sub->lock);
2527 /* SC: check again to be on the safe side */
2529 ast_rtp_destroy(sub->rtp);
2532 /* Allocate the RTP now */
2533 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
2534 if (sub->rtp && sub->owner)
2535 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2537 ast_rtp_setnat(sub->rtp, sub->nat);
2539 ast_rtp_set_callback(p->rtp, rtpready);
2540 ast_rtp_set_data(p->rtp, p);
2542 /* Make a call*ID */
2543 snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
2544 /* Transmit the connection create */
2545 transmit_connect_with_sdp(sub, NULL);
2546 ast_mutex_unlock(&sub->lock);
2549 static void *mgcp_ss(void *data)
2551 struct ast_channel *chan = data;
2552 struct mgcp_subchannel *sub = chan->tech_pvt;
2553 struct mgcp_endpoint *p = sub->parent;
2554 char exten[AST_MAX_EXTENSION] = "";
2556 int timeout = firstdigittimeout;
2560 while(len < AST_MAX_EXTENSION-1) {
2561 res = ast_waitfordigit(chan, timeout);
2564 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
2565 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2566 ast_indicate(chan, -1);
2573 if (!ast_ignore_pattern(chan->context, exten)) {
2574 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2575 ast_indicate(chan, -1);
2577 /* XXX Redundant? We should already be playing dialtone */
2578 /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2579 transmit_notify_request(sub, "L/dl");
2581 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
2582 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
2584 /* Record this as the forwarding extension */
2585 strncpy(p->call_forward, exten, sizeof(p->call_forward) - 1);
2586 if (option_verbose > 2) {
2587 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
2588 p->call_forward, chan->name);
2590 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2591 transmit_notify_request(sub, "L/sl");
2595 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2596 ast_indicate(chan, -1);
2598 memset(exten, 0, sizeof(exten));
2599 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2600 transmit_notify_request(sub, "L/dl");
2604 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2605 ast_indicate(chan, -1);
2606 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
2607 if (!ast_strlen_zero(p->cid_num)) {
2608 if (!p->hidecallerid) {
2609 /* SC: free existing chan->callerid */
2610 if (chan->cid.cid_num)
2611 free(chan->cid.cid_num);
2612 chan->cid.cid_num = strdup(p->cid_num);
2613 /* SC: free existing chan->callerid */
2614 if (chan->cid.cid_name)
2615 free(chan->cid.cid_name);
2616 chan->cid.cid_name = strdup(p->cid_name);
2618 if (chan->cid.cid_ani)
2619 free(chan->cid.cid_ani);
2620 chan->cid.cid_ani = strdup(p->cid_num);
2622 ast_setstate(chan, AST_STATE_RING);
2623 /*zt_enable_ec(p);*/
2624 if (p->dtmfmode & MGCP_DTMF_HYBRID) {
2625 p->dtmfmode |= MGCP_DTMF_INBAND;
2626 ast_indicate(chan, -1);
2628 res = ast_pbx_run(chan);
2630 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2631 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2632 /*transmit_notify_request(p, "nbz", 1);*/
2633 transmit_notify_request(sub, "G/cg");
2638 /* It's a match, but they just typed a digit, and there is an ambiguous match,
2639 so just set the timeout to matchdigittimeout and wait some more */
2640 timeout = matchdigittimeout;
2642 } else if (res == 0) {
2643 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
2644 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2645 transmit_notify_request(sub, "G/cg");
2646 /*zt_wait_event(p->subs[index].zfd);*/
2649 } else if (p->callwaiting && !strcmp(exten, "*70")) {
2650 if (option_verbose > 2) {
2651 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
2653 /* Disable call waiting if enabled */
2655 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2656 transmit_notify_request(sub, "L/sl");
2658 memset(exten, 0, sizeof(exten));
2659 timeout = firstdigittimeout;
2660 } else if (!strcmp(exten,ast_pickup_ext())) {
2661 /* Scan all channels and see if any there
2662 * ringing channqels with that have call groups
2663 * that equal this channels pickup group
2665 if (ast_pickup_call(chan)) {
2666 ast_log(LOG_WARNING, "No call pickup possible...\n");
2667 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2668 transmit_notify_request(sub, "G/cg");
2672 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
2673 if (option_verbose > 2) {
2674 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
2676 /* Disable Caller*ID if enabled */
2677 p->hidecallerid = 1;
2678 if (chan->cid.cid_num)
2679 free(chan->cid.cid_num);
2680 chan->cid.cid_num = NULL;
2681 if (chan->cid.cid_name)
2682 free(chan->cid.cid_name);
2683 chan->cid.cid_name = NULL;
2684 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2685 transmit_notify_request(sub, "L/sl");
2687 memset(exten, 0, sizeof(exten));
2688 timeout = firstdigittimeout;
2689 } else if (p->callreturn && !strcmp(exten, "*69")) {
2691 if (strlen(p->lastcallerid)) {
2692 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
2695 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2696 transmit_notify_request(sub, "L/sl");
2698 } else if (!strcmp(exten, "*78")) {
2699 /* Do not disturb */
2700 if (option_verbose > 2) {
2701 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
2703 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2704 transmit_notify_request(sub, "L/sl");
2707 memset(exten, 0, sizeof(exten));
2709 } else if (!strcmp(exten, "*79")) {
2710 /* Do not disturb */
2711 if (option_verbose > 2) {
2712 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
2714 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2715 transmit_notify_request(sub, "L/sl");
2718 memset(exten, 0, sizeof(exten));
2720 } else if (p->cancallforward && !strcmp(exten, "*72")) {
2721 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2722 transmit_notify_request(sub, "L/sl");
2724 memset(exten, 0, sizeof(exten));
2726 } else if (p->cancallforward && !strcmp(exten, "*73")) {
2727 if (option_verbose > 2) {
2728 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
2730 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2731 transmit_notify_request(sub, "L/sl");
2732 memset(p->call_forward, 0, sizeof(p->call_forward));
2734 memset(exten, 0, sizeof(exten));
2736 } else if (!strcmp(exten, ast_parking_ext()) &&
2737 sub->next->owner && ast_bridged_channel(sub->next->owner)) {
2738 /* This is a three way call, the main call being a real channel,
2739 and we're parking the first call. */
2740 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
2741 if (option_verbose > 2) {
2742 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
2745 } else if (strlen(p->lastcallerid) && !strcmp(exten, "*60")) {
2746 if (option_verbose > 2) {
2747 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
2749 res = ast_db_put("blacklist", p->lastcallerid, "1");
2751 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2752 transmit_notify_request(sub, "L/sl");
2753 memset(exten, 0, sizeof(exten));
2756 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
2757 if (option_verbose > 2) {
2758 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
2760 /* Enable Caller*ID if enabled */
2761 p->hidecallerid = 0;
2762 if (chan->cid.cid_num)
2763 free(chan->cid.cid_num);
2764 if (!ast_strlen_zero(p->cid_num))
2765 chan->cid.cid_num = strdup(p->cid_num);
2766 if (chan->cid.cid_name)
2767 free(chan->cid.cid_name);
2768 if (!ast_strlen_zero(p->cid_name))
2769 chan->cid.cid_name = strdup(p->cid_name);
2770 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2771 transmit_notify_request(sub, "L/sl");
2773 memset(exten, 0, sizeof(exten));
2774 timeout = firstdigittimeout;
2775 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
2776 ((exten[0] != '*') || (strlen(exten) > 2))) {
2778 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
2782 timeout = gendigittimeout;
2783 if (len && !ast_ignore_pattern(chan->context, exten))
2784 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
2785 ast_indicate(chan, -1);
2789 res = ast_waitfordigit(chan, to);
2791 ast_log(LOG_DEBUG, "Timeout...\n");
2795 ast_log(LOG_DEBUG, "Got hangup...\n");
2800 if (!ast_ignore_pattern(chan->context, exten))
2801 ast_indicate(chan, -1);
2802 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
2803 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
2810 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
2811 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
2815 ast_setstate(chan, AST_STATE_RING);
2817 if (ast_pbx_run(chan)) {
2818 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
2827 static int attempt_transfer(struct mgcp_endpoint *p)
2829 /* *************************
2830 * I hope this works.
2831 * Copied out of chan_zap
2832 * Cross your fingers
2833 * *************************/
2835 /* In order to transfer, we need at least one of the channels to
2836 actually be in a call bridge. We can't conference two applications
2837 together (but then, why would we want to?) */
2838 if (ast_bridged_channel(p->sub->owner)) {
2839 /* The three-way person we're about to transfer to could still be in MOH, so
2840 stop if now if appropriate */
2841 if (ast_bridged_channel(p->sub->next->owner))
2842 ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
2843 if (p->sub->owner->_state == AST_STATE_RINGING) {
2844 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
2846 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
2847 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2848 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
2851 /* Orphan the channel */
2852 unalloc_sub(p->sub->next);
2853 } else if (ast_bridged_channel(p->sub->next->owner)) {
2854 if (p->sub->owner->_state == AST_STATE_RINGING) {
2855 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
2857 ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
2858 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
2859 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2860 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
2863 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
2864 if (option_verbose > 2) {
2865 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);
2867 p->sub = p->sub->next;
2868 unalloc_sub(p->sub->next);
2869 /* Tell the caller not to hangup */
2872 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
2873 p->sub->owner->name, p->sub->next->owner->name);
2874 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2875 if (p->sub->next->owner) {
2876 p->sub->next->alreadygone = 1;
2877 mgcp_queue_hangup(p->sub->next);
2883 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
2885 struct mgcp_endpoint *p = sub->parent;
2886 struct ast_channel *c;
2888 pthread_attr_t attr;
2889 pthread_attr_init(&attr);
2890 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2892 /* Off hook / answer */
2893 if (sub->outgoing) {
2896 if (ast_bridged_channel(sub->owner)) {
2897 ast_moh_stop(ast_bridged_channel(sub->owner));
2899 sub->cxmode = MGCP_CX_SENDRECV;
2903 transmit_modify_request(sub);
2905 /*transmit_notify_request(sub, "aw");*/
2906 transmit_notify_request(sub, "");
2907 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
2911 /*sub->cxmode = MGCP_CX_SENDRECV;*/
2916 transmit_modify_request(sub);
2919 /* The channel is immediately up. Start right away */
2920 #ifdef DLINK_BUGGY_FIRMWARE
2921 transmit_notify_request(sub, "rt");
2923 transmit_notify_request(sub, "G/rt");
2925 c = mgcp_new(sub, AST_STATE_RING);
2927 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
2928 transmit_notify_request(sub, "G/cg");
2932 if (has_voicemail(p)) {
2933 transmit_notify_request(sub, "L/sl");
2935 transmit_notify_request(sub, "L/dl");
2937 c = mgcp_new(sub, AST_STATE_DOWN);
2939 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
2940 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
2944 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
2948 if (p->hookstate == MGCP_OFFHOOK) {
2949 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
2951 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
2952 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
2954 if (ast_bridged_channel(sub->owner)) {
2955 ast_moh_stop(ast_bridged_channel(sub->owner));
2957 sub->cxmode = MGCP_CX_SENDRECV;
2961 transmit_modify_request(sub);
2963 /*transmit_notify_request(sub, "aw");*/
2964 transmit_notify_request(sub, "");
2965 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
2970 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
2973 struct ast_frame f = { 0, };
2974 struct mgcp_endpoint *p = sub->parent;
2975 struct mgcp_gateway *g = NULL;
2976 char iabuf[INET_ADDRSTRLEN];
2980 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
2982 /* Clear out potential response */
2983 if (!strcasecmp(req->verb, "RSIP")) {
2984 /* Test if this RSIP request is just a keepalive */
2985 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
2986 if (option_verbose > 2)
2987 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
2988 transmit_response(sub, "200", req, "OK");
2990 dump_queue(p->parent, p);
2991 dump_cmd_queues(p, NULL);
2993 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
2994 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);