2 * Asterisk -- A telephony toolkit for Linux.
4 * Implementation of Media Gateway Control Protocol
6 * Copyright (C) 1999-2004, 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 support for the wildcard endpoint
16 -- seteable wildcard with wcardep on mgcp.conf
17 -- added package indicator on RQNT, i.e "dl" --> "L/dl"
18 -- removed MDCX just before DLCX, do we need this ?
22 -- reload for wildcard endpoint probably buggy
23 -- when hf is notified we're sending CRCX after MDCX, without waiting for
24 OK on the MDCX which fails on Cisco IAD 24XX
25 -- honour codec order, by now the lowest codec number in "allow" is the prefered
29 -- packet retransmit mechanism (simplistic)
30 -- per endpoint/subchannel mgcp command sequencing.
31 -- better transaction handling
32 -- fixed some mem leaks
33 -- run-time configuration reload
34 -- distinguish CA and GW default MGCP ports
35 -- prevent clipping of DTMF tones in an established call
36 -- fixed a few crash scenarios in 3-way
37 -- fix for a few cases where asterisk and MGW end-up in conflicting ep states
38 -- enclose numeric IP in [] for outgoing requests
43 -- responseAck support
44 -- enhance retransmit mechanism (RTO calc. etc.)
45 -- embedded command support
48 * -- fixed reload_config() / do_monitor to stay responsive during reloads
53 #include <asterisk/lock.h>
54 #include <asterisk/channel.h>
55 #include <asterisk/channel_pvt.h>
56 #include <asterisk/config.h>
57 #include <asterisk/logger.h>
58 #include <asterisk/module.h>
59 #include <asterisk/pbx.h>
60 #include <asterisk/options.h>
61 #include <asterisk/lock.h>
62 #include <asterisk/sched.h>
63 #include <asterisk/io.h>
64 #include <asterisk/rtp.h>
65 #include <asterisk/acl.h>
66 #include <asterisk/callerid.h>
67 #include <asterisk/cli.h>
68 #include <asterisk/say.h>
69 #include <asterisk/cdr.h>
70 #include <asterisk/astdb.h>
71 #include <asterisk/features.h>
72 #include <asterisk/app.h>
73 #include <asterisk/musiconhold.h>
74 #include <asterisk/utils.h>
75 #include <asterisk/causes.h>
76 #include <sys/socket.h>
77 #include <sys/ioctl.h>
84 #include <arpa/inet.h>
85 #include <sys/signal.h>
87 #include <netinet/in_systm.h>
88 #include <netinet/ip.h>
90 #include <asterisk/dsp.h>
94 #define IPTOS_MINCOST 0x02
98 * Define to work around buggy dlink MGCP phone firmware which
99 * appears not to know that "rt" is part of the "G" package.
101 /* #define DLINK_BUGGY_FIRMWARE */
104 #define DEFAULT_EXPIREY 120
105 #define MAX_EXPIREY 3600
106 #define CANREINVITE 1
109 #define INADDR_NONE (in_addr_t)(-1)
112 static char *desc = "Media Gateway Control Protocol (MGCP)";
113 static char *type = "MGCP";
114 static char *tdesc = "Media Gateway Control Protocol (MGCP)";
115 static char *config = "mgcp.conf";
117 #define MGCP_DTMF_RFC2833 (1 << 0)
118 #define MGCP_DTMF_INBAND (1 << 1)
120 #define DEFAULT_MGCP_GW_PORT 2427/* From RFC 2705 */
121 #define DEFAULT_MGCP_CA_PORT 2727/* From RFC 2705 */
122 #define MGCP_MAX_PACKET 1500 /* Also from RFC 2543, should sub headers tho */
123 #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */
124 #define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
126 /* MGCP rtp stream modes */
127 #define MGCP_CX_SENDONLY 0
128 #define MGCP_CX_RECVONLY 1
129 #define MGCP_CX_SENDRECV 2
130 #define MGCP_CX_CONF 3
131 #define MGCP_CX_CONFERENCE 3
132 #define MGCP_CX_MUTE 4
133 #define MGCP_CX_INACTIVE 4
135 static char *mgcp_cxmodes[] = {
143 /* SC: MGCP commands */
144 #define MGCP_CMD_EPCF 0
145 #define MGCP_CMD_CRCX 1
146 #define MGCP_CMD_MDCX 2
147 #define MGCP_CMD_DLCX 3
148 #define MGCP_CMD_RQNT 4
149 #define MGCP_CMD_NTFY 5
150 #define MGCP_CMD_AUEP 6
151 #define MGCP_CMD_AUCX 7
152 #define MGCP_CMD_RSIP 8
154 static char context[AST_MAX_EXTENSION] = "default";
156 static char language[MAX_LANGUAGE] = "";
157 static char musicclass[MAX_LANGUAGE] = "";
158 static char cid_num[AST_MAX_EXTENSION] = "";
159 static char cid_name[AST_MAX_EXTENSION] = "";
161 static int dtmfmode = 0;
164 /* Not used. Dosn't hurt for us to always send cid */
165 /* to the mgcp box. */
166 /* static int use_callerid = 1;*/
167 /*static int cur_signalling = -1;*/
169 /*static unsigned int cur_group = 0;*/
170 static unsigned int cur_callergroup = 0;
171 static unsigned int cur_pickupgroup = 0;
173 /* XXX Is this needed? */
174 /* Doesn't look like the dsp stuff for */
175 /* dtmfmode is actually hooked up. */
176 /* static int relaxdtmf = 0; */
180 static int immediate = 0;
182 static int callwaiting = 0;
184 /* Not used. Dosn't hurt for us to always send cid */
185 /* to the mgcp box. */
186 /*static int callwaitingcallerid = 0;*/
188 /*static int hidecallerid = 0;*/
190 static int callreturn = 0;
192 static int slowsequence = 0;
194 static int threewaycalling = 0;
196 /* This is for flashhook transfers */
197 static int transfer = 0;
199 static int cancallforward = 0;
201 static int singlepath = 0;
203 static int canreinvite = CANREINVITE;
205 /*static int busycount = 3;*/
207 /*static int callprogress = 0;*/
209 static char accountcode[20] = "";
211 static char mailbox[AST_MAX_EXTENSION];
213 static int amaflags = 0;
218 static int usecnt =0;
219 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
220 /* SC: transaction id should always be positive */
221 static unsigned int oseq;
223 /* Wait up to 16 seconds for first digit (FXO logic) */
224 static int firstdigittimeout = 16000;
226 /* How long to wait for following digits (FXO logic) */
227 static int gendigittimeout = 8000;
229 /* How long to wait for an extra digit, if there is an ambiguous match */
230 static int matchdigittimeout = 3000;
232 /* Protect the monitoring thread, so only one process can kill or start it, and not
233 when it's doing something critical. */
234 AST_MUTEX_DEFINE_STATIC(netlock);
236 AST_MUTEX_DEFINE_STATIC(monlock);
238 /* This is the thread for the monitor which checks for input on the channels
239 which are not currently in use. */
240 static pthread_t monitor_thread = AST_PTHREADT_NULL;
242 static int restart_monitor(void);
244 /* Just about everybody seems to support ulaw, so make it a nice default */
245 static int capability = AST_FORMAT_ULAW;
246 static int nonCodecCapability = AST_RTP_DTMF;
248 static char ourhost[256];
249 static struct in_addr __ourip;
252 static int mgcpdebug = 0;
254 static struct sched_context *sched;
255 static struct io_context *io;
256 /* The private structures of the mgcp channels are linked for
257 selecting outgoing channels */
259 #define MGCP_MAX_HEADERS 64
260 #define MGCP_MAX_LINES 64
262 struct mgcp_request {
268 int headers; /* MGCP Headers */
269 char *header[MGCP_MAX_HEADERS];
270 int lines; /* SDP Content */
271 char *line[MGCP_MAX_LINES];
272 char data[MGCP_MAX_PACKET];
273 int cmd; /* SC: int version of verb = command */
274 unsigned int trid; /* SC: int version of identifier = transaction id */
275 struct mgcp_request *next; /* SC: next in the queue */
279 static struct mgcp_pkt {
281 struct mgcp_endpoint *owner;
283 char data[MGCP_MAX_PACKET];
284 struct mgcp_pkt *next;
288 /* MGCP message for queuing up */
289 struct mgcp_message {
290 struct mgcp_endpoint *owner_ep;
291 struct mgcp_subchannel *owner_sub;
293 unsigned long expire;
296 struct mgcp_message *next;
297 unsigned char buf[0];
300 #define RESPONSE_TIMEOUT 30 /* in seconds */
302 struct mgcp_response {
306 struct mgcp_response *next;
307 unsigned char buf[0];
315 struct mgcp_subchannel {
316 /* SC: subchannel magic string.
317 Needed to prove that any subchannel pointer passed by asterisk
318 really points to a valid subchannel memory area.
319 Ugly.. But serves the purpose for the time being.
321 #define MGCP_SUBCHANNEL_MAGIC "!978!"
325 struct ast_channel *owner;
326 struct mgcp_endpoint *parent;
328 struct sockaddr_in tmpdest;
329 char txident[80]; /* FIXME SC: txident is replaced by rqnt_ident in endpoint.
330 This should be obsoleted */
338 struct mgcp_request *cx_queue; /* SC: pending CX commands */
339 ast_mutex_t cx_queue_lock; /* SC: CX queue lock */
341 int iseq; /* Not used? RTP? */
346 struct mgcp_message *msgs;
348 struct mgcp_subchannel *next; /* for out circular linked list */
351 #define MGCP_ONHOOK 1
352 #define MGCP_OFFHOOK 2
357 struct mgcp_endpoint {
360 struct mgcp_subchannel *sub; /* pointer to our current connection, channel and stuff */
361 char accountcode[80];
362 char exten[AST_MAX_EXTENSION]; /* Extention where to start */
363 char context[AST_MAX_EXTENSION];
364 char language[MAX_LANGUAGE];
365 char cid_num[AST_MAX_EXTENSION]; /* Caller*ID */
366 char cid_name[AST_MAX_EXTENSION]; /* Caller*ID */
367 char lastcallerid[AST_MAX_EXTENSION]; /* Last Caller*ID */
368 char call_forward[AST_MAX_EXTENSION]; /* Last Caller*ID */
369 char mailbox[AST_MAX_EXTENSION];
370 char musicclass[MAX_LANGUAGE];
371 char curtone[80]; /* Current tone */
372 unsigned int callgroup;
373 unsigned int pickupgroup;
381 int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
387 int slowsequence; /* MS: Sequence the endpoint as a whole */
389 int iseq; /* Not used? */
390 int lastout; /* tracking this on the subchannels. Is it needed here? */
391 int needdestroy; /* Not used? */
393 int nonCodecCapability;
395 int msgstate; /* voicemail message state */
399 char rqnt_ident[80]; /* SC: request identifier */
400 struct mgcp_request *rqnt_queue; /* SC: pending RQNT commands */
401 ast_mutex_t rqnt_queue_lock;
402 struct mgcp_request *cmd_queue; /* SC: pending commands other than RQNT */
403 ast_mutex_t cmd_queue_lock;
404 int delme; /* SC: needed for reload */
405 int needaudit; /* SC: needed for reload */
406 struct ast_dsp *dsp; /* XXX Should there be a dsp/subchannel? XXX */
407 /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
408 /* struct ast_channel *owner; */
409 /* struct ast_rtp *rtp; */
410 /* struct sockaddr_in tmpdest; */
411 /* message go the the endpoint and not the channel so they stay here */
412 struct mgcp_endpoint *next;
413 struct mgcp_gateway *parent;
416 static struct mgcp_gateway {
417 /* A gateway containing one or more endpoints */
419 int isnamedottedip; /* SC: is the name FQDN or dotted ip */
420 struct sockaddr_in addr;
421 struct sockaddr_in defaddr;
422 struct in_addr ourip;
424 int expire; /* XXX Should we ever expire dynamic registrations? XXX */
425 struct mgcp_endpoint *endpoints;
432 /* JS: Wildcard endpoint name */
434 struct mgcp_message *msgs; /* SC: gw msg queue */
435 ast_mutex_t msgs_lock; /* SC: queue lock */
436 int retransid; /* SC: retrans timer id */
437 int delme; /* SC: needed for reload */
438 struct mgcp_response *responses;
439 struct mgcp_gateway *next;
442 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
443 static int mgcp_reloading = 0;
445 AST_MUTEX_DEFINE_STATIC(gatelock);
447 static int mgcpsock = -1;
449 static struct sockaddr_in bindaddr;
451 static struct ast_frame *mgcp_read(struct ast_channel *ast);
452 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
453 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
454 static int transmit_modify_request(struct mgcp_subchannel *sub);
455 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
456 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
457 static int transmit_connection_del(struct mgcp_subchannel *sub);
458 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
459 static void start_rtp(struct mgcp_subchannel *sub);
460 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
461 int result, unsigned int ident, struct mgcp_request *resp);
462 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
463 static int mgcp_do_reload(void);
464 static int mgcp_reload(int fd, int argc, char *argv[]);
466 static int has_voicemail(struct mgcp_endpoint *p)
468 return ast_app_has_voicemail(p->mailbox, NULL);
471 static int unalloc_sub(struct mgcp_subchannel *sub)
473 struct mgcp_endpoint *p = sub->parent;
475 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
478 ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
481 if (strlen(sub->cxident)) {
482 transmit_connection_del(sub);
484 sub->cxident[0] = '\0';
485 sub->callid[0] = '\0';
486 sub->cxmode = MGCP_CX_INACTIVE;
488 sub->alreadygone = 0;
489 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
491 ast_rtp_destroy(sub->rtp);
494 dump_cmd_queues(NULL, sub); /* SC */
498 /* SC: modified for new transport mechanism */
499 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
502 if (gw->addr.sin_addr.s_addr)
503 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
505 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
507 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
512 static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp)
514 struct mgcp_endpoint *p = sub->parent;
516 char iabuf[INET_ADDRSTRLEN];
518 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));
520 res = __mgcp_xmit(p->parent, resp->buf, resp->len);
526 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
528 struct mgcp_endpoint *p = sub->parent;
530 char iabuf[INET_ADDRSTRLEN];
532 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));
534 res = __mgcp_xmit(p->parent, req->data, req->len);
540 /* SC: modified for new transport framework */
541 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
543 struct mgcp_message *cur, *q = NULL, *w, *prev;
545 ast_mutex_lock(&gw->msgs_lock);
546 prev = NULL, cur = gw->msgs;
548 if (!p || cur->owner_ep == p) {
550 prev->next = cur->next;
552 gw->msgs = cur->next;
554 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
555 gw->name, cur->seqno);
568 prev = cur, cur=cur->next;
571 ast_mutex_unlock(&gw->msgs_lock);
580 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
584 if (!ast_mutex_trylock(&sub->owner->lock)) {
585 ast_queue_frame(sub->owner, f);
586 ast_mutex_unlock(&sub->owner->lock);
589 ast_mutex_unlock(&sub->lock);
591 ast_mutex_lock(&sub->lock);
598 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
602 if (!ast_mutex_trylock(&sub->owner->lock)) {
603 ast_queue_hangup(sub->owner);
604 ast_mutex_unlock(&sub->owner->lock);
607 ast_mutex_unlock(&sub->lock);
609 ast_mutex_lock(&sub->lock);
616 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
618 struct ast_frame f = { AST_FRAME_CONTROL, };
619 f.subclass = control;
620 return mgcp_queue_frame(sub, &f);
623 static int retrans_pkt(void *data)
625 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
626 struct mgcp_message *cur, *exq = NULL, *w, *prev;
631 if (gettimeofday(&tv, NULL) < 0) {
632 /* This shouldn't ever happen, but let's be sure */
633 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
637 t = tv.tv_sec * 1000 + tv.tv_usec / 1000;
639 /* find out expired msgs */
640 ast_mutex_lock(&gw->msgs_lock);
642 prev = NULL, cur = gw->msgs;
644 if (cur->retrans < MAX_RETRANS) {
647 ast_verbose("Retransmitting #%d transaction %u on [%s]\n", cur->retrans, cur->seqno, gw->name);
649 __mgcp_xmit(gw, cur->buf, cur->len);
656 prev->next = cur->next;
658 gw->msgs = cur->next;
660 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", cur->seqno, gw->name);
682 ast_mutex_unlock(&gw->msgs_lock);
686 /* time-out transaction */
687 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
695 /* SC: modified for the new transaction mechanism */
696 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
697 unsigned char *data, int len, unsigned int seqno)
699 struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
700 struct mgcp_message *cur;
701 struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
712 if (gw->messagepending && (gw->lastouttime + 20 < t)) {
713 ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d, lastouttime: %ld, now: %ld. Dumping pending queue\n",
714 gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
715 dump_queue(sub->parent);
718 msg->owner_sub = sub;
724 memcpy(msg->buf, data, msg->len);
726 ast_mutex_lock(&gw->msgs_lock);
736 if (gettimeofday(&tv, NULL) < 0) {
737 /* This shouldn't ever happen, but let's be sure */
738 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
741 msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
743 if (gw->retransid == -1)
744 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
746 ast_mutex_unlock(&gw->msgs_lock);
748 if (!gw->messagepending) {
749 gw->messagepending = 1;
753 __mgcp_xmit(gw, msg->buf, msg->len);
754 /* XXX Should schedule retransmission XXX */
757 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
762 /* SC: modified for new transport */
763 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
764 struct mgcp_request *req, unsigned int seqno)
767 struct mgcp_request **queue, *q, *r, *t;
768 char iabuf[INET_ADDRSTRLEN];
771 ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
772 if (p->slowsequence) {
773 queue = &p->cmd_queue;
774 l = &p->cmd_queue_lock;
779 queue = &sub->cx_queue;
780 l = &sub->cx_queue_lock;
783 /* delete pending cx cmds */
794 queue = &sub->cx_queue;
795 l = &sub->cx_queue_lock;
800 queue = &p->rqnt_queue;
801 l = &p->rqnt_queue_lock;
806 queue = &p->cmd_queue;
807 l = &p->cmd_queue_lock;
812 r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
814 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
818 memcpy(r, req, sizeof(struct mgcp_request));
822 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
823 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
826 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
830 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
831 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
835 /* XXX SC: find tail. We could also keep tail in the data struct for faster access */
836 for (t = *queue; t && t->next; t = t->next);
849 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
852 struct mgcp_endpoint *p;
853 struct mgcp_subchannel *sub;
857 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
861 ast_mutex_lock(&sub->lock);
862 switch (p->hookstate) {
872 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
873 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
874 ast_mutex_unlock(&sub->lock);
880 sub->cxmode = MGCP_CX_RECVONLY;
881 if (p->type == TYPE_LINE) {
885 transmit_modify_request(sub);
888 if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
889 /* try to prevent a callwait from disturbing the other connection */
890 sub->next->cxmode = MGCP_CX_RECVONLY;
891 transmit_modify_request(sub->next);
894 transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
895 ast_setstate(ast, AST_STATE_RINGING);
897 if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
898 /* Put the connection back in sendrecv */
899 sub->next->cxmode = MGCP_CX_SENDRECV;
900 transmit_modify_request(sub->next);
904 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
907 ast_mutex_unlock(&sub->lock);
908 ast_queue_control(ast, AST_CONTROL_RINGING);
912 static int mgcp_hangup(struct ast_channel *ast)
914 struct mgcp_subchannel *sub = ast->pvt->pvt;
915 struct mgcp_endpoint *p = sub->parent;
918 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
919 if (!ast->pvt->pvt) {
920 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
923 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
924 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
928 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
931 if ((p->dtmfmode & MGCP_DTMF_INBAND) && (p->dsp != NULL)){
932 /* SC: check whether other channel is active. */
933 if (!sub->next->owner)
936 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
938 ast_dsp_free(p->dsp);
942 ast_mutex_lock(&sub->lock);
945 if (strlen(sub->cxident)) {
946 transmit_connection_del(sub);
948 sub->cxident[0] = '\0';
949 if ((sub == p->sub) && sub->next->owner) {
950 if (p->hookstate == MGCP_OFFHOOK) {
951 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
952 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);
955 /* set our other connection as the primary and swith over to it */
957 p->sub->cxmode = MGCP_CX_RECVONLY;
958 transmit_modify_request(p->sub);
959 if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
960 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);
964 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
965 transmit_notify_request(sub, "L/v");
966 } else if (p->hookstate == MGCP_OFFHOOK) {
967 transmit_notify_request(sub, "L/ro");
969 transmit_notify_request(sub, "");
972 ast->pvt->pvt = NULL;
973 sub->alreadygone = 0;
975 sub->cxmode = MGCP_CX_INACTIVE;
976 sub->callid[0] = '\0';
977 /* Reset temporary destination */
978 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
980 ast_rtp_destroy(sub->rtp);
984 /* SC: Decrement use count */
985 ast_mutex_lock(&usecnt_lock);
987 ast_mutex_unlock(&usecnt_lock);
988 ast_update_use_count();
989 /* SC: Decrement use count */
991 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
992 if (has_voicemail(p)) {
994 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", ast->name, p->name, p->parent->name);
996 transmit_notify_request(sub, "L/vmwi(+)");
999 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", ast->name, p->name, p->parent->name);
1001 transmit_notify_request(sub, "L/vmwi(-)");
1004 ast_mutex_unlock(&sub->lock);
1008 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
1010 struct mgcp_gateway *g;
1011 struct mgcp_endpoint *e;
1012 int hasendpoints = 0;
1013 char iabuf[INET_ADDRSTRLEN];
1015 return RESULT_SHOWUSAGE;
1016 ast_mutex_lock(&gatelock);
1020 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");
1022 /* JS: Don't show wilcard endpoint */
1023 if (strcmp(e->name, g->wcardep) !=0)
1024 ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
1028 if (!hasendpoints) {
1029 ast_cli(fd, " << No Endpoints Defined >> ");
1033 ast_mutex_unlock(&gatelock);
1034 return RESULT_SUCCESS;
1037 static char show_endpoints_usage[] =
1038 "Usage: mgcp show endpoints\n"
1039 " Lists all endpoints known to the MGCP (Media Gateawy Control Protocol) subsystem.\n";
1041 static struct ast_cli_entry cli_show_endpoints =
1042 { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage };
1044 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
1046 struct mgcp_gateway *g;
1047 struct mgcp_endpoint *e;
1049 char *ename,*gname, *c;
1051 return RESULT_SHOWUSAGE;
1054 return RESULT_SHOWUSAGE;
1055 /* split the name into parts by null */
1059 if (*gname == '@') {
1066 if (gname[0] == '[')
1068 if ((c = strrchr(gname, ']')))
1070 ast_mutex_lock(&gatelock);
1073 if (!strcasecmp(g->name, gname)) {
1076 if (!strcasecmp(e->name, ename)) {
1078 transmit_audit_endpoint(e);
1090 ast_cli(fd, " << Could not find endpoint >> ");
1092 ast_mutex_unlock(&gatelock);
1093 return RESULT_SUCCESS;
1096 static char audit_endpoint_usage[] =
1097 "Usage: mgcp audit endpoint <endpointid>\n"
1098 " List the capabilities of an endpoint in the MGCP (Media Gateawy Control Protocol) subsystem.\n"
1099 " mgcp debug MUST be on to see the results of this command.\n";
1101 static struct ast_cli_entry cli_audit_endpoint =
1102 { { "mgcp", "audit", "endpoint", NULL }, mgcp_audit_endpoint, "Audit specified MGCP endpoint", audit_endpoint_usage };
1104 static int mgcp_answer(struct ast_channel *ast)
1107 struct mgcp_subchannel *sub = ast->pvt->pvt;
1108 struct mgcp_endpoint *p = sub->parent;
1109 ast_mutex_lock(&sub->lock);
1110 sub->cxmode = MGCP_CX_SENDRECV;
1114 transmit_modify_request(sub);
1116 /* SC: verbose level check */
1117 if (option_verbose > 2) {
1118 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n", ast->name, p->name, p->parent->name, sub->id);
1120 if (ast->_state != AST_STATE_UP) {
1121 ast_setstate(ast, AST_STATE_UP);
1123 ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
1124 transmit_notify_request(sub, "");
1125 transmit_modify_request(sub);
1127 ast_mutex_unlock(&sub->lock);
1131 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
1133 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
1134 struct ast_frame *f;
1135 static struct ast_frame null_frame = { AST_FRAME_NULL, };
1136 f = ast_rtp_read(sub->rtp);
1137 /* Don't send RFC2833 if we're not supposed to */
1138 if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
1141 /* We already hold the channel lock */
1142 if (f->frametype == AST_FRAME_VOICE) {
1143 if (f->subclass != sub->owner->nativeformats) {
1144 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1145 sub->owner->nativeformats = f->subclass;
1146 ast_set_read_format(sub->owner, sub->owner->readformat);
1147 ast_set_write_format(sub->owner, sub->owner->writeformat);
1149 /* Courtesy fearnor aka alex@pilosoft.com */
1150 if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
1152 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1154 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1162 static struct ast_frame *mgcp_read(struct ast_channel *ast)
1164 struct ast_frame *f;
1165 struct mgcp_subchannel *sub = ast->pvt->pvt;
1166 ast_mutex_lock(&sub->lock);
1167 f = mgcp_rtp_read(sub);
1168 ast_mutex_unlock(&sub->lock);
1172 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
1174 struct mgcp_subchannel *sub = ast->pvt->pvt;
1176 if (frame->frametype != AST_FRAME_VOICE) {
1177 if (frame->frametype == AST_FRAME_IMAGE)
1180 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
1184 if (!(frame->subclass & ast->nativeformats)) {
1185 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
1186 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
1191 ast_mutex_lock(&sub->lock);
1192 if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
1194 res = ast_rtp_write(sub->rtp, frame);
1197 ast_mutex_unlock(&sub->lock);
1202 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1204 struct mgcp_subchannel *sub = newchan->pvt->pvt;
1205 ast_mutex_lock(&sub->lock);
1206 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
1207 if (sub->owner != oldchan) {
1208 ast_mutex_unlock(&sub->lock);
1209 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1212 sub->owner = newchan;
1213 ast_mutex_unlock(&sub->lock);
1217 static int mgcp_senddigit(struct ast_channel *ast, char digit)
1219 struct mgcp_subchannel *sub = ast->pvt->pvt;
1225 ast_mutex_lock(&sub->lock);
1226 transmit_notify_request(sub, tmp);
1227 ast_mutex_unlock(&sub->lock);
1231 static char *control2str(int ind) {
1233 case AST_CONTROL_HANGUP:
1234 return "Other end has hungup";
1235 case AST_CONTROL_RING:
1236 return "Local ring";
1237 case AST_CONTROL_RINGING:
1238 return "Remote end is ringing";
1239 case AST_CONTROL_ANSWER:
1240 return "Remote end has answered";
1241 case AST_CONTROL_BUSY:
1242 return "Remote end is busy";
1243 case AST_CONTROL_TAKEOFFHOOK:
1244 return "Make it go off hook";
1245 case AST_CONTROL_OFFHOOK:
1246 return "Line is off hook";
1247 case AST_CONTROL_CONGESTION:
1248 return "Congestion (circuits busy)";
1249 case AST_CONTROL_FLASH:
1250 return "Flash hook";
1251 case AST_CONTROL_WINK:
1253 case AST_CONTROL_OPTION:
1254 return "Set a low-level option";
1255 case AST_CONTROL_RADIO_KEY:
1257 case AST_CONTROL_RADIO_UNKEY:
1258 return "Un-Key Radio";
1264 static int mgcp_indicate(struct ast_channel *ast, int ind)
1266 struct mgcp_subchannel *sub = ast->pvt->pvt;
1269 ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n", ind, control2str(ind), ast->name);
1271 ast_mutex_lock(&sub->lock);
1273 case AST_CONTROL_RINGING:
1274 #ifdef DLINK_BUGGY_FIRMWARE
1275 transmit_notify_request(sub, "rt");
1277 transmit_notify_request(sub, "G/rt");
1280 case AST_CONTROL_BUSY:
1281 transmit_notify_request(sub, "L/bz");
1283 case AST_CONTROL_CONGESTION:
1284 transmit_notify_request(sub, "G/cg");
1287 transmit_notify_request(sub, "");
1290 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1293 ast_mutex_unlock(&sub->lock);
1297 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
1299 struct ast_channel *tmp;
1300 struct mgcp_endpoint *i = sub->parent;
1303 tmp = ast_channel_alloc(1);
1305 tmp->nativeformats = i->capability;
1306 if (!tmp->nativeformats)
1307 tmp->nativeformats = capability;
1308 fmt = ast_best_codec(tmp->nativeformats);
1309 snprintf(tmp->name, sizeof(tmp->name), "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1311 tmp->fds[0] = ast_rtp_fd(sub->rtp);
1313 if (i->dtmfmode & MGCP_DTMF_INBAND) {
1314 i->dsp = ast_dsp_new();
1315 ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
1316 /* SC: this is to prevent clipping of dtmf tones during dsp processing */
1317 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
1321 ast_setstate(tmp, state);
1322 if (state == AST_STATE_RING)
1324 tmp->writeformat = fmt;
1325 tmp->pvt->rawwriteformat = fmt;
1326 tmp->readformat = fmt;
1327 tmp->pvt->rawreadformat = fmt;
1328 tmp->pvt->pvt = sub;
1329 tmp->pvt->call = mgcp_call;
1330 tmp->pvt->hangup = mgcp_hangup;
1331 tmp->pvt->answer = mgcp_answer;
1332 tmp->pvt->read = mgcp_read;
1333 tmp->pvt->write = mgcp_write;
1334 tmp->pvt->indicate = mgcp_indicate;
1335 tmp->pvt->fixup = mgcp_fixup;
1336 tmp->pvt->send_digit = mgcp_senddigit;
1337 tmp->pvt->bridge = ast_rtp_bridge;
1338 if (strlen(i->language))
1339 strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
1340 if (strlen(i->accountcode))
1341 strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode)-1);
1343 tmp->amaflags = i->amaflags;
1345 ast_mutex_lock(&usecnt_lock);
1347 ast_mutex_unlock(&usecnt_lock);
1348 ast_update_use_count();
1349 tmp->callgroup = i->callgroup;
1350 tmp->pickupgroup = i->pickupgroup;
1351 strncpy(tmp->call_forward, i->call_forward, sizeof(tmp->call_forward) - 1);
1352 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
1353 strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
1354 if (!ast_strlen_zero(i->cid_num))
1355 tmp->cid.cid_num = strdup(i->cid_num);
1356 if (!ast_strlen_zero(i->cid_name))
1357 tmp->cid.cid_name = strdup(i->cid_name);
1359 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
1361 if (state != AST_STATE_DOWN) {
1362 if (ast_pbx_start(tmp)) {
1363 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
1368 /* SC: verbose level check */
1369 if (option_verbose > 2) {
1370 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n", tmp->name, ast_state2str(state));
1373 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1378 static char* get_sdp_by_line(char* line, char *name, int nameLen) {
1379 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1380 char* r = line + nameLen + 1;
1381 while (*r && (*r < 33)) ++r;
1388 static char *get_sdp(struct mgcp_request *req, char *name) {
1390 int len = strlen(name);
1393 for (x=0; x<req->lines; x++) {
1394 r = get_sdp_by_line(req->line[x], name, len);
1395 if (r[0] != '\0') return r;
1400 static void sdpLineNum_iterator_init(int* iterator) {
1404 static char* get_sdp_iterate(int* iterator,
1405 struct mgcp_request *req, char *name) {
1406 int len = strlen(name);
1408 while (*iterator < req->lines) {
1409 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1410 if (r[0] != '\0') return r;
1415 static char *__get_header(struct mgcp_request *req, char *name, int *start)
1418 int len = strlen(name);
1420 for (x=*start;x<req->headers;x++) {
1421 if (!strncasecmp(req->header[x], name, len) &&
1422 (req->header[x][len] == ':')) {
1423 r = req->header[x] + len + 1;
1424 while(*r && (*r < 33))
1430 /* Don't return NULL, so get_header is always a valid pointer */
1434 static char *get_header(struct mgcp_request *req, char *name)
1437 return __get_header(req, name, &start);
1440 /* SC: get comma separated value */
1441 static char *get_csv(char *c, int *len, char **next)
1445 *next = NULL, *len = 0;
1446 if (!c) return NULL;
1448 while(*c && (*c < 33 || *c == ','))
1452 while(*c && (*c >= 33 && *c != ','))
1457 s = NULL, *next = NULL;
1462 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
1464 struct mgcp_endpoint *p = NULL;
1465 struct mgcp_subchannel *sub = NULL;
1466 struct mgcp_gateway *g;
1467 char iabuf[INET_ADDRSTRLEN];
1469 char *at = NULL, *c;
1472 strncpy(tmp, name, sizeof(tmp) - 1);
1473 at = strchr(tmp, '@');
1475 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1481 ast_mutex_lock(&gatelock);
1482 if (at && (at[0] == '[')) {
1484 c = strrchr(at, ']');
1490 if ((!name || !strcasecmp(g->name, at)) &&
1491 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1492 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1493 if (sin && g->dynamic && name) {
1494 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1495 (g->addr.sin_port != sin->sin_port)) {
1496 memcpy(&g->addr, sin, sizeof(g->addr));
1497 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
1498 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1499 if (option_verbose > 2)
1500 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));
1503 /* SC: not dynamic, check if the name matches */
1505 if (strcasecmp(g->name, at)) {
1510 /* SC: not dynamic, no name, check if the addr matches */
1511 else if (!name && sin) {
1512 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1513 (g->addr.sin_port != sin->sin_port)) {
1526 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n", p->name, g->name);
1528 #if 0 /* SC: new transport mech */
1532 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n", p->name, g->name, sub->id, msgid);
1533 if (sub->lastout == msgid) {
1535 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", sub->id, msgid, sub->lastout);
1540 } while (sub != p->sub);
1550 } else if (name && !strcasecmp(p->name, tmp)) {
1551 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1552 p->name, g->name, p->sub->id);
1560 ast_mutex_lock(&sub->lock);
1566 ast_mutex_unlock(&gatelock);
1570 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp,at);
1572 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1578 static void parse(struct mgcp_request *req)
1580 /* Divide fields by NULL's */
1585 /* First header starts immediately */
1589 /* We've got a new header */
1593 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
1595 if (!strlen(req->header[f])) {
1596 /* Line by itself means we're now in content */
1600 if (f >= MGCP_MAX_HEADERS - 1) {
1601 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1604 req->header[f] = c + 1;
1605 } else if (*c == '\r') {
1606 /* Ignore but eliminate \r's */
1611 /* Check for last header */
1612 if (strlen(req->header[f]))
1615 /* Now we process any mime content */
1620 /* We've got a new line */
1623 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
1625 if (f >= MGCP_MAX_LINES - 1) {
1626 ast_log(LOG_WARNING, "Too many SDP lines...\n");
1629 req->line[f] = c + 1;
1630 } else if (*c == '\r') {
1631 /* Ignore and eliminate \r's */
1636 /* Check for last line */
1637 if (strlen(req->line[f]))
1640 /* Parse up the initial header */
1642 while(*c && *c < 33) c++;
1643 /* First the verb */
1645 while(*c && (*c > 32)) c++;
1649 while(*c && (*c < 33)) c++;
1650 req->identifier = c;
1651 while(*c && (*c > 32)) c++;
1655 while(*c && (*c < 33)) c++;
1657 while(*c && (*c > 32)) c++;
1661 while(*c && (*c < 33)) c++;
1663 while(*c && (*c > 32)) c++;
1664 while(*c && (*c < 33)) c++;
1665 while(*c && (*c > 32)) c++;
1672 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1673 req->verb, req->identifier, req->endpoint, req->version);
1674 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
1677 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1680 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1688 int peercapability, peerNonCodecCapability;
1689 struct sockaddr_in sin;
1691 struct ast_hostent ahp; struct hostent *hp;
1694 struct mgcp_endpoint *p = sub->parent;
1696 /* Get codec and RTP info from SDP */
1697 m = get_sdp(req, "m");
1698 c = get_sdp(req, "c");
1699 if (!strlen(m) || !strlen(c)) {
1700 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1703 if (sscanf(c, "IN IP4 %256s", host) != 1) {
1704 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1707 /* XXX This could block for a long time, and block the main thread! XXX */
1708 hp = ast_gethostbyname(host, &ahp);
1710 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1713 if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
1714 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
1717 sin.sin_family = AF_INET;
1718 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1719 sin.sin_port = htons(portno);
1720 ast_rtp_set_peer(sub->rtp, &sin);
1722 printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
1724 /* Scan through the RTP payload types specified in a "m=" line: */
1725 ast_rtp_pt_clear(sub->rtp);
1727 while(strlen(codecs)) {
1728 if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
1729 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
1732 ast_rtp_set_m_type(sub->rtp, codec);
1736 /* Next, scan through each "a=rtpmap:" line, noting each */
1737 /* specified RTP payload type (with corresponding MIME subtype): */
1738 sdpLineNum_iterator_init(&iterator);
1739 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
1740 char* mimeSubtype = strdup(a); /* ensures we have enough space */
1741 if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
1742 /* Note: should really look at the 'freq' and '#chans' params too */
1743 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
1747 /* Now gather all of the codecs that were asked for: */
1748 ast_rtp_get_current_formats(sub->rtp,
1749 &peercapability, &peerNonCodecCapability);
1750 p->capability = capability & peercapability;
1752 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
1753 capability, peercapability, p->capability);
1754 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
1755 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
1757 if (!p->capability) {
1758 ast_log(LOG_WARNING, "No compatible codecs!\n");
1765 static int add_header(struct mgcp_request *req, char *var, char *value)
1767 if (req->len >= sizeof(req->data) - 4) {
1768 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1772 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
1775 req->header[req->headers] = req->data + req->len;
1776 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
1777 req->len += strlen(req->header[req->headers]);
1778 if (req->headers < MGCP_MAX_HEADERS)
1781 ast_log(LOG_WARNING, "Out of header space\n");
1787 static int add_line(struct mgcp_request *req, char *line)
1789 if (req->len >= sizeof(req->data) - 4) {
1790 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1794 /* Add extra empty return */
1795 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
1796 req->len += strlen(req->data + req->len);
1798 req->line[req->lines] = req->data + req->len;
1799 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
1800 req->len += strlen(req->line[req->lines]);
1801 if (req->lines < MGCP_MAX_LINES)
1804 ast_log(LOG_WARNING, "Out of line space\n");
1810 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1812 /* Initialize a response */
1813 if (req->headers || req->len) {
1814 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1817 req->header[req->headers] = req->data + req->len;
1818 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1819 req->len += strlen(req->header[req->headers]);
1820 if (req->headers < MGCP_MAX_HEADERS)
1823 ast_log(LOG_WARNING, "Out of header space\n");
1827 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1829 /* Initialize a response */
1830 if (req->headers || req->len) {
1831 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1834 req->header[req->headers] = req->data + req->len;
1835 /* SC: check if we need brackets around the gw name */
1836 if (p->parent->isnamedottedip)
1837 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);
1839 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);
1840 req->len += strlen(req->header[req->headers]);
1841 if (req->headers < MGCP_MAX_HEADERS)
1844 ast_log(LOG_WARNING, "Out of header space\n");
1849 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1851 memset(resp, 0, sizeof(*resp));
1852 init_resp(resp, msg, req, msgrest);
1856 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1858 memset(req, 0, sizeof(struct mgcp_request));
1860 if (oseq > 999999999)
1862 init_req(p, req, verb);
1866 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
1868 struct mgcp_request resp;
1869 struct mgcp_endpoint *p = sub->parent;
1870 struct mgcp_response *mgr;
1871 respprep(&resp, p, msg, req, msgrest);
1872 mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
1874 /* Store MGCP response in case we have to retransmit */
1875 memset(mgr, 0, sizeof(struct mgcp_response));
1876 sscanf(req->identifier, "%d", &mgr->seqno);
1877 time(&mgr->whensent);
1878 mgr->len = resp.len;
1879 memcpy(mgr->buf, resp.data, resp.len);
1880 mgr->buf[resp.len] = '\0';
1881 mgr->next = p->parent->responses;
1882 p->parent->responses = mgr;
1884 return send_response(sub, &resp);
1888 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1893 struct sockaddr_in sin;
1901 char iabuf[INET_ADDRSTRLEN];
1903 struct sockaddr_in dest;
1904 struct mgcp_endpoint *p = sub->parent;
1905 /* XXX We break with the "recommendation" and send our IP, in order that our
1906 peer doesn't have to ast_gethostbyname() us XXX */
1909 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1912 ast_rtp_get_us(sub->rtp, &sin);
1914 ast_rtp_get_peer(rtp, &dest);
1916 if (sub->tmpdest.sin_addr.s_addr) {
1917 dest.sin_addr = sub->tmpdest.sin_addr;
1918 dest.sin_port = sub->tmpdest.sin_port;
1919 /* Reset temporary destination */
1920 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1922 dest.sin_addr = p->parent->ourip;
1923 dest.sin_port = sin.sin_port;
1927 ast_verbose("We're at %s port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->ourip), ntohs(sin.sin_port));
1929 snprintf(v, sizeof(v), "v=0\r\n");
1930 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
1931 snprintf(s, sizeof(s), "s=session\r\n");
1932 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(iabuf, sizeof(iabuf), dest.sin_addr));
1933 snprintf(t, sizeof(t), "t=0 0\r\n");
1934 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
1935 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1936 if (p->capability & x) {
1938 ast_verbose("Answering with capability %d\n", x);
1940 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
1942 snprintf(costr, sizeof(costr), " %d", codec);
1943 strncat(m, costr, sizeof(m) - strlen(m) - 1);
1944 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
1945 strncat(a, costr, sizeof(a) - strlen(a) - 1);
1949 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1950 if (p->nonCodecCapability & x) {
1952 ast_verbose("Answering with non-codec capability %d\n", x);
1954 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
1956 snprintf(costr, sizeof(costr), " %d", codec);
1957 strncat(m, costr, sizeof(m) - strlen(m) - 1);
1958 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
1959 strncat(a, costr, sizeof(a) - strlen(a) - 1);
1960 if (x == AST_RTP_DTMF) {
1961 /* Indicate we support DTMF... Not sure about 16, but MSN supports it so dang it, we will too... */
1962 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
1963 strncat(a, costr, sizeof(a) - strlen(a) - 1);
1968 strncat(m, "\r\n", sizeof(m) - strlen(m) - 1);
1969 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
1970 snprintf(costr, sizeof(costr), "%d", len);
1981 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
1983 struct mgcp_request resp;
1988 struct mgcp_endpoint *p = sub->parent;
1989 capability = p->capability;
1991 capability = codecs;
1992 if (!strlen(sub->cxident) && rtp) {
1993 /* We don't have a CXident yet, store the destination and
1995 ast_rtp_get_peer(rtp, &sub->tmpdest);
1998 snprintf(local, sizeof(local), "p:20");
1999 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2000 if (p->capability & x) {
2001 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
2002 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2005 reqprep(&resp, p, "MDCX");
2006 add_header(&resp, "C", sub->callid);
2007 add_header(&resp, "L", local);
2008 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2009 /* SC: X header should not be sent. kept for compatibility */
2010 add_header(&resp, "X", sub->txident);
2011 add_header(&resp, "I", sub->cxident);
2012 /*add_header(&resp, "S", "");*/
2013 ast_rtp_offered_from_local(sub->rtp, 0);
2014 add_sdp(&resp, sub, rtp);
2015 /* SC: fill in new fields */
2016 resp.cmd = MGCP_CMD_MDCX;
2018 return send_request(p, sub, &resp, oseq); /* SC */
2021 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
2023 struct mgcp_request resp;
2027 struct mgcp_endpoint *p = sub->parent;
2029 snprintf(local, sizeof(local), "p:20");
2030 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
2031 if (p->capability & x) {
2032 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
2033 strncat(local, tmp, sizeof(local) - strlen(local) - 1);
2037 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
2038 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2040 reqprep(&resp, p, "CRCX");
2041 add_header(&resp, "C", sub->callid);
2042 add_header(&resp, "L", local);
2043 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2044 /* SC: X header should not be sent. kept for compatibility */
2045 add_header(&resp, "X", sub->txident);
2046 /*add_header(&resp, "S", "");*/
2047 ast_rtp_offered_from_local(sub->rtp, 1);
2048 add_sdp(&resp, sub, rtp);
2049 /* SC: fill in new fields */
2050 resp.cmd = MGCP_CMD_CRCX;
2052 return send_request(p, sub, &resp, oseq); /* SC */
2055 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
2057 struct mgcp_request resp;
2058 struct mgcp_endpoint *p = sub->parent;
2061 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2062 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2064 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
2065 reqprep(&resp, p, "RQNT");
2066 add_header(&resp, "X", p->rqnt_ident); /* SC */
2067 switch (p->hookstate) {
2069 add_header(&resp, "R", "L/hd(N)");
2072 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)");
2076 add_header(&resp, "S", tone);
2078 /* SC: fill in new fields */
2079 resp.cmd = MGCP_CMD_RQNT;
2081 return send_request(p, NULL, &resp, oseq); /* SC */
2084 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
2086 struct mgcp_request resp;
2091 struct mgcp_endpoint *p = sub->parent;
2094 localtime_r(&t,&tm);
2102 /* Keep track of last callerid for blacklist and callreturn */
2103 strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
2105 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
2106 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
2107 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
2108 reqprep(&resp, p, "RQNT");
2109 add_header(&resp, "X", p->rqnt_ident); /* SC */
2110 switch (p->hookstate) {
2112 add_header(&resp, "R", "L/hd(N)");
2115 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)");
2118 if (strlen(tone2)) {
2119 add_header(&resp, "S", tone2);
2122 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2123 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2125 /* SC: fill in new fields */
2126 resp.cmd = MGCP_CMD_RQNT;
2128 return send_request(p, NULL, &resp, oseq); /* SC */
2131 static int transmit_modify_request(struct mgcp_subchannel *sub)
2133 struct mgcp_request resp;
2134 struct mgcp_endpoint *p = sub->parent;
2135 if (!strlen(sub->cxident)) {
2136 /* We don't have a CXident yet, store the destination and
2141 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
2142 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2144 reqprep(&resp, p, "MDCX");
2145 add_header(&resp, "C", sub->callid);
2146 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2147 /* SC: X header should not be sent. kept for compatibility */
2148 add_header(&resp, "X", sub->txident);
2149 add_header(&resp, "I", sub->cxident);
2150 switch (sub->parent->hookstate) {
2152 add_header(&resp, "R", "L/hd(N)");
2155 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)");
2158 /* SC: fill in new fields */
2159 resp.cmd = MGCP_CMD_MDCX;
2161 return send_request(p, sub, &resp, oseq); /* SC */
2165 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
2167 struct mgcp_request resp;
2168 reqprep(&resp, p, "AUEP");
2169 /* SC: removed unknown param VS */
2170 /*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M"); */
2171 add_header(&resp, "F", "A");
2172 /* SC: fill in new fields */
2173 resp.cmd = MGCP_CMD_AUEP;
2175 return send_request(p, NULL, &resp, oseq); /* SC */
2178 static int transmit_connection_del(struct mgcp_subchannel *sub)
2180 struct mgcp_endpoint *p = sub->parent;
2181 struct mgcp_request resp;
2183 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2184 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2186 reqprep(&resp, p, "DLCX");
2187 /* SC: check if call id is avail */
2189 add_header(&resp, "C", sub->callid);
2190 /* SC: X header should not be sent. kept for compatibility */
2191 add_header(&resp, "X", sub->txident);
2192 /* SC: check if cxident is avail */
2193 if (sub->cxident[0])
2194 add_header(&resp, "I", sub->cxident);
2195 /* SC: fill in new fields */
2196 resp.cmd = MGCP_CMD_DLCX;
2198 return send_request(p, sub, &resp, oseq); /* SC */
2201 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
2203 struct mgcp_request resp;
2205 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
2206 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2208 reqprep(&resp, p, "DLCX");
2209 /* SC: check if call id is avail */
2210 if (callid && *callid)
2211 add_header(&resp, "C", callid);
2212 /* SC: check if cxident is avail */
2213 if (cxident && *cxident)
2214 add_header(&resp, "I", cxident);
2215 /* SC: fill in new fields */
2216 resp.cmd = MGCP_CMD_DLCX;
2218 return send_request(p, p->sub, &resp, oseq);
2221 /* SC: cleanup pendng commands */
2222 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
2224 struct mgcp_request *t, *q;
2227 ast_mutex_lock(&p->rqnt_queue_lock);
2228 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
2229 p->rqnt_queue = NULL;
2230 ast_mutex_unlock(&p->rqnt_queue_lock);
2232 ast_mutex_lock(&p->cmd_queue_lock);
2233 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
2234 p->cmd_queue = NULL;
2235 ast_mutex_unlock(&p->cmd_queue_lock);
2237 ast_mutex_lock(&p->sub->cx_queue_lock);
2238 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
2239 p->sub->cx_queue = NULL;
2240 ast_mutex_unlock(&p->sub->cx_queue_lock);
2242 ast_mutex_lock(&p->sub->next->cx_queue_lock);
2243 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
2244 p->sub->next->cx_queue = NULL;
2245 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
2248 ast_mutex_lock(&sub->cx_queue_lock);
2249 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
2250 sub->cx_queue = NULL;
2251 ast_mutex_unlock(&sub->cx_queue_lock);
2256 /* SC: remove command transaction from queue */
2257 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2258 struct mgcp_request **queue, ast_mutex_t *l, int ident)
2260 struct mgcp_request *prev, *req;
2261 char iabuf[INET_ADDRSTRLEN];
2264 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2265 if (req->trid == ident) {
2266 /* remove from queue */
2270 prev->next = req->next;
2272 /* send next pending command */
2275 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2276 ast_inet_ntoa(iabuf, sizeof(iabuf), p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2279 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2284 ast_mutex_unlock(l);
2288 /* SC: modified for new transport mechanism */
2289 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2290 int result, unsigned int ident, struct mgcp_request *resp)
2293 struct mgcp_request *req;
2294 struct mgcp_gateway *gw = p->parent;
2297 /* provisional response */
2301 if (p->slowsequence)
2302 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2304 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2305 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2306 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2309 if (option_verbose > 2) {
2310 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
2316 if (p && (result >= 400) && (result <= 599)) {
2319 p->hookstate = MGCP_OFFHOOK;
2322 p->hookstate = MGCP_ONHOOK;
2325 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
2328 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
2334 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2335 result, p->name, p->parent->name, sub ? sub->id:-1);
2336 mgcp_queue_hangup(sub);
2340 if (p->sub->next->owner) {
2341 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2342 result, p->name, p->parent->name, sub ? sub->id:-1);
2343 mgcp_queue_hangup(p->sub);
2346 if (p->sub->owner) {
2347 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2348 result, p->name, p->parent->name, sub ? sub->id:-1);
2349 mgcp_queue_hangup(p->sub);
2352 dump_cmd_queues(p, NULL);
2357 if (req->cmd == MGCP_CMD_CRCX) {
2358 if ((c = get_header(resp, "I"))) {
2359 if (strlen(c) && sub) {
2360 /* SC: if we are hanging up do not process this conn. */
2362 if (strlen(sub->cxident)) {
2363 if (strcasecmp(c, sub->cxident)) {
2364 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2367 strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
2368 if (sub->tmpdest.sin_addr.s_addr) {
2369 transmit_modify_with_sdp(sub, NULL, 0);
2373 /* XXX SC: delete this one
2374 callid and conn id may already be lost.
2375 so the following del conn may have a side effect of
2376 cleaning up the next subchannel */
2377 transmit_connection_del(sub);
2383 if (req->cmd == MGCP_CMD_AUEP) {
2384 /* SC: check stale connection ids */
2385 if ((c = get_header(resp, "I"))) {
2388 while ((v = get_csv(c, &len, &n))) {
2390 if(strncasecmp(v, p->sub->cxident, len) &&
2391 strncasecmp(v, p->sub->next->cxident, len)) {
2392 /* connection id not found. delete it */
2394 memcpy(cxident, v, len);
2395 cxident[len] = '\0';
2396 if (option_verbose > 2) {
2397 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
2398 cxident, p->name, gw->name);
2400 transmit_connection_del_w_params(p, NULL, cxident);
2407 /* Try to determine the hookstate returned from an audit endpoint command */
2408 if ((c = get_header(resp, "ES"))) {
2410 if (strstr(c, "hu")) {
2411 if (p->hookstate != MGCP_ONHOOK) {
2412 /* SC: XXX cleanup if we think we are offhook XXX */
2413 if ((p->sub->owner || p->sub->next->owner ) &&
2414 p->hookstate == MGCP_OFFHOOK)
2415 mgcp_queue_hangup(sub);
2416 p->hookstate = MGCP_ONHOOK;
2418 /* SC: update the requested events according to the new hookstate */
2419 transmit_notify_request(p->sub, "");
2421 /* SC: verbose level check */
2422 if (option_verbose > 2) {
2423 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2426 } else if (strstr(c, "hd")) {
2427 if (p->hookstate != MGCP_OFFHOOK) {
2428 p->hookstate = MGCP_OFFHOOK;
2430 /* SC: update the requested events according to the new hookstate */
2431 transmit_notify_request(p->sub, "");
2433 /* SC: verbose level check */
2434 if (option_verbose > 2) {
2435 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2443 if (resp && resp->lines) {
2444 /* SC: do not process sdp if we are hanging up. this may be a late response */
2445 if (sub && sub->owner) {
2449 process_sdp(sub, resp);
2457 static void start_rtp(struct mgcp_subchannel *sub)
2459 ast_mutex_lock(&sub->lock);
2460 /* SC: check again to be on the safe side */
2462 ast_rtp_destroy(sub->rtp);
2465 /* Allocate the RTP now */
2466 sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
2467 if (sub->rtp && sub->owner)
2468 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2470 ast_rtp_setnat(sub->rtp, sub->nat);
2472 ast_rtp_set_callback(p->rtp, rtpready);
2473 ast_rtp_set_data(p->rtp, p);
2475 /* Make a call*ID */
2476 snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
2477 /* Transmit the connection create */
2478 transmit_connect_with_sdp(sub, NULL);
2479 ast_mutex_unlock(&sub->lock);
2482 static void *mgcp_ss(void *data)
2484 struct ast_channel *chan = data;
2485 struct mgcp_subchannel *sub = chan->pvt->pvt;
2486 struct mgcp_endpoint *p = sub->parent;
2487 char exten[AST_MAX_EXTENSION] = "";
2489 int timeout = firstdigittimeout;
2492 while(len < AST_MAX_EXTENSION-1) {
2493 res = ast_waitfordigit(chan, timeout);
2496 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
2497 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2498 ast_indicate(chan, -1);
2505 if (!ast_ignore_pattern(chan->context, exten)) {
2506 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2507 ast_indicate(chan, -1);
2509 /* XXX Redundant? We should already be playing dialtone */
2510 /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2511 transmit_notify_request(sub, "L/dl");
2513 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
2514 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
2516 /* Record this as the forwarding extension */
2517 strncpy(p->call_forward, exten, sizeof(p->call_forward) - 1);
2518 if (option_verbose > 2) {
2519 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
2520 p->call_forward, chan->name);
2522 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2523 transmit_notify_request(sub, "L/sl");
2527 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2528 ast_indicate(chan, -1);
2530 memset(exten, 0, sizeof(exten));
2531 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2532 transmit_notify_request(sub, "L/dl");
2536 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2537 ast_indicate(chan, -1);
2538 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
2539 if (!ast_strlen_zero(p->cid_num)) {
2540 if (!p->hidecallerid) {
2541 /* SC: free existing chan->callerid */
2542 if (chan->cid.cid_num)
2543 free(chan->cid.cid_num);
2544 chan->cid.cid_num = strdup(p->cid_num);
2545 /* SC: free existing chan->callerid */
2546 if (chan->cid.cid_name)
2547 free(chan->cid.cid_name);
2548 chan->cid.cid_name = strdup(p->cid_name);
2550 if (chan->cid.cid_ani)
2551 free(chan->cid.cid_ani);
2552 chan->cid.cid_ani = strdup(p->cid_num);
2554 ast_setstate(chan, AST_STATE_RING);
2555 /*zt_enable_ec(p);*/
2556 res = ast_pbx_run(chan);
2558 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2559 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2560 /*transmit_notify_request(p, "nbz", 1);*/
2561 transmit_notify_request(sub, "G/cg");
2566 /* It's a match, but they just typed a digit, and there is an ambiguous match,
2567 so just set the timeout to matchdigittimeout and wait some more */
2568 timeout = matchdigittimeout;
2570 } else if (res == 0) {
2571 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
2572 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2573 transmit_notify_request(sub, "G/cg");
2574 /*zt_wait_event(p->subs[index].zfd);*/
2577 } else if (p->callwaiting && !strcmp(exten, "*70")) {
2578 if (option_verbose > 2) {
2579 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
2581 /* Disable call waiting if enabled */
2583 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2584 transmit_notify_request(sub, "L/sl");
2586 memset(exten, 0, sizeof(exten));
2587 timeout = firstdigittimeout;
2589 } else if (!strcmp(exten,ast_pickup_ext())) {
2590 /* Scan all channels and see if any there
2591 * ringing channqels with that have call groups
2592 * that equal this channels pickup group
2594 if (ast_pickup_call(chan)) {
2595 ast_log(LOG_WARNING, "No call pickup possible...\n");
2596 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2597 transmit_notify_request(sub, "G/cg");
2602 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
2603 if (option_verbose > 2) {
2604 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
2606 /* Disable Caller*ID if enabled */
2607 p->hidecallerid = 1;
2608 if (chan->cid.cid_num)
2609 free(chan->cid.cid_num);
2610 chan->cid.cid_num = NULL;
2611 if (chan->cid.cid_name)
2612 free(chan->cid.cid_name);
2613 chan->cid.cid_name = NULL;
2614 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2615 transmit_notify_request(sub, "L/sl");
2617 memset(exten, 0, sizeof(exten));
2618 timeout = firstdigittimeout;
2619 } else if (p->callreturn && !strcmp(exten, "*69")) {
2621 if (strlen(p->lastcallerid)) {
2622 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
2625 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2626 transmit_notify_request(sub, "L/sl");
2628 } else if (!strcmp(exten, "*78")) {
2629 /* Do not disturb */
2630 if (option_verbose > 2) {
2631 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
2633 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2634 transmit_notify_request(sub, "L/sl");
2637 memset(exten, 0, sizeof(exten));
2639 } else if (!strcmp(exten, "*79")) {
2640 /* Do not disturb */
2641 if (option_verbose > 2) {
2642 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
2644 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2645 transmit_notify_request(sub, "L/sl");
2648 memset(exten, 0, sizeof(exten));
2650 } else if (p->cancallforward && !strcmp(exten, "*72")) {
2651 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2652 transmit_notify_request(sub, "L/sl");
2654 memset(exten, 0, sizeof(exten));
2656 } else if (p->cancallforward && !strcmp(exten, "*73")) {
2657 if (option_verbose > 2) {
2658 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
2660 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2661 transmit_notify_request(sub, "L/sl");
2662 memset(p->call_forward, 0, sizeof(p->call_forward));
2664 memset(exten, 0, sizeof(exten));
2666 } else if (!strcmp(exten, ast_parking_ext()) &&
2668 ast_bridged_channel(sub->next->owner)) {
2669 /* This is a three way call, the main call being a real channel,
2670 and we're parking the first call. */
2671 ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
2672 if (option_verbose > 2) {
2673 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
2676 } else if (strlen(p->lastcallerid) && !strcmp(exten, "*60")) {
2677 if (option_verbose > 2) {
2678 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
2680 res = ast_db_put("blacklist", p->lastcallerid, "1");
2682 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2683 transmit_notify_request(sub, "L/sl");
2684 memset(exten, 0, sizeof(exten));
2687 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
2688 if (option_verbose > 2) {
2689 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
2691 /* Enable Caller*ID if enabled */
2692 p->hidecallerid = 0;
2693 if (chan->cid.cid_num)
2694 free(chan->cid.cid_num);
2695 if (!ast_strlen_zero(p->cid_num))
2696 chan->cid.cid_num = strdup(p->cid_num);
2697 if (chan->cid.cid_name)
2698 free(chan->cid.cid_name);
2699 if (!ast_strlen_zero(p->cid_name))
2700 chan->cid.cid_name = strdup(p->cid_name);
2701 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2702 transmit_notify_request(sub, "L/sl");
2704 memset(exten, 0, sizeof(exten));
2705 timeout = firstdigittimeout;
2706 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
2707 ((exten[0] != '*') || (strlen(exten) > 2))) {
2709 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);
2713 timeout = gendigittimeout;
2714 if (len && !ast_ignore_pattern(chan->context, exten))
2715 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
2716 ast_indicate(chan, -1);
2720 res = ast_waitfordigit(chan, to);
2722 ast_log(LOG_DEBUG, "Timeout...\n");
2726 ast_log(LOG_DEBUG, "Got hangup...\n");
2731 if (!ast_ignore_pattern(chan->context, exten))
2732 ast_indicate(chan, -1);
2733 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
2734 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
2741 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
2742 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
2746 ast_setstate(chan, AST_STATE_RING);
2748 if (ast_pbx_run(chan)) {
2749 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
2758 static int attempt_transfer(struct mgcp_endpoint *p)
2760 /* *************************
2761 * I hope this works.
2762 * Copied out of chan_zap
2763 * Cross your fingers
2764 * *************************/
2766 /* In order to transfer, we need at least one of the channels to
2767 actually be in a call bridge. We can't conference two applications
2768 together (but then, why would we want to?) */
2769 if (ast_bridged_channel(p->sub->owner)) {
2770 /* The three-way person we're about to transfer to could still be in MOH, so
2771 stop if now if appropriate */
2772 if (ast_bridged_channel(p->sub->next->owner))
2773 ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
2774 if (p->sub->owner->_state == AST_STATE_RINGING) {
2775 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
2777 if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
2778 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2779 ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
2782 /* Orphan the channel */
2783 unalloc_sub(p->sub->next);
2784 } else if (ast_bridged_channel(p->sub->next->owner)) {
2785 if (p->sub->owner->_state == AST_STATE_RINGING) {
2786 ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
2788 ast_moh_stop(ast_bridged_channel(p->sub->next->owner));
2789 if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
2790 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2791 ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
2794 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
2795 if (option_verbose > 2) {
2796 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);
2798 p->sub = p->sub->next;
2799 unalloc_sub(p->sub->next);
2800 /* Tell the caller not to hangup */
2803 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
2804 p->sub->owner->name, p->sub->next->owner->name);
2805 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2806 if (p->sub->next->owner) {
2807 p->sub->next->alreadygone = 1;
2808 mgcp_queue_hangup(p->sub->next);
2814 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
2816 struct mgcp_endpoint *p = sub->parent;
2817 struct ast_channel *c;
2819 pthread_attr_t attr;
2820 pthread_attr_init(&attr);
2821 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2823 /* Off hook / answer */
2824 if (sub->outgoing) {
2827 if (ast_bridged_channel(sub->owner)) {
2828 ast_moh_stop(ast_bridged_channel(sub->owner));
2830 sub->cxmode = MGCP_CX_SENDRECV;
2834 transmit_modify_request(sub);
2836 /*transmit_notify_request(sub, "aw");*/
2837 transmit_notify_request(sub, "");
2838 mgcp_queue_control(sub, AST_CONTROL_ANSWER);
2842 /*sub->cxmode = MGCP_CX_SENDRECV;*/
2847 transmit_modify_request(sub);
2850 /* The channel is immediately up. Start right away */
2851 #ifdef DLINK_BUGGY_FIRMWARE
2852 transmit_notify_request(sub, "rt");
2854 transmit_notify_request(sub, "G/rt");
2856 c = mgcp_new(sub, AST_STATE_RING);
2858 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
2859 transmit_notify_request(sub, "G/cg");
2863 if (has_voicemail(p)) {
2864 transmit_notify_request(sub, "L/sl");
2866 transmit_notify_request(sub, "L/dl");
2868 c = mgcp_new(sub, AST_STATE_DOWN);
2870 if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
2871 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
2875 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
2879 if (p->hookstate == MGCP_OFFHOOK) {
2880 ast_log(LOG_WARNING, "Off hook, but already have owner on %s@%s\n", p->name, p->parent->name);
2882 ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name);
2883 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
2885 if (ast_bridged_channel(sub->owner)) {
2886 ast_moh_stop(ast_bridged_channel(sub->owner));
2888 sub->cxmode = MGCP_CX_SENDRECV;
2892 transmit_modify_request(sub);
2894 /*transmit_notify_request(sub, "aw");*/
2895 transmit_notify_request(sub, "");
2896 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
2901 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
2904 struct ast_frame f = { 0, };
2905 struct mgcp_endpoint *p = sub->parent;
2906 struct mgcp_gateway *g = NULL;
2907 char iabuf[INET_ADDRSTRLEN];
2910 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
2912 /* Clear out potential response */
2913 if (!strcasecmp(req->verb, "RSIP")) {
2914 /* Test if this RSIP request is just a keepalive */
2915 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
2916 if (option_verbose > 2)
2917 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
2918 transmit_response(sub, "200", req, "OK");
2920 dump_queue(p->parent, p);
2921 dump_cmd_queues(p, NULL);
2923 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
2924 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
2926 /* JS: For RSIP on wildcard we reset all endpoints */
2927 if (!strcmp(p->name, p->parent->wcardep)) {
2928 /* Reset all endpoints */
2929 struct mgcp_endpoint *tmp_ep;
2932 tmp_ep = g->endpoints;
2934 /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) { */
2935 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
2936 struct mgcp_subchannel *tmp_sub, *first_sub;
2937 if (option_verbose > 2) {
2938 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
2941 first_sub = tmp_ep->sub;
2942 tmp_sub = tmp_ep->sub;
2944 mgcp_queue_hangup(tmp_sub);
2945 tmp_sub = tmp_sub->next;
2946 if (tmp_sub == first_sub)
2950 tmp_ep = tmp_ep->next;
2952 } else if (sub->owner) {
2953 mgcp_queue_hangup(sub);
2955 transmit_response(sub, "200", req, "OK");
2956 /* JS: We dont send NTFY or AUEP to wildcard ep */
2957 if (strcmp(p->name, p->parent->wcardep) != 0) {
2958 transmit_notify_request(sub, "");
2959 /* SC: Audit endpoint.
2960 Idea is to prevent lost lines due to race conditions
2962 transmit_audit_endpoint(p);
2965 } else if (!strcasecmp(req->verb, "NTFY")) {
2966 /* Acknowledge and be sure we keep looking for the same things */
2967 transmit_response(sub, "200", req, "OK");
2968 /* Notified of an event */
2969 ev = get_header(req, "O");
2970 s = strchr(ev, '/');
2972 if (option_verbose > 2) {
2973 ast_verbose(VERBOSE_PREFIX_3 "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
2975 /* Keep looking for events unless this was a hangup */
2976 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
2977 transmit_notify_request(sub, p->curtone);
2979 if (!strcasecmp(ev, "hd")) {
2980 p->hookstate = MGCP_OFFHOOK;
2981 sub->cxmode = MGCP_CX_SENDRECV;
2982 handle_hd_hf(sub, ev);
2983 } else if (!strcasecmp(ev, "hf")) {
2984 /* We can assume we are offhook if we received a hookflash */
2985 /* First let's just do call wait and ignore threeway */
2986 /* We're currently in charge */
2987 if (p->hookstate != MGCP_OFFHOOK) {
2988 /* Cisco c7940 sends hf even if the phone is onhook */
2989 /* Thanks to point on IRC for pointing this out */
2992 /* do not let * confrnce two down channels */
2993 if( sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1;
2995 if (p->callwaiting || p->transfer || p->threewaycalling) {
2996 if (option_verbose > 2) {
2997 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);
2999 p->sub = p->sub->next;
3001 /* transfer control to our next subchannel */
3002 if (!sub->next->owner) {
3003 /* plave the first call on hold and start up a new call */
3004 sub->cxmode = MGCP_CX_MUTE;
3005 if (option_verbose > 2) {
3006 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3008 transmit_modify_request(sub);
3009 if (sub->owner && ast_bridged_channel(sub->owner)) {
3010 ast_moh_start(ast_bridged_channel(sub->owner), NULL);
3012 sub->next->cxmode = MGCP_CX_RECVONLY;
3013 handle_hd_hf(sub->next, ev);
3014 } else if (sub->owner && sub->next->owner) {
3015 /* We've got two active calls lets decide whether or not to conference or just flip flop */
3016 if ((!sub->outgoing) && (!sub->next->outgoing)) {
3017 /* We made both calls lets conferenct */
3018 if (option_verbose > 2) {
3019 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n",
3020 sub->id, sub->next->id, p->name, p->parent->name);
3022 sub->cxmode = MGCP_CX_CONF;
3023 sub->next->cxmode = MGCP_CX_CONF;
3024 if (ast_bridged_channel(sub->next->owner))
3025 ast_moh_stop(ast_bridged_channel(sub->next->owner));
3026 transmit_modify_request(sub);
3027 transmit_modify_request(sub->next);
3029 /* Let's flipflop between calls */
3030 /* XXX Need to check for state up ??? */
3031 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
3032 if (option_verbose > 2) {
3033 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
3034 sub->id, sub->next->id, p->name, p->parent->name);
3036 sub->cxmode = MGCP_CX_MUTE;
3037 if (option_verbose > 2) {
3038 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
3040 transmit_modify_request(sub);
3041 if (ast_bridged_channel(sub->owner))
3042 ast_moh_start(ast_bridged_channel(sub->owner), NULL);
3044 if (ast_bridged_channel(sub->next->owner))
3045 ast_moh_stop(ast_bridged_channel(sub->next->owner));
3047 handle_hd_hf(sub->next, ev);
3049 if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) {
3050 handle_hd_hf(sub->next, ev);
3052 ast_verbose(VERBOSE_PREFIX_3 "MGCP Unmuting %d on %s@%s\n", sub->next->id, p->name, p->parent->name);
3053 sub->next->cxmode = MGCP_CX_SENDRECV;
3054 transmit_modify_request(sub->next);
3059 /* We've most likely lost one of our calls find an active call and bring it up */
3062 } else if (sub->next->owner) {
3065 /* We seem to have lost both our calls */
3066 /* XXX - What do we do now? */
3069 if (ast_bridged_channel(p->sub->owner)) {
3070 ast_moh_stop(ast_bridged_channel(p->sub->owner));
3072 p->sub->cxmode = MGCP_CX_SENDRECV;
3073 transmit_modify_request(p->sub);
3076 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
3077 p->name, p->parent->name);
3079 /* ast_moh_stop(sub->owner->bridge); */
3080 } else if (!strcasecmp(ev, "hu")) {
3081 p->hookstate = MGCP_ONHOOK;
3082 sub->cxmode = MGCP_CX_RECVONLY;
3083 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
3084 /* JS: Do we need to send MDCX before a DLCX ?
3086 transmit_modify_request(sub);
3089 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
3090 /* We're allowed to transfer, we have two avtive calls and */
3091 /* we made at least one of the calls. Let's try and transfer */
3092 ast_mutex_lock(&p->sub->next->lock);
3093 res = attempt_transfer(p);
3095 if (p->sub->next->owner) {
3096 sub->next->alreadygone = 1;
3097 mgcp_queue_hangup(sub->next);
3100 ast_log(LOG_WARNING, "Transfer attempt failed\n");
3101 ast_mutex_unlock(&p->sub->next->lock);
3104 ast_mutex_unlock(&p->sub->next->lock);
3106 /* Hangup the current call */
3107 /* If there is another active call, mgcp_hangup will ring the phone with the other call */
3109 sub->alreadygone = 1;
3110 mgcp_queue_hangup(sub);
3112 /* SC: verbose level check */
3113 if (option_verbose > 2) {
3114 if (option_verbose > 2) {
3115 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
3116 p->name, p->parent->name, sub->id);
3118 /* Instruct the other side to remove the connection since it apparently *
3119 * still thinks the channel is active. *
3120 * For Cisco IAD2421 /BAK/ */
3121 transmit_connection_del(sub);
3125 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
3126 if (has_voicemail(p)) {
3127 if (option_verbose > 2) {
3128 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
3130 transmit_notify_request(sub, "L/vmwi(+)");
3132 if (option_verbose > 2) {
3133 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
3135 transmit_notify_request(sub, "L/vmwi(-)");
3138 } else if ((strlen(ev) == 1) &&
3139 (((ev[0] >= '0') && (ev[0] <= '9')) ||
3140 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
3141 (ev[0] == '*') || (ev[0] == '#'))) {
3142 f.frametype = AST_FRAME_DTMF;
3146 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
3147 mgcp_queue_frame(sub, &f);