2 * Asterisk -- A telephony toolkit for Linux.
4 * Implementation of Media Gateway Control Protocol
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
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
51 #include <asterisk/lock.h>
52 #include <asterisk/channel.h>
53 #include <asterisk/channel_pvt.h>
54 #include <asterisk/config.h>
55 #include <asterisk/logger.h>
56 #include <asterisk/module.h>
57 #include <asterisk/pbx.h>
58 #include <asterisk/options.h>
59 #include <asterisk/lock.h>
60 #include <asterisk/sched.h>
61 #include <asterisk/io.h>
62 #include <asterisk/rtp.h>
63 #include <asterisk/acl.h>
64 #include <asterisk/callerid.h>
65 #include <asterisk/cli.h>
66 #include <asterisk/say.h>
67 #include <asterisk/cdr.h>
68 #include <asterisk/astdb.h>
69 #include <asterisk/parking.h>
70 #include <asterisk/app.h>
71 #include <asterisk/musiconhold.h>
72 #include <sys/socket.h>
73 #include <sys/ioctl.h>
80 #include <arpa/inet.h>
81 #include <sys/signal.h>
84 #include <netinet/in_systm.h>
85 #include <netinet/ip.h>
87 #include <asterisk/dsp.h>
91 #define IPTOS_MINCOST 0x02
95 #define DEFAULT_EXPIREY 120
96 #define MAX_EXPIREY 3600
99 static char *desc = "Media Gateway Control Protocol (MGCP)";
100 static char *type = "MGCP";
101 static char *tdesc = "Media Gateway Control Protocol (MGCP)";
102 static char *config = "mgcp.conf";
104 #define DEFAULT_MGCP_GW_PORT 2427/* From RFC 2705 */
105 #define DEFAULT_MGCP_CA_PORT 2727/* From RFC 2705 */
106 #define MGCP_MAX_PACKET 1500 /* Also from RFC 2543, should sub headers tho */
107 #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */
108 #define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
110 /* MGCP rtp stream modes */
111 #define MGCP_CX_SENDONLY 0
112 #define MGCP_CX_RECVONLY 1
113 #define MGCP_CX_SENDRECV 2
114 #define MGCP_CX_CONF 3
115 #define MGCP_CX_CONFERENCE 3
116 #define MGCP_CX_MUTE 4
117 #define MGCP_CX_INACTIVE 4
119 static char *mgcp_cxmodes[] = {
127 /* SC: MGCP commands */
128 #define MGCP_CMD_EPCF 0
129 #define MGCP_CMD_CRCX 1
130 #define MGCP_CMD_MDCX 2
131 #define MGCP_CMD_DLCX 3
132 #define MGCP_CMD_RQNT 4
133 #define MGCP_CMD_NTFY 5
134 #define MGCP_CMD_AUEP 6
135 #define MGCP_CMD_AUCX 7
136 #define MGCP_CMD_RSIP 8
138 static char context[AST_MAX_EXTENSION] = "default";
140 static char language[MAX_LANGUAGE] = "";
141 static char musicclass[MAX_LANGUAGE] = "";
142 static char callerid[AST_MAX_EXTENSION] = "";
144 static int inbanddtmf = 0;
147 /* Not used. Dosn't hurt for us to always send cid */
148 /* to the mgcp box. */
149 /* static int use_callerid = 1;*/
150 /*static int cur_signalling = -1;*/
152 /*static unsigned int cur_group = 0;*/
153 static unsigned int cur_callergroup = 0;
154 static unsigned int cur_pickupgroup = 0;
156 /* XXX Is this needed? */
157 /* Doesn't look like the dsp stuff for */
158 /* inbanddtmf is actually hooked up. */
159 /* static int relaxdtmf = 0; */
163 static int immediate = 0;
165 static int callwaiting = 0;
167 /* Not used. Dosn't hurt for us to always send cid */
168 /* to the mgcp box. */
169 /*static int callwaitingcallerid = 0;*/
171 /*static int hidecallerid = 0;*/
173 static int callreturn = 0;
175 static int threewaycalling = 0;
177 /* This is for flashhook transfers */
178 static int transfer = 0;
180 static int cancallforward = 0;
182 static int canreinvite = CANREINVITE;
184 /*static int busycount = 3;*/
186 /*static int callprogress = 0;*/
188 static char accountcode[20] = "";
190 static char mailbox[AST_MAX_EXTENSION];
192 static int amaflags = 0;
197 static int usecnt =0;
198 static ast_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
199 /* SC: transaction id should always be positive */
200 static unsigned int oseq;
202 /* Wait up to 16 seconds for first digit (FXO logic) */
203 static int firstdigittimeout = 16000;
205 /* How long to wait for following digits (FXO logic) */
206 static int gendigittimeout = 8000;
208 /* How long to wait for an extra digit, if there is an ambiguous match */
209 static int matchdigittimeout = 3000;
211 /* Protect the monitoring thread, so only one process can kill or start it, and not
212 when it's doing something critical. */
213 static ast_mutex_t netlock = AST_MUTEX_INITIALIZER;
215 static ast_mutex_t monlock = AST_MUTEX_INITIALIZER;
217 /* This is the thread for the monitor which checks for input on the channels
218 which are not currently in use. */
219 static pthread_t monitor_thread = AST_PTHREADT_NULL;
221 static int restart_monitor(void);
223 /* Just about everybody seems to support ulaw, so make it a nice default */
224 static int capability = AST_FORMAT_ULAW;
225 static int nonCodecCapability = AST_RTP_DTMF;
227 static char ourhost[256];
228 static struct in_addr __ourip;
231 static int mgcpdebug = 0;
233 static struct sched_context *sched;
234 static struct io_context *io;
235 /* The private structures of the mgcp channels are linked for
236 selecting outgoing channels */
238 #define MGCP_MAX_HEADERS 64
239 #define MGCP_MAX_LINES 64
241 struct mgcp_request {
247 int headers; /* MGCP Headers */
248 char *header[MGCP_MAX_HEADERS];
249 int lines; /* SDP Content */
250 char *line[MGCP_MAX_LINES];
251 char data[MGCP_MAX_PACKET];
252 int cmd; /* SC: int version of verb = command */
253 unsigned int trid; /* SC: int version of identifier = transaction id */
254 struct mgcp_request *next; /* SC: next in the queue */
258 static struct mgcp_pkt {
260 struct mgcp_endpoint *owner;
262 char data[MGCP_MAX_PACKET];
263 struct mgcp_pkt *next;
267 /* MGCP message for queuing up */
268 struct mgcp_message {
269 struct mgcp_endpoint *owner_ep;
270 struct mgcp_subchannel *owner_sub;
272 unsigned long expire;
275 struct mgcp_message *next;
276 unsigned char buf[0];
284 struct mgcp_subchannel {
285 /* SC: subchannel magic string.
286 Needed to prove that any subchannel pointer passed by asterisk
287 really points to a valid subchannel memory area.
288 Ugly.. But serves the purpose for the time being.
290 #define MGCP_SUBCHANNEL_MAGIC "!978!"
294 struct ast_channel *owner;
295 struct mgcp_endpoint *parent;
297 struct sockaddr_in tmpdest;
298 char txident[80]; /* FIXME SC: txident is replaced by rqnt_ident in endpoint.
299 This should be obsoleted */
307 struct mgcp_request *cx_queue; /* SC: pending CX commands */
308 ast_mutex_t cx_queue_lock; /* SC: CX queue lock */
310 int iseq; /* Not used? RTP? */
315 struct mgcp_message *msgs;
317 struct mgcp_subchannel *next; /* for out circular linked list */
320 #define MGCP_ONHOOK 1
321 #define MGCP_OFFHOOK 2
326 struct mgcp_endpoint {
329 struct mgcp_subchannel *sub; /* pointer to our current connection, channel and stuff */
330 char accountcode[80];
331 char exten[AST_MAX_EXTENSION]; /* Extention where to start */
332 char context[AST_MAX_EXTENSION];
333 char language[MAX_LANGUAGE];
334 char callerid[AST_MAX_EXTENSION]; /* Caller*ID */
335 char lastcallerid[AST_MAX_EXTENSION]; /* Last Caller*ID */
336 char call_forward[AST_MAX_EXTENSION]; /* Last Caller*ID */
337 char mailbox[AST_MAX_EXTENSION];
338 char musicclass[MAX_LANGUAGE];
339 char curtone[80]; /* Current tone */
340 unsigned int callgroup;
341 unsigned int pickupgroup;
348 int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
355 int iseq; /* Not used? */
356 int lastout; /* tracking this on the subchannels. Is it needed here? */
357 int needdestroy; /* Not used? */
359 int nonCodecCapability;
361 int msgstate; /* voicemail message state */
365 char rqnt_ident[80]; /* SC: request identifier */
366 struct mgcp_request *rqnt_queue; /* SC: pending RQNT commands */
367 ast_mutex_t rqnt_queue_lock;
368 struct mgcp_request *cmd_queue; /* SC: pending commands other than RQNT */
369 ast_mutex_t cmd_queue_lock;
370 int delme; /* SC: needed for reload */
371 int needaudit; /* SC: needed for reload */
372 struct ast_dsp *dsp; /* XXX Should there be a dsp/subchannel? XXX */
373 /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
374 /* struct ast_channel *owner; */
375 /* struct ast_rtp *rtp; */
376 /* struct sockaddr_in tmpdest; */
377 /* message go the the endpoint and not the channel so they stay here */
378 struct mgcp_endpoint *next;
379 struct mgcp_gateway *parent;
382 static struct mgcp_gateway {
383 /* A gateway containing one or more endpoints */
385 int isnamedottedip; /* SC: is the name FQDN or dotted ip */
386 struct sockaddr_in addr;
387 struct sockaddr_in defaddr;
388 struct in_addr ourip;
390 int expire; /* XXX Should we ever expire dynamic registrations? XXX */
391 struct mgcp_endpoint *endpoints;
398 /* JS: Wildcard endpoint name */
400 struct mgcp_message *msgs; /* SC: gw msg queue */
401 ast_mutex_t msgs_lock; /* SC: queue lock */
402 int retransid; /* SC: retrans timer id */
403 int delme; /* SC: needed for reload */
404 struct mgcp_gateway *next;
407 static ast_mutex_t mgcp_reload_lock = AST_MUTEX_INITIALIZER;
408 static int mgcp_reloading = 0;
410 static ast_mutex_t gatelock = AST_MUTEX_INITIALIZER;
412 static int mgcpsock = -1;
414 static struct sockaddr_in bindaddr;
416 static struct ast_frame *mgcp_read(struct ast_channel *ast);
417 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
418 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
419 static int transmit_modify_request(struct mgcp_subchannel *sub);
420 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callerid);
421 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp);
422 static int transmit_connection_del(struct mgcp_subchannel *sub);
423 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
424 static void start_rtp(struct mgcp_subchannel *sub);
425 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
426 int result, unsigned int ident, struct mgcp_request *resp);
427 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
428 static int mgcp_do_reload(void);
429 static int mgcp_reload(int fd, int argc, char *argv[]);
431 static int has_voicemail(struct mgcp_endpoint *p)
433 return ast_app_has_voicemail(p->mailbox);
436 static int unalloc_sub(struct mgcp_subchannel *sub)
438 struct mgcp_endpoint *p = sub->parent;
440 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
443 ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
446 if (strlen(sub->cxident)) {
447 transmit_connection_del(sub);
449 sub->cxident[0] = '\0';
450 sub->callid[0] = '\0';
451 sub->cxmode = MGCP_CX_INACTIVE;
453 sub->alreadygone = 0;
454 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
456 ast_rtp_destroy(sub->rtp);
459 dump_cmd_queues(NULL, sub); /* SC */
463 /* SC: modified for new transport mechanism */
464 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
467 if (gw->addr.sin_addr.s_addr)
468 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
470 res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
472 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
477 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
479 struct mgcp_endpoint *p = sub->parent;
482 ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
484 res = __mgcp_xmit(p->parent, req->data, req->len);
490 /* SC: modified for new transport framework */
491 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
493 struct mgcp_message *cur, *q = NULL, *w, *prev;
495 ast_mutex_lock(&gw->msgs_lock);
496 prev = NULL, cur = gw->msgs;
498 if (!p || cur->owner_ep == p) {
500 prev->next = cur->next;
502 gw->msgs = cur->next;
504 ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
505 gw->name, cur->seqno);
518 prev = cur, cur=cur->next;
521 ast_mutex_unlock(&gw->msgs_lock);
530 static int retrans_pkt(void *data)
532 struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
533 struct mgcp_message *cur, *exq = NULL, *w, *prev;
538 if (gettimeofday(&tv, NULL) < 0) {
539 /* This shouldn't ever happen, but let's be sure */
540 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
544 t = tv.tv_sec * 1000 + tv.tv_usec / 1000;
546 /* find out expired msgs */
547 ast_mutex_lock(&gw->msgs_lock);
549 prev = NULL, cur = gw->msgs;
551 if (cur->retrans < MAX_RETRANS) {
554 ast_verbose("Retransmitting #%d transaction %u on [%s]\n", cur->retrans, cur->seqno, gw->name);
556 __mgcp_xmit(gw, cur->buf, cur->len);
563 prev->next = cur->next;
565 gw->msgs = cur->next;
567 ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", cur->seqno, gw->name);
589 ast_mutex_unlock(&gw->msgs_lock);
593 /* time-out transaction */
594 handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
602 /* SC: modified for the new transaction mechanism */
603 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
604 unsigned char *data, int len, unsigned int seqno)
606 struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
607 struct mgcp_message *cur;
608 struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
619 if (gw->messagepending && (gw->lastouttime + 20 < t)) {
620 ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d, lastouttime: %ld, now: %ld. Dumping pending queue\n",
621 gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
622 dump_queue(sub->parent);
625 msg->owner_sub = sub;
631 memcpy(msg->buf, data, msg->len);
633 ast_mutex_lock(&gw->msgs_lock);
643 if (gettimeofday(&tv, NULL) < 0) {
644 /* This shouldn't ever happen, but let's be sure */
645 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
648 msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
650 if (gw->retransid == -1)
651 gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
653 ast_mutex_unlock(&gw->msgs_lock);
655 if (!gw->messagepending) {
656 gw->messagepending = 1;
660 __mgcp_xmit(gw, msg->buf, msg->len);
661 /* XXX Should schedule retransmission XXX */
664 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
669 /* SC: modified for new transport */
670 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
671 struct mgcp_request *req, unsigned int seqno)
674 struct mgcp_request **queue, *q, *r, *t;
679 queue = &sub->cx_queue;
680 l = &sub->cx_queue_lock;
683 /* delete pending cx cmds */
694 queue = &sub->cx_queue;
695 l = &sub->cx_queue_lock;
700 queue = &p->rqnt_queue;
701 l = &p->rqnt_queue_lock;
706 queue = &p->cmd_queue;
707 l = &p->cmd_queue_lock;
712 r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
714 ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
718 memcpy(r, req, sizeof(struct mgcp_request));
722 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data,
723 inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
726 res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
730 ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data,
731 inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
735 /* XXX SC: find tail. We could also keep tail in the data struct for faster access */
736 for (t = *queue; t && t->next; t = t->next);
749 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
752 struct mgcp_endpoint *p;
753 struct mgcp_subchannel *sub;
757 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
762 switch (p->hookstate) {
772 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
773 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
779 sub->cxmode = MGCP_CX_RECVONLY;
780 if (p->type == TYPE_LINE) {
784 transmit_modify_request(sub);
787 if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
788 /* try to prevent a callwait from disturbing the other connection */
789 sub->next->cxmode = MGCP_CX_RECVONLY;
790 transmit_modify_request(sub->next);
793 transmit_notify_request_with_callerid(sub, tone, ast->callerid);
794 ast_setstate(ast, AST_STATE_RINGING);
795 ast_queue_control(ast, AST_CONTROL_RINGING);
797 if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
798 /* Put the connection back in sendrecv */
799 sub->next->cxmode = MGCP_CX_SENDRECV;
800 transmit_modify_request(sub->next);
804 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
810 static int mgcp_hangup(struct ast_channel *ast)
812 struct mgcp_subchannel *sub = ast->pvt->pvt;
813 struct mgcp_endpoint *p = sub->parent;
816 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
817 if (!ast->pvt->pvt) {
818 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
821 if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
822 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
826 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
829 if ((p->dtmfinband) && (p->dsp != NULL)){
830 /* SC: check whether other channel is active. */
831 if (!sub->next->owner)
834 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
836 ast_dsp_free(p->dsp);
840 ast_mutex_lock(&sub->lock);
843 if (strlen(sub->cxident)) {
844 transmit_connection_del(sub);
846 strcpy(sub->cxident, "");
847 if ((sub == p->sub) && sub->next->owner) {
848 if (p->hookstate == MGCP_OFFHOOK) {
849 if (sub->next->owner && sub->next->owner->bridge) {
850 transmit_notify_request_with_callerid(p->sub, "L/wt", sub->next->owner->bridge->callerid);
853 /* set our other connection as the primary and swith over to it */
855 p->sub->cxmode = MGCP_CX_RECVONLY;
856 transmit_modify_request(p->sub);
857 if (sub->next->owner && sub->next->owner->bridge) {
858 transmit_notify_request_with_callerid(p->sub, "L/rg", sub->next->owner->callerid);
862 } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
863 transmit_notify_request(sub, "L/v");
864 } else if (p->hookstate == MGCP_OFFHOOK) {
865 transmit_notify_request(sub, "L/ro");
867 transmit_notify_request(sub, "");
870 ast->pvt->pvt = NULL;
871 sub->alreadygone = 0;
873 sub->cxmode = MGCP_CX_INACTIVE;
874 strcpy(sub->callid, "");
875 /* Reset temporary destination */
876 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
878 ast_rtp_destroy(sub->rtp);
882 /* SC: Decrement use count */
883 ast_mutex_lock(&usecnt_lock);
885 ast_mutex_unlock(&usecnt_lock);
886 ast_update_use_count();
887 /* SC: Decrement use count */
889 if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
890 if (has_voicemail(p)) {
892 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", ast->name, p->name, p->parent->name);
894 transmit_notify_request(sub, "L/vmwi(+)");
897 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", ast->name, p->name, p->parent->name);
899 transmit_notify_request(sub, "L/vmwi(-)");
902 ast_mutex_unlock(&sub->lock);
906 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
908 struct mgcp_gateway *g;
909 struct mgcp_endpoint *e;
910 int hasendpoints = 0;
912 return RESULT_SHOWUSAGE;
913 ast_mutex_lock(&gatelock);
917 ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? inet_ntoa(g->addr.sin_addr) : inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
919 // JS: Don't show wilcard endpoint
920 if (strcmp(e->name, g->wcardep) !=0)
921 ast_cli(fd, " -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
926 ast_cli(fd, " << No Endpoints Defined >> ");
930 ast_mutex_unlock(&gatelock);
931 return RESULT_SUCCESS;
934 static char show_endpoints_usage[] =
935 "Usage: mgcp show endpoints\n"
936 " Lists all endpoints known to the MGCP (Media Gateawy Control Protocol) subsystem.\n";
938 static struct ast_cli_entry cli_show_endpoints =
939 { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage };
941 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
943 struct mgcp_gateway *g;
944 struct mgcp_endpoint *e;
946 char *ename,*gname, *c;
948 return RESULT_SHOWUSAGE;
951 return RESULT_SHOWUSAGE;
952 /* split the name into parts by null */
965 if ((c = strrchr(gname, ']')))
967 ast_mutex_lock(&gatelock);
970 if (!strcasecmp(g->name, gname)) {
973 if (!strcasecmp(e->name, ename)) {
975 transmit_audit_endpoint(e);
987 ast_cli(fd, " << Could not find endpoint >> ");
989 ast_mutex_unlock(&gatelock);
990 return RESULT_SUCCESS;
993 static char audit_endpoint_usage[] =
994 "Usage: mgcp audit endpoint <endpointid>\n"
995 " List the capabilities of an endpoint in the MGCP (Media Gateawy Control Protocol) subsystem.\n"
996 " mgcp debug MUST be on to see the results of this command.\n";
998 static struct ast_cli_entry cli_audit_endpoint =
999 { { "mgcp", "audit", "endpoint", NULL }, mgcp_audit_endpoint, "Audit specified MGCP endpoint", audit_endpoint_usage };
1001 static int mgcp_answer(struct ast_channel *ast)
1004 struct mgcp_subchannel *sub = ast->pvt->pvt;
1005 struct mgcp_endpoint *p = sub->parent;
1006 sub->cxmode = MGCP_CX_SENDRECV;
1010 transmit_modify_request(sub);
1012 /* SC: verbose level check */
1013 if (option_verbose > 2) {
1014 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n", ast->name, p->name, p->parent->name, sub->id);
1016 if (ast->_state != AST_STATE_UP) {
1017 ast_setstate(ast, AST_STATE_UP);
1019 ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
1020 transmit_notify_request(sub, "");
1021 transmit_modify_request(sub);
1026 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
1028 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
1029 struct ast_frame *f;
1030 f = ast_rtp_read(sub->rtp);
1032 /* We already hold the channel lock */
1033 if (f->frametype == AST_FRAME_VOICE) {
1034 if (f->subclass != sub->owner->nativeformats) {
1035 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1036 sub->owner->nativeformats = f->subclass;
1037 ast_set_read_format(sub->owner, sub->owner->readformat);
1038 ast_set_write_format(sub->owner, sub->owner->writeformat);
1040 /* Courtesy fearnor aka alex@pilosoft.com */
1041 if (sub->parent->dtmfinband) {
1043 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1045 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1053 static struct ast_frame *mgcp_read(struct ast_channel *ast)
1055 struct ast_frame *fr;
1056 struct mgcp_subchannel *sub = ast->pvt->pvt;
1057 ast_mutex_lock(&sub->lock);
1058 fr = mgcp_rtp_read(sub);
1059 ast_mutex_unlock(&sub->lock);
1063 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
1065 struct mgcp_subchannel *sub = ast->pvt->pvt;
1067 if (frame->frametype != AST_FRAME_VOICE) {
1068 if (frame->frametype == AST_FRAME_IMAGE)
1071 ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
1075 if (!(frame->subclass & ast->nativeformats)) {
1076 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
1077 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
1082 ast_mutex_lock(&sub->lock);
1084 res = ast_rtp_write(sub->rtp, frame);
1086 ast_mutex_unlock(&sub->lock);
1091 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1093 struct mgcp_subchannel *sub = newchan->pvt->pvt;
1094 ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
1095 if (sub->owner != oldchan) {
1096 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1099 sub->owner = newchan;
1103 static int mgcp_senddigit(struct ast_channel *ast, char digit)
1105 struct mgcp_subchannel *sub = ast->pvt->pvt;
1109 transmit_notify_request(sub, tmp);
1113 static char *control2str(int ind) {
1115 case AST_CONTROL_HANGUP:
1116 return "Other end has hungup";
1117 case AST_CONTROL_RING:
1118 return "Local ring";
1119 case AST_CONTROL_RINGING:
1120 return "Remote end is ringing";
1121 case AST_CONTROL_ANSWER:
1122 return "Remote end has answered";
1123 case AST_CONTROL_BUSY:
1124 return "Remote end is busy";
1125 case AST_CONTROL_TAKEOFFHOOK:
1126 return "Make it go off hook";
1127 case AST_CONTROL_OFFHOOK:
1128 return "Line is off hook";
1129 case AST_CONTROL_CONGESTION:
1130 return "Congestion (circuits busy)";
1131 case AST_CONTROL_FLASH:
1132 return "Flash hook";
1133 case AST_CONTROL_WINK:
1135 case AST_CONTROL_OPTION:
1136 return "Set a low-level option";
1137 case AST_CONTROL_RADIO_KEY:
1139 case AST_CONTROL_RADIO_UNKEY:
1140 return "Un-Key Radio";
1146 static int mgcp_indicate(struct ast_channel *ast, int ind)
1148 struct mgcp_subchannel *sub = ast->pvt->pvt;
1150 ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n", ind, control2str(ind), ast->name);
1153 case AST_CONTROL_RINGING:
1154 transmit_notify_request(sub, "G/rt");
1156 case AST_CONTROL_BUSY:
1157 transmit_notify_request(sub, "L/bz");
1159 case AST_CONTROL_CONGESTION:
1160 transmit_notify_request(sub, "G/cg");
1163 transmit_notify_request(sub, "");
1166 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1172 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
1174 struct ast_channel *tmp;
1175 struct mgcp_endpoint *i = sub->parent;
1178 tmp = ast_channel_alloc(1);
1180 tmp->nativeformats = i->capability;
1181 if (!tmp->nativeformats)
1182 tmp->nativeformats = capability;
1183 fmt = ast_best_codec(tmp->nativeformats);
1184 snprintf(tmp->name, sizeof(tmp->name), "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1186 tmp->fds[0] = ast_rtp_fd(sub->rtp);
1188 if (i->dtmfinband) {
1189 i->dsp = ast_dsp_new();
1190 ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
1191 /* SC: this is to prevent clipping of dtmf tones during dsp processing */
1192 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
1196 ast_setstate(tmp, state);
1197 if (state == AST_STATE_RING)
1199 tmp->writeformat = fmt;
1200 tmp->pvt->rawwriteformat = fmt;
1201 tmp->readformat = fmt;
1202 tmp->pvt->rawreadformat = fmt;
1203 tmp->pvt->pvt = sub;
1204 tmp->pvt->call = mgcp_call;
1205 tmp->pvt->hangup = mgcp_hangup;
1206 tmp->pvt->answer = mgcp_answer;
1207 tmp->pvt->read = mgcp_read;
1208 tmp->pvt->write = mgcp_write;
1209 tmp->pvt->indicate = mgcp_indicate;
1210 tmp->pvt->fixup = mgcp_fixup;
1211 tmp->pvt->send_digit = mgcp_senddigit;
1212 tmp->pvt->bridge = ast_rtp_bridge;
1213 if (strlen(i->language))
1214 strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
1215 if (strlen(i->accountcode))
1216 strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode)-1);
1218 tmp->amaflags = i->amaflags;
1220 ast_mutex_lock(&usecnt_lock);
1222 ast_mutex_unlock(&usecnt_lock);
1223 ast_update_use_count();
1224 tmp->callgroup = i->callgroup;
1225 tmp->pickupgroup = i->pickupgroup;
1226 strncpy(tmp->call_forward, i->call_forward, sizeof(tmp->call_forward));
1227 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
1228 strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
1229 if (strlen(i->callerid))
1230 tmp->callerid = strdup(i->callerid);
1232 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
1234 if (state != AST_STATE_DOWN) {
1235 if (ast_pbx_start(tmp)) {
1236 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
1241 /* SC: verbose level check */
1242 if (option_verbose > 2) {
1243 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n", tmp->name, ast_state2str(state));
1246 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1251 static char* get_sdp_by_line(char* line, char *name, int nameLen) {
1252 if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1253 char* r = line + nameLen + 1;
1254 while (*r && (*r < 33)) ++r;
1261 static char *get_sdp(struct mgcp_request *req, char *name) {
1263 int len = strlen(name);
1266 for (x=0; x<req->lines; x++) {
1267 r = get_sdp_by_line(req->line[x], name, len);
1268 if (r[0] != '\0') return r;
1273 static void sdpLineNum_iterator_init(int* iterator) {
1277 static char* get_sdp_iterate(int* iterator,
1278 struct mgcp_request *req, char *name) {
1279 int len = strlen(name);
1281 while (*iterator < req->lines) {
1282 r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1283 if (r[0] != '\0') return r;
1288 static char *__get_header(struct mgcp_request *req, char *name, int *start)
1291 int len = strlen(name);
1293 for (x=*start;x<req->headers;x++) {
1294 if (!strncasecmp(req->header[x], name, len) &&
1295 (req->header[x][len] == ':')) {
1296 r = req->header[x] + len + 1;
1297 while(*r && (*r < 33))
1303 /* Don't return NULL, so get_header is always a valid pointer */
1307 static char *get_header(struct mgcp_request *req, char *name)
1310 return __get_header(req, name, &start);
1313 /* SC: get comma separated value */
1314 static char *get_csv(char *c, int *len, char **next)
1318 *next = NULL, *len = 0;
1319 if (!c) return NULL;
1321 while(*c && (*c < 33 || *c == ','))
1325 while(*c && (*c >= 33 && *c != ','))
1330 s = NULL, *next = NULL;
1336 static int rtpready(struct ast_rtp *rtp, struct ast_frame *f, void *data)
1338 /* Just deliver the audio directly */
1339 struct mgcp_endpoint *p = data;
1340 ast_mutex_lock(&p->lock);
1342 /* Generally, you lock in the order channel lock, followed by private
1343 lock. Since here we are doing the reverse, there is the possibility
1344 of deadlock. As a result, in the case of a deadlock, we simply fail out
1346 if (!ast_mutex_trylock(&p->owner->lock)) {
1347 if (f->frametype == AST_FRAME_VOICE) {
1348 if (f->subclass != p->owner->nativeformats) {
1349 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1350 p->owner->nativeformats = f->subclass;
1351 ast_set_read_format(p->owner, p->owner->readformat);
1352 ast_set_write_format(p->owner, p->owner->writeformat);
1354 if (p->dtmfinband) {
1355 f = ast_dsp_process(p->owner,p->dsp,f);
1358 ast_queue_frame(p->owner, f);
1359 ast_mutex_unlock(&p->owner->lock);
1362 ast_mutex_unlock(&p->lock);
1367 static struct mgcp_subchannel *find_subchannel(char *name, int msgid, struct sockaddr_in *sin)
1369 struct mgcp_endpoint *p = NULL;
1370 struct mgcp_subchannel *sub = NULL;
1371 struct mgcp_gateway *g;
1373 char *at = NULL, *c;
1376 strncpy(tmp, name, sizeof(tmp) - 1);
1377 at = strchr(tmp, '@');
1379 ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1385 ast_mutex_lock(&gatelock);
1386 if (at && (at[0] == '[')) {
1388 c = strrchr(at, ']');
1394 if ((!name || !strcasecmp(g->name, at)) &&
1395 (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1396 /* Found the gateway. If it's dynamic, save it's address -- now for the endpoint */
1397 if (sin && g->dynamic && name) {
1398 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1399 (g->addr.sin_port != sin->sin_port)) {
1400 memcpy(&g->addr, sin, sizeof(g->addr));
1401 if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
1402 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1403 if (option_verbose > 2)
1404 ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
1407 /* SC: not dynamic, check if the name matches */
1409 if (strcasecmp(g->name, at)) {
1414 /* SC: not dynamic, no name, check if the addr matches */
1415 else if (!name && sin) {
1416 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1417 (g->addr.sin_port != sin->sin_port)) {
1430 ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n", p->name, g->name);
1432 #if 0 /* SC: new transport mech */
1436 ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n", p->name, g->name, sub->id, msgid);
1437 if (sub->lastout == msgid) {
1439 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", sub->id, msgid, sub->lastout);
1444 } while (sub != p->sub);
1454 } else if (name && !strcasecmp(p->name, tmp)) {
1455 ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
1456 p->name, g->name, p->sub->id);
1469 ast_mutex_unlock(&gatelock);
1473 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp,at);
1475 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1481 static void parse(struct mgcp_request *req)
1483 /* Divide fields by NULL's */
1488 /* First header starts immediately */
1492 /* We've got a new header */
1496 printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
1498 if (!strlen(req->header[f])) {
1499 /* Line by itself means we're now in content */
1503 if (f >= MGCP_MAX_HEADERS - 1) {
1504 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1507 req->header[f] = c + 1;
1508 } else if (*c == '\r') {
1509 /* Ignore but eliminate \r's */
1514 /* Check for last header */
1515 if (strlen(req->header[f]))
1518 /* Now we process any mime content */
1523 /* We've got a new line */
1526 printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
1528 if (f >= MGCP_MAX_LINES - 1) {
1529 ast_log(LOG_WARNING, "Too many SDP lines...\n");
1532 req->line[f] = c + 1;
1533 } else if (*c == '\r') {
1534 /* Ignore and eliminate \r's */
1539 /* Check for last line */
1540 if (strlen(req->line[f]))
1543 /* Parse up the initial header */
1545 while(*c && *c < 33) c++;
1546 /* First the verb */
1548 while(*c && (*c > 32)) c++;
1552 while(*c && (*c < 33)) c++;
1553 req->identifier = c;
1554 while(*c && (*c > 32)) c++;
1558 while(*c && (*c < 33)) c++;
1560 while(*c && (*c > 32)) c++;
1564 while(*c && (*c < 33)) c++;
1566 while(*c && (*c > 32)) c++;
1567 while(*c && (*c < 33)) c++;
1568 while(*c && (*c > 32)) c++;
1575 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1576 req->verb, req->identifier, req->endpoint, req->version);
1577 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
1580 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1583 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1591 int peercapability, peerNonCodecCapability;
1592 struct sockaddr_in sin;
1594 struct ast_hostent ahp; struct hostent *hp;
1597 struct mgcp_endpoint *p = sub->parent;
1599 /* Get codec and RTP info from SDP */
1600 m = get_sdp(req, "m");
1601 c = get_sdp(req, "c");
1602 if (!strlen(m) || !strlen(c)) {
1603 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1606 if (sscanf(c, "IN IP4 %256s", host) != 1) {
1607 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1610 /* XXX This could block for a long time, and block the main thread! XXX */
1611 hp = ast_gethostbyname(host, &ahp);
1613 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1616 if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
1617 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
1620 sin.sin_family = AF_INET;
1621 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1622 sin.sin_port = htons(portno);
1623 ast_rtp_set_peer(sub->rtp, &sin);
1625 printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1627 // Scan through the RTP payload types specified in a "m=" line:
1628 ast_rtp_pt_clear(sub->rtp);
1630 while(strlen(codecs)) {
1631 if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
1632 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
1635 ast_rtp_set_m_type(sub->rtp, codec);
1639 // Next, scan through each "a=rtpmap:" line, noting each
1640 // specified RTP payload type (with corresponding MIME subtype):
1641 sdpLineNum_iterator_init(&iterator);
1642 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
1643 char* mimeSubtype = strdup(a); // ensures we have enough space
1644 if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
1645 // Note: should really look at the 'freq' and '#chans' params too
1646 ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
1650 // Now gather all of the codecs that were asked for:
1651 ast_rtp_get_current_formats(sub->rtp,
1652 &peercapability, &peerNonCodecCapability);
1653 p->capability = capability & peercapability;
1655 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
1656 capability, peercapability, p->capability);
1657 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
1658 nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
1660 if (!p->capability) {
1661 ast_log(LOG_WARNING, "No compatible codecs!\n");
1668 static int add_header(struct mgcp_request *req, char *var, char *value)
1670 if (req->len >= sizeof(req->data) - 4) {
1671 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1675 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
1678 req->header[req->headers] = req->data + req->len;
1679 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
1680 req->len += strlen(req->header[req->headers]);
1681 if (req->headers < MGCP_MAX_HEADERS)
1684 ast_log(LOG_WARNING, "Out of header space\n");
1690 static int add_line(struct mgcp_request *req, char *line)
1692 if (req->len >= sizeof(req->data) - 4) {
1693 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1697 /* Add extra empty return */
1698 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
1699 req->len += strlen(req->data + req->len);
1701 req->line[req->lines] = req->data + req->len;
1702 snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
1703 req->len += strlen(req->line[req->lines]);
1704 if (req->lines < MGCP_MAX_LINES)
1707 ast_log(LOG_WARNING, "Out of line space\n");
1713 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1715 /* Initialize a response */
1716 if (req->headers || req->len) {
1717 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1720 req->header[req->headers] = req->data + req->len;
1721 snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1722 req->len += strlen(req->header[req->headers]);
1723 if (req->headers < MGCP_MAX_HEADERS)
1726 ast_log(LOG_WARNING, "Out of header space\n");
1730 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1732 /* Initialize a response */
1733 if (req->headers || req->len) {
1734 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1737 req->header[req->headers] = req->data + req->len;
1738 /* SC: check if we need brackets around the gw name */
1739 if (p->parent->isnamedottedip)
1740 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);
1742 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);
1743 req->len += strlen(req->header[req->headers]);
1744 if (req->headers < MGCP_MAX_HEADERS)
1747 ast_log(LOG_WARNING, "Out of header space\n");
1752 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1754 memset(resp, 0, sizeof(*resp));
1755 init_resp(resp, msg, req, msgrest);
1759 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1761 memset(req, 0, sizeof(struct mgcp_request));
1763 init_req(p, req, verb);
1767 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
1769 struct mgcp_request resp;
1770 struct mgcp_endpoint *p = sub->parent;
1771 respprep(&resp, p, msg, req, msgrest);
1772 return send_response(sub, &resp);
1776 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1781 struct sockaddr_in sin;
1790 struct sockaddr_in dest;
1791 struct mgcp_endpoint *p = sub->parent;
1792 /* XXX We break with the "recommendation" and send our IP, in order that our
1793 peer doesn't have to ast_gethostbyname() us XXX */
1796 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1799 ast_rtp_get_us(sub->rtp, &sin);
1801 ast_rtp_get_peer(rtp, &dest);
1803 if (sub->tmpdest.sin_addr.s_addr) {
1804 dest.sin_addr = sub->tmpdest.sin_addr;
1805 dest.sin_port = sub->tmpdest.sin_port;
1806 /* Reset temporary destination */
1807 memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1809 dest.sin_addr = p->parent->ourip;
1810 dest.sin_port = sin.sin_port;
1814 ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
1816 snprintf(v, sizeof(v), "v=0\r\n");
1817 snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
1818 snprintf(s, sizeof(s), "s=session\r\n");
1819 snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", inet_ntoa(dest.sin_addr));
1820 snprintf(t, sizeof(t), "t=0 0\r\n");
1821 snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
1822 for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1823 if (p->capability & x) {
1825 ast_verbose("Answering with capability %d\n", x);
1827 codec = ast_rtp_lookup_code(sub->rtp, 1, x);
1829 snprintf(costr, sizeof(costr), " %d", codec);
1831 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
1836 for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1837 if (p->nonCodecCapability & x) {
1839 ast_verbose("Answering with non-codec capability %d\n", x);
1841 codec = ast_rtp_lookup_code(sub->rtp, 0, x);
1843 snprintf(costr, sizeof(costr), " %d", codec);
1845 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
1847 if (x == AST_RTP_DTMF) {
1848 /* Indicate we support DTMF... Not sure about 16, but MSN supports it so dang it, we will too... */
1849 snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
1856 len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
1857 snprintf(costr, sizeof(costr), "%d", len);
1868 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1870 struct mgcp_request resp;
1874 struct mgcp_endpoint *p = sub->parent;
1875 if (!strlen(sub->cxident) && rtp) {
1876 /* We don't have a CXident yet, store the destination and
1878 ast_rtp_get_peer(rtp, &sub->tmpdest);
1881 snprintf(local, sizeof(local), "p:20");
1882 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1883 if (p->capability & x) {
1884 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1888 reqprep(&resp, p, "MDCX");
1889 add_header(&resp, "C", sub->callid);
1890 add_header(&resp, "L", local);
1891 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1892 /* SC: X header should not be sent. kept for compatibility */
1893 add_header(&resp, "X", sub->txident);
1894 add_header(&resp, "I", sub->cxident);
1895 /*add_header(&resp, "S", "");*/
1896 add_sdp(&resp, sub, rtp);
1897 /* SC: fill in new fields */
1898 resp.cmd = MGCP_CMD_MDCX;
1900 return send_request(p, sub, &resp, oseq); /* SC */
1903 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1905 struct mgcp_request resp;
1909 struct mgcp_endpoint *p = sub->parent;
1911 snprintf(local, sizeof(local), "p:20");
1912 for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1913 if (p->capability & x) {
1914 snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1919 ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
1920 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
1922 reqprep(&resp, p, "CRCX");
1923 add_header(&resp, "C", sub->callid);
1924 add_header(&resp, "L", local);
1925 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1926 /* SC: X header should not be sent. kept for compatibility */
1927 add_header(&resp, "X", sub->txident);
1928 /*add_header(&resp, "S", "");*/
1929 add_sdp(&resp, sub, rtp);
1930 /* SC: fill in new fields */
1931 resp.cmd = MGCP_CMD_CRCX;
1933 return send_request(p, sub, &resp, oseq); /* SC */
1936 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
1938 struct mgcp_request resp;
1939 struct mgcp_endpoint *p = sub->parent;
1942 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
1943 tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
1945 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1946 reqprep(&resp, p, "RQNT");
1947 add_header(&resp, "X", p->rqnt_ident); /* SC */
1948 switch (p->hookstate) {
1950 add_header(&resp, "R", "L/hd(N)");
1953 add_header(&resp, "R", "L/hu(N), L/hf(N), D/[0-9#*](N)");
1957 add_header(&resp, "S", tone);
1959 /* SC: fill in new fields */
1960 resp.cmd = MGCP_CMD_RQNT;
1962 return send_request(p, NULL, &resp, oseq); /* SC */
1965 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callerid)
1967 struct mgcp_request resp;
1973 struct mgcp_endpoint *p = sub->parent;
1976 localtime_r(&t,&tm);
1978 strncpy(cid, callerid, sizeof(cid) - 1);
1981 ast_callerid_parse(cid, &n, &l);
1983 ast_shrink_phone_number(l);
1984 if (!ast_isphonenumber(l)) {
1994 /* Keep track of last callerid for blacklist and callreturn */
1995 strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
1997 snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
1998 tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
1999 strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
2000 reqprep(&resp, p, "RQNT");
2001 add_header(&resp, "X", p->rqnt_ident); /* SC */
2002 switch (p->hookstate) {
2004 add_header(&resp, "R", "L/hd(N)");
2007 add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
2010 if (strlen(tone2)) {
2011 add_header(&resp, "S", tone2);
2014 ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s\n",
2015 tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
2017 /* SC: fill in new fields */
2018 resp.cmd = MGCP_CMD_RQNT;
2020 return send_request(p, NULL, &resp, oseq); /* SC */
2023 static int transmit_modify_request(struct mgcp_subchannel *sub)
2025 struct mgcp_request resp;
2026 struct mgcp_endpoint *p = sub->parent;
2027 if (!strlen(sub->cxident)) {
2028 /* We don't have a CXident yet, store the destination and
2033 ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n",
2034 p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2036 reqprep(&resp, p, "MDCX");
2037 add_header(&resp, "C", sub->callid);
2038 add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2039 /* SC: X header should not be sent. kept for compatibility */
2040 add_header(&resp, "X", sub->txident);
2041 add_header(&resp, "I", sub->cxident);
2042 switch (sub->parent->hookstate) {
2044 add_header(&resp, "R", "L/hd(N)");
2047 add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
2050 /* SC: fill in new fields */
2051 resp.cmd = MGCP_CMD_MDCX;
2053 return send_request(p, sub, &resp, oseq); /* SC */
2057 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
2059 struct mgcp_request resp;
2060 reqprep(&resp, p, "AUEP");
2061 /* SC: removed unknown param VS */
2062 //add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");
2063 add_header(&resp, "F", "A");
2064 /* SC: fill in new fields */
2065 resp.cmd = MGCP_CMD_AUEP;
2067 return send_request(p, NULL, &resp, oseq); /* SC */
2070 static int transmit_connection_del(struct mgcp_subchannel *sub)
2072 struct mgcp_endpoint *p = sub->parent;
2073 struct mgcp_request resp;
2075 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
2076 sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2078 reqprep(&resp, p, "DLCX");
2079 /* SC: check if call id is avail */
2081 add_header(&resp, "C", sub->callid);
2082 /* SC: X header should not be sent. kept for compatibility */
2083 add_header(&resp, "X", sub->txident);
2084 /* SC: check if cxident is avail */
2085 if (sub->cxident[0])
2086 add_header(&resp, "I", sub->cxident);
2087 /* SC: fill in new fields */
2088 resp.cmd = MGCP_CMD_DLCX;
2090 return send_request(p, sub, &resp, oseq); /* SC */
2093 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
2095 struct mgcp_request resp;
2097 ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n",
2098 cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2100 reqprep(&resp, p, "DLCX");
2101 /* SC: check if call id is avail */
2102 if (callid && *callid)
2103 add_header(&resp, "C", callid);
2104 /* SC: check if cxident is avail */
2105 if (cxident && *cxident)
2106 add_header(&resp, "I", cxident);
2107 /* SC: fill in new fields */
2108 resp.cmd = MGCP_CMD_DLCX;
2110 return send_request(p, p->sub, &resp, oseq);
2113 /* SC: cleanup pendng commands */
2114 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
2116 struct mgcp_request *t, *q;
2119 ast_mutex_lock(&p->rqnt_queue_lock);
2120 for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
2121 p->rqnt_queue = NULL;
2122 ast_mutex_unlock(&p->rqnt_queue_lock);
2124 ast_mutex_lock(&p->cmd_queue_lock);
2125 for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
2126 p->cmd_queue = NULL;
2127 ast_mutex_unlock(&p->cmd_queue_lock);
2129 ast_mutex_lock(&p->sub->cx_queue_lock);
2130 for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
2131 p->sub->cx_queue = NULL;
2132 ast_mutex_unlock(&p->sub->cx_queue_lock);
2134 ast_mutex_lock(&p->sub->next->cx_queue_lock);
2135 for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
2136 p->sub->next->cx_queue = NULL;
2137 ast_mutex_unlock(&p->sub->next->cx_queue_lock);
2140 ast_mutex_lock(&sub->cx_queue_lock);
2141 for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
2142 sub->cx_queue = NULL;
2143 ast_mutex_unlock(&sub->cx_queue_lock);
2148 /* SC: remove command transaction from queue */
2149 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2150 struct mgcp_request **queue, ast_mutex_t *l, int ident)
2152 struct mgcp_request *prev, *req;
2155 for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2156 if (req->trid == ident) {
2157 /* remove from queue */
2161 prev->next = req->next;
2163 /* send next pending command */
2166 ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
2167 inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2170 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2175 ast_mutex_unlock(l);
2179 /* SC: modified for new transport mechanism */
2180 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2181 int result, unsigned int ident, struct mgcp_request *resp)
2184 struct mgcp_request *req;
2185 struct mgcp_gateway *gw = p->parent;
2188 /* provisional response */
2193 req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2194 else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2195 req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2198 if (option_verbose > 2) {
2199 ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n",
2205 if (p && (result >= 400) && (result <= 599)) {
2208 p->hookstate = MGCP_OFFHOOK;
2211 p->hookstate = MGCP_ONHOOK;
2214 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
2217 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
2223 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2224 result, p->name, p->parent->name, sub ? sub->id:-1);
2225 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2229 if (p->sub->next->owner) {
2230 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2231 result, p->name, p->parent->name, sub ? sub->id:-1);
2232 ast_softhangup(p->sub->next->owner, AST_SOFTHANGUP_DEV);
2235 if (p->sub->owner) {
2236 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
2237 result, p->name, p->parent->name, sub ? sub->id:-1);
2238 ast_softhangup(p->sub->owner, AST_SOFTHANGUP_DEV);
2241 dump_cmd_queues(p, NULL);
2246 if (req->cmd == MGCP_CMD_CRCX) {
2247 if ((c = get_header(resp, "I"))) {
2249 /* SC: if we are hanging up do not process this conn. */
2251 if (strlen(sub->cxident)) {
2252 if (strcasecmp(c, sub->cxident)) {
2253 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2256 strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
2257 if (sub->tmpdest.sin_addr.s_addr) {
2258 transmit_modify_with_sdp(sub, NULL);
2262 /* XXX SC: delete this one
2263 callid and conn id may already be lost.
2264 so the following del conn may have a side effect of
2265 cleaning up the next subchannel */
2266 transmit_connection_del(sub);
2272 if (req->cmd == MGCP_CMD_AUEP) {
2273 /* SC: check stale connection ids */
2274 if ((c = get_header(resp, "I"))) {
2277 while ((v = get_csv(c, &len, &n))) {
2279 if(strncasecmp(v, p->sub->cxident, len) &&
2280 strncasecmp(v, p->sub->next->cxident, len)) {
2281 /* connection id not found. delete it */
2283 memcpy(cxident, v, len);
2284 cxident[len] = '\0';
2285 if (option_verbose > 2) {
2286 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n",
2287 cxident, p->name, gw->name);
2289 transmit_connection_del_w_params(p, NULL, cxident);
2296 /* Try to determine the hookstate returned from an audit endpoint command */
2297 if ((c = get_header(resp, "ES"))) {
2299 if (strstr(c, "hu")) {
2300 if (p->hookstate != MGCP_ONHOOK) {
2301 /* SC: XXX cleanup if we think we are offhook XXX */
2302 if ((p->sub->owner || p->sub->next->owner ) &&
2303 p->hookstate == MGCP_OFFHOOK)
2304 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2305 p->hookstate = MGCP_ONHOOK;
2307 /* SC: update the requested events according to the new hookstate */
2308 transmit_notify_request(p->sub, "");
2310 /* SC: verbose level check */
2311 if (option_verbose > 2) {
2312 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2315 } else if (strstr(c, "hd")) {
2316 if (p->hookstate != MGCP_OFFHOOK) {
2317 p->hookstate = MGCP_OFFHOOK;
2319 /* SC: update the requested events according to the new hookstate */
2320 transmit_notify_request(p->sub, "");
2322 /* SC: verbose level check */
2323 if (option_verbose > 2) {
2324 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2332 if (resp && resp->lines) {
2333 /* SC: do not process sdp if we are hanging up. this may be a late response */
2334 if (sub && sub->owner) {
2338 process_sdp(sub, resp);
2346 static void start_rtp(struct mgcp_subchannel *sub)
2348 ast_mutex_lock(&sub->lock);
2349 /* SC: check again to be on the safe side */
2351 ast_rtp_destroy(sub->rtp);
2354 /* Allocate the RTP now */
2355 sub->rtp = ast_rtp_new(sched, io, 1, 0);
2356 if (sub->rtp && sub->owner)
2357 sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2359 ast_rtp_setnat(sub->rtp, sub->nat);
2361 ast_rtp_set_callback(p->rtp, rtpready);
2362 ast_rtp_set_data(p->rtp, p);
2364 /* Make a call*ID */
2365 snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
2366 /* Transmit the connection create */
2367 transmit_connect_with_sdp(sub, NULL);
2368 ast_mutex_unlock(&sub->lock);
2371 static void *mgcp_ss(void *data)
2373 struct ast_channel *chan = data;
2374 struct mgcp_subchannel *sub = chan->pvt->pvt;
2375 struct mgcp_endpoint *p = sub->parent;
2376 char exten[AST_MAX_EXTENSION] = "";
2378 int timeout = firstdigittimeout;
2381 while(len < AST_MAX_EXTENSION-1) {
2382 res = ast_waitfordigit(chan, timeout);
2385 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
2386 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2387 ast_indicate(chan, -1);
2394 if (!ast_ignore_pattern(chan->context, exten)) {
2395 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2396 ast_indicate(chan, -1);
2398 /* XXX Redundant? We should already be playing dialtone */
2399 /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2400 transmit_notify_request(sub, "L/dl");
2402 if (ast_exists_extension(chan, chan->context, exten, 1, p->callerid)) {
2403 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->callerid)) {
2405 /* Record this as the forwarding extension */
2406 strncpy(p->call_forward, exten, sizeof(p->call_forward));
2407 if (option_verbose > 2) {
2408 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
2409 p->call_forward, chan->name);
2411 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2412 transmit_notify_request(sub, "L/sl");
2416 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2417 ast_indicate(chan, -1);
2419 memset(exten, 0, sizeof(exten));
2420 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2421 transmit_notify_request(sub, "L/dl");
2425 /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2426 ast_indicate(chan, -1);
2427 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
2428 if (strlen(p->callerid)) {
2429 if (!p->hidecallerid) {
2430 /* SC: free existing chan->callerid */
2432 free(chan->callerid);
2433 chan->callerid = strdup(p->callerid);
2437 chan->ani = strdup(p->callerid);
2439 ast_setstate(chan, AST_STATE_RING);
2440 /*zt_enable_ec(p);*/
2441 res = ast_pbx_run(chan);
2443 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2444 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2445 /*transmit_notify_request(p, "nbz", 1);*/
2446 transmit_notify_request(sub, "G/cg");
2451 /* It's a match, but they just typed a digit, and there is an ambiguous match,
2452 so just set the timeout to matchdigittimeout and wait some more */
2453 timeout = matchdigittimeout;
2455 } else if (res == 0) {
2456 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
2457 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2458 transmit_notify_request(sub, "G/cg");
2459 /*zt_wait_event(p->subs[index].zfd);*/
2462 } else if (p->callwaiting && !strcmp(exten, "*70")) {
2463 if (option_verbose > 2) {
2464 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
2466 /* Disable call waiting if enabled */
2468 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2469 transmit_notify_request(sub, "L/sl");
2471 memset(exten, 0, sizeof(exten));
2472 timeout = firstdigittimeout;
2474 } else if (!strcmp(exten,ast_pickup_ext())) {
2475 /* Scan all channels and see if any there
2476 * ringing channqels with that have call groups
2477 * that equal this channels pickup group
2479 if (ast_pickup_call(chan)) {
2480 ast_log(LOG_WARNING, "No call pickup possible...\n");
2481 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2482 transmit_notify_request(sub, "G/cg");
2487 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
2488 if (option_verbose > 2) {
2489 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
2491 /* Disable Caller*ID if enabled */
2492 p->hidecallerid = 1;
2494 free(chan->callerid);
2495 chan->callerid = NULL;
2496 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2497 transmit_notify_request(sub, "L/sl");
2499 memset(exten, 0, sizeof(exten));
2500 timeout = firstdigittimeout;
2501 } else if (p->callreturn && !strcmp(exten, "*69")) {
2503 if (strlen(p->lastcallerid)) {
2504 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
2507 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2508 transmit_notify_request(sub, "L/sl");
2510 } else if (!strcmp(exten, "*78")) {
2511 /* Do not disturb */
2512 if (option_verbose > 2) {
2513 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
2515 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2516 transmit_notify_request(sub, "L/sl");
2519 memset(exten, 0, sizeof(exten));
2521 } else if (!strcmp(exten, "*79")) {
2522 /* Do not disturb */
2523 if (option_verbose > 2) {
2524 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
2526 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2527 transmit_notify_request(sub, "L/sl");
2530 memset(exten, 0, sizeof(exten));
2532 } else if (p->cancallforward && !strcmp(exten, "*72")) {
2533 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2534 transmit_notify_request(sub, "L/sl");
2536 memset(exten, 0, sizeof(exten));
2538 } else if (p->cancallforward && !strcmp(exten, "*73")) {
2539 if (option_verbose > 2) {
2540 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
2542 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2543 transmit_notify_request(sub, "L/sl");
2544 memset(p->call_forward, 0, sizeof(p->call_forward));
2546 memset(exten, 0, sizeof(exten));
2548 } else if (!strcmp(exten, ast_parking_ext()) &&
2550 sub->next->owner->bridge) {
2551 /* This is a three way call, the main call being a real channel,
2552 and we're parking the first call. */
2553 ast_masq_park_call(sub->next->owner->bridge, chan, 0, NULL);
2554 if (option_verbose > 2) {
2555 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
2558 } else if (strlen(p->lastcallerid) && !strcmp(exten, "*80")) {
2559 if (option_verbose > 2) {
2560 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
2562 res = ast_db_put("blacklist", p->lastcallerid, "1");
2564 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2565 transmit_notify_request(sub, "L/sl");
2566 memset(exten, 0, sizeof(exten));
2569 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
2570 if (option_verbose > 2) {
2571 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
2573 /* Enable Caller*ID if enabled */
2574 p->hidecallerid = 0;
2576 free(chan->callerid);
2577 if (strlen(p->callerid))
2578 chan->callerid = strdup(p->callerid);
2579 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2580 transmit_notify_request(sub, "L/sl");
2582 memset(exten, 0, sizeof(exten));
2583 timeout = firstdigittimeout;
2584 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->callerid) &&
2585 ((exten[0] != '*') || (strlen(exten) > 2))) {
2587 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->callerid ? chan->callerid : "<Unknown Caller>", chan->context);
2591 timeout = gendigittimeout;
2592 if (len && !ast_ignore_pattern(chan->context, exten))
2593 /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
2594 ast_indicate(chan, -1);
2598 res = ast_waitfordigit(chan, to);
2600 ast_log(LOG_DEBUG, "Timeout...\n");
2604 ast_log(LOG_DEBUG, "Got hangup...\n");
2609 if (!ast_ignore_pattern(chan->context, exten))
2610 ast_indicate(chan, -1);
2611 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
2612 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
2619 if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
2620 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
2624 ast_setstate(chan, AST_STATE_RING);
2626 if (ast_pbx_run(chan)) {
2627 ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
2636 static int attempt_transfer(struct mgcp_endpoint *p)
2638 /* *************************
2639 * I hope this works.
2640 * Copied out of chan_zap
2641 * Cross your fingers
2642 * *************************/
2644 /* In order to transfer, we need at least one of the channels to
2645 actually be in a call bridge. We can't conference two applications
2646 together (but then, why would we want to?) */
2647 if (p->sub->owner->bridge) {
2648 /* The three-way person we're about to transfer to could still be in MOH, so
2649 stop if now if appropriate */
2650 if (p->sub->next->owner->bridge)
2651 ast_moh_stop(p->sub->next->owner->bridge);
2652 if (p->sub->owner->_state == AST_STATE_RINGING) {
2653 ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING);
2655 if (ast_channel_masquerade(p->sub->next->owner, p->sub->owner->bridge)) {
2656 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2657 p->sub->owner->bridge->name, p->sub->next->owner->name);
2660 /* Orphan the channel */
2661 unalloc_sub(p->sub->next);
2662 } else if (p->sub->next->owner->bridge) {
2663 if (p->sub->owner->_state == AST_STATE_RINGING) {
2664 ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING);
2666 ast_moh_stop(p->sub->next->owner->bridge);
2667 if (ast_channel_masquerade(p->sub->owner, p->sub->next->owner->bridge)) {
2668 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2669 p->sub->next->owner->bridge->name, p->sub->owner->name);
2672 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
2673 if (option_verbose > 2) {
2674 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);
2676 p->sub = p->sub->next;
2677 unalloc_sub(p->sub->next);
2678 /* Tell the caller not to hangup */
2681 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
2682 p->sub->owner->name, p->sub->next->owner->name);
2683 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2684 if (p->sub->next->owner) {
2685 p->sub->next->alreadygone = 1;
2686 ast_queue_hangup(p->sub->next->owner);
2692 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
2694 struct mgcp_endpoint *p = sub->parent;
2695 struct ast_channel *c;
2697 pthread_attr_t attr;
2698 pthread_attr_init(&attr);
2699 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2701 /* Off hook / answer */
2702 if (sub->outgoing) {
2705 if (sub->owner->bridge) {
2706 ast_moh_stop(sub->owner->bridge);
2708 sub->cxmode = MGCP_CX_SENDRECV;
2712 transmit_modify_request(sub);
2714 /*transmit_notify_request(sub, "aw");*/
2715 transmit_notify_request(sub, "");
2716 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2720 /*sub->cxmode = MGCP_CX_SENDRECV;*/
2725 transmit_modify_request(sub);
2728 /* The channel is immediately up. Start right away */
2729 transmit_notify_request(sub, "G/rt");
2730 c = mgcp_new(sub, AST_STATE_RING);
2732 ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
2733 transmit_notify_request(sub, "G/cg");
2737 if (has_voicemail(p)) {
2738 transmit_notify_request(sub, "L/sl");
2740 transmit_notify_request(sub, "L/dl");
2742 c = mgcp_new(sub, AST_STATE_DOWN);
2744 if (pthread_create(&t, &attr, mgcp_ss, c)) {
2745 ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
2749 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
2753 if (p->hookstate == MGCP_OFFHOOK) {
2754 ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
2756 ast_log(LOG_WARNING, "On hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
2757 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
2759 if (sub->owner->bridge) {
2760 ast_moh_stop(sub->owner->bridge);
2762 sub->cxmode = MGCP_CX_SENDRECV;
2766 transmit_modify_request(sub);
2768 /*transmit_notify_request(sub, "aw");*/
2769 transmit_notify_request(sub, "");
2770 /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
2775 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
2778 struct ast_frame f = { 0, };
2779 struct mgcp_endpoint *p = sub->parent;
2780 struct mgcp_gateway *g = NULL;
2783 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
2785 /* Clear out potential response */
2786 if (!strcasecmp(req->verb, "RSIP")) {
2787 /* Test if this RSIP request is just a keepalive */
2788 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
2789 if (option_verbose > 2)
2790 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
2791 transmit_response(sub, "200", req, "OK");
2793 dump_queue(p->parent, p);
2794 dump_cmd_queues(p, NULL);
2796 if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
2797 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
2799 // JS: For RSIP on wildcard we reset all endpoints
2800 if (!strcmp(p->name, p->parent->wcardep)) {
2801 /* Reset all endpoints */
2802 struct mgcp_endpoint *tmp_ep;
2805 tmp_ep = g->endpoints;
2807 //if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/*") != 0)) {
2808 if (strcmp(tmp_ep->name, g->wcardep) != 0) {
2809 struct mgcp_subchannel *tmp_sub, *first_sub;
2810 if (option_verbose > 2) {
2811 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
2814 first_sub = tmp_ep->sub;
2815 tmp_sub = tmp_ep->sub;
2818 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2819 tmp_sub = tmp_sub->next;
2820 if (tmp_sub == first_sub)
2824 tmp_ep = tmp_ep->next;
2826 } else if (sub->owner) {
2827 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2829 transmit_response(sub, "200", req, "OK");
2830 /* JS: We dont send NTFY or AUEP to wildcard ep */
2831 if (strcmp(p->name, p->parent->wcardep) != 0) {
2832 transmit_notify_request(sub, "");
2833 /* SC: Audit endpoint.
2834 Idea is to prevent lost lines due to race conditions
2836 transmit_audit_endpoint(p);
2839 } else if (!strcasecmp(req->verb, "NTFY")) {
2840 /* Acknowledge and be sure we keep looking for the same things */
2841 transmit_response(sub, "200", req, "OK");
2842 /* Notified of an event */
2843 ev = get_header(req, "O");
2844 s = strchr(ev, '/');
2846 if (option_verbose > 2) {
2847 ast_verbose(VERBOSE_PREFIX_3 "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
2849 /* Keep looking for events unless this was a hangup */
2850 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd")) {
2851 transmit_notify_request(sub, p->curtone);
2853 if (!strcasecmp(ev, "hd")) {
2854 p->hookstate = MGCP_OFFHOOK;
2855 sub->cxmode = MGCP_CX_SENDRECV;
2856 handle_hd_hf(sub, ev);
2857 } else if (!strcasecmp(ev, "hf")) {
2858 /* We can assume we are offhook if we received a hookflash */
2859 /* First let's just do call wait and ignore threeway */
2860 /* We're currently in charge */
2861 if (p->hookstate != MGCP_OFFHOOK) {
2862 /* Cisco c7940 sends hf even if the phone is onhook */
2863 /* Thanks to point on IRC for pointing this out */
2866 /* do not let * confrnce two down channels */
2867 if( sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1;
2869 if (p->callwaiting || p->transfer || p->threewaycalling) {
2870 if (option_verbose > 2) {
2871 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);
2873 p->sub = p->sub->next;
2875 /* transfer control to our next subchannel */
2876 if (!sub->next->owner) {
2877 /* plave the first call on hold and start up a new call */
2878 sub->cxmode = MGCP_CX_MUTE;
2879 if (option_verbose > 2) {
2880 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
2882 transmit_modify_request(sub);
2883 if (sub->owner && sub->owner->bridge) {
2884 ast_moh_start(sub->owner->bridge, NULL);
2886 sub->next->cxmode = MGCP_CX_RECVONLY;
2887 handle_hd_hf(sub->next, ev);
2888 } else if (sub->owner && sub->next->owner) {
2889 /* We've got two active calls lets decide whether or not to conference or just flip flop */
2890 if ((!sub->outgoing) && (!sub->next->outgoing)) {
2891 /* We made both calls lets conferenct */
2892 if (option_verbose > 2) {
2893 ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n",
2894 sub->id, sub->next->id, p->name, p->parent->name);
2896 sub->cxmode = MGCP_CX_CONF;
2897 sub->next->cxmode = MGCP_CX_CONF;
2898 if (sub->next->owner->bridge) {
2899 ast_moh_stop(sub->next->owner->bridge);
2901 transmit_modify_request(sub);
2902 transmit_modify_request(sub->next);
2904 /* Let's flipflop between calls */
2905 /* XXX Need to check for state up ??? */
2906 /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
2907 if (option_verbose > 2) {
2908 ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
2909 sub->id, sub->next->id, p->name, p->parent->name);
2911 sub->cxmode = MGCP_CX_MUTE;
2912 if (option_verbose > 2) {
2913 ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
2915 transmit_modify_request(sub);
2916 if (sub->owner->bridge) {
2917 ast_moh_start(sub->owner->bridge, NULL);
2919 if (sub->next->owner->bridge) {
2920 ast_moh_stop(sub->next->owner->bridge);
2922 handle_hd_hf(sub->next, ev);
2924 if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) {
2925 handle_hd_hf(sub->next, ev);
2927 ast_verbose(VERBOSE_PREFIX_3 "MGCP Unmuting %d on %s@%s\n", sub->next->id, p->name, p->parent->name);
2928 sub->next->cxmode = MGCP_CX_SENDRECV;
2929 transmit_modify_request(sub->next);
2934 /* We've most likely lost one of our calls find an active call and bring it up */
2937 } else if (sub->next->owner) {
2940 /* We seem to have lost both our calls */
2941 /* XXX - What do we do now? */
2944 if (p->sub->owner->bridge) {
2945 ast_moh_stop(p->sub->owner->bridge);
2947 p->sub->cxmode = MGCP_CX_SENDRECV;
2948 transmit_modify_request(p->sub);
2951 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
2952 p->name, p->parent->name);
2954 /* ast_moh_stop(sub->owner->bridge); */
2955 } else if (!strcasecmp(ev, "hu")) {
2956 p->hookstate = MGCP_ONHOOK;
2957 sub->cxmode = MGCP_CX_RECVONLY;
2958 ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
2959 /* JS: Do we need to send MDCX before a DLCX ?
2961 transmit_modify_request(sub);
2964 if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
2965 /* We're allowed to transfer, we have two avtive calls and */
2966 /* we made at least one of the calls. Let's try and transfer */
2967 if ((res = attempt_transfer(p)) < 0) {
2968 if (p->sub->next->owner) {
2969 sub->next->alreadygone = 1;
2970 ast_queue_hangup(sub->next->owner);
2973 ast_log(LOG_WARNING, "Transfer attempt failed\n");
2977 /* Hangup the current call */
2978 /* If there is another active call, mgcp_hangup will ring the phone with the other call */
2980 sub->alreadygone = 1;
2981 ast_queue_hangup(sub->owner);
2983 /* SC: verbose level check */
2984 if (option_verbose > 2) {
2985 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed\n",
2986 p->name, p->parent->name, sub->id);
2990 if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
2991 if (has_voicemail(p)) {
2992 if (option_verbose > 2) {
2993 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
2995 transmit_notify_request(sub, "L/vmwi(+)");
2997 if (option_verbose > 2) {
2998 ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
3000 transmit_notify_request(sub, "L/vmwi(-)");
3003 } else if ((strlen(ev) == 1) &&
3004 (((ev[0] >= '0') && (ev[0] <= '9')) ||
3005 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
3006 (ev[0] == '*') || (ev[0] == '#'))) {
3007 f.frametype = AST_FRAME_DTMF;
3011 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
3012 ast_queue_frame(sub->owner, &f);
3013 if (sub->next->owner) {
3014 ast_queue_frame(sub->next->owner, &f);
3017 if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
3018 memset(p->curtone, 0, sizeof(p->curtone));
3021 else if (!strcasecmp(ev, "T")) {
3022 /* Digit timeout -- unimportant */
3024 ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
3027 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, inet_ntoa(sin->sin_addr));
3028 transmit_response(sub, "510", req, "Unknown verb");
3033 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
3035 struct mgcp_request req;
3036 struct sockaddr_in sin;
3037 struct mgcp_subchannel *sub;
3043 memset(&req, 0, sizeof(req));
3044 res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
3046 if (errno != ECONNREFUSED)
3047 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
3050 req.data[res] = '\0';
3053 ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
3056 if (req.headers < 1) {
3057 /* Must have at least one header */
3060 if (!req.identifier || !strlen(req.identifier)) {
3061 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", inet_ntoa(sin.sin_addr));
3065 if (sscanf(req.verb, "%d", &result) &&
3066 sscanf(req.identifier, "%d", &ident)) {
3067 /* Try to find who this message is for, if it's important */
3068 sub = find_subchannel(NULL, ident, &sin);
3070 struct mgcp_gateway *gw = sub->parent->parent;
3071 struct mgcp_message *cur, *prev;
3073 ast_mutex_lock(&gw->msgs_lock);
3074 for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
3075 if (cur->seqno == ident) {
3076 ast_log(LOG_DEBUG, "Got response back on tansaction %d\n", ident);
3078 prev->next = cur->next;
3080 gw->msgs = cur->next;
3085 /* stop retrans timer if the queue is empty */
3086 if (!gw->msgs && (gw->retransid != -1)) {
3087 ast_sched_del(sched, gw->retransid);
3091 ast_mutex_unlock(&gw->msgs_lock);
3094 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
3099 ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
3103 if (!req.endpoint || !strlen(req.endpoint) ||
3104 !req.version || !strlen(req.version) ||
3105 !req.verb || !strlen(req.verb)) {
3106 ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
3109 /* Process request, with iflock held */
3110 sub = find_subchannel(req.endpoint, 0, &sin);
3112 /* pass the request off to the currently mastering subchannel */
3113 handle_request(sub, &req, &sin);
3119 static void *do_monitor(void *data)
3123 /* struct mgcp_gateway *g; */
3124 /* struct mgcp_endpoint *e; */
3125 /*time_t thispass = 0, lastpass = 0;*/
3127 /* Add an I/O event to our UDP socket */
3129 ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
3131 /* This thread monitors all the frame relay interfaces which are not yet in use
3132 (and thus do not have a separate thread) indefinitely */
3133 /* From here on out, we die whenever asked */
3135 /* Check for a reload request */
3136 ast_mutex_lock(&mgcp_reload_lock);
3137 reloading = mgcp_reloading;
3139 ast_mutex_unlock(&mgcp_reload_lock);
3141 if (option_verbose > 0)
3142 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
3146 /* Check for interfaces needing to be killed */
3147 /* Don't let anybody kill us right away. Nobody should lock the interface list
3148 and wait for the monitor list, but the other way around is okay. */
3149 ast_mutex_lock(&monlock);
3150 /* Lock the network interface */
3151 ast_mutex_lock(&netlock);
3153 /* XXX THIS IS COMPLETELY HOSED */
3154 /* The gateway goes into a state of panic */
3155 /* If the vmwi indicator is sent while it is reseting interfaces */
3157 lastpass = thispass;
3158 thispass = time(NULL);
3161 if (thispass != lastpass) {
3164 if (e->type == TYPE_LINE) {
3165 res = has_voicemail(e);
3166 if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
3168 transmit_notify_request(e, "L/vmwi(+)");
3170 transmit_notify_request(e, "L/vmwi(-)");
3173 e->onhooktime = thispass;
3183 /* Okay, now that we know what to do, release the network lock */
3184 ast_mutex_unlock(&netlock);
3185 /* And from now on, we're okay to be killed, so release the monitor lock as well */
3186 ast_mutex_unlock(&monlock);
3187 pthread_testcancel();
3188 /* Wait for sched or io */
3189 res = ast_sched_wait(sched);
3190 /* SC: copied from chan_sip.c */
3191 if ((res < 0) || (res > 1000))
3193 res = ast_io_wait(io, res);
3194 ast_mutex_lock(&monlock);
3196 ast_sched_runq(sched);
3197 ast_mutex_unlock(&monlock);
3204 static int restart_monitor(void)
3206 pthread_attr_t attr;
3207 pthread_attr_init(&attr);
3208 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3210 /* If we're supposed to be stopped -- stay stopped */
3211 if (monitor_thread == AST_PTHREADT_STOP)
3213 if (ast_mutex_lock(&monlock)) {
3214 ast_log(LOG_WARNING, "Unable to lock monitor\n");
3217 if (monitor_thread == pthread_self()) {
3218 ast_mutex_unlock(&monlock);
3219 ast_log(LOG_WARNING, "Cannot kill myself\n");
3222 if (monitor_thread != AST_PTHREADT_NULL) {
3223 /* Wake up the thread */
3224 pthread_kill(monitor_thread, SIGURG);
3226 /* Start a new monitor */
3227 if (pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
3228 ast_mutex_unlock(&monlock);
3229 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
3233 ast_mutex_unlock(&monlock);
3237 static struct ast_channel *mgcp_request(char *type, int format, void *data)
3240 struct mgcp_subchannel *sub;
3241 struct ast_channel *tmpc = NULL;
3246 format &= capability;
3248 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
3251 strncpy(tmp, dest, sizeof(tmp) - 1);
3253 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
3256 sub = find_subchannel(tmp, 0, NULL);
3258 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
3262 if (option_verbose > 2) {
3263 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
3264 ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
3265 sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
3268 if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
3269 ((!sub->parent->callwaiting) && (sub->owner)) ||
3270 (sub->parent->dnd && (!strlen(sub->parent->call_forward)))) {
3271 if (sub->parent->hookstate == MGCP_ONHOOK) {
3272 if (has_voicemail(sub->parent)) {
3273 transmit_notify_request(sub,"L/vmwi(+)");
3275 transmit_notify_request(sub,"L/vmwi(-)");
3280 tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
3282 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
3287 /* SC: modified for reload support */
3288 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
3290 struct mgcp_gateway *gw;
3291 struct mgcp_endpoint *e;
3292 struct mgcp_subchannel *sub;
3293 /*char txident[80];*/
3297 canreinvite = CANREINVITE;
3299 /* SC: locate existing gateway */
3302 if (!strcasecmp(cat, gw->name)) {
3303 /* gateway already exists */
3312 gw = malloc(sizeof(struct mgcp_gateway));
3316 memset(gw, 0, sizeof(struct mgcp_gateway));
3318 gw->retransid = -1; /* SC */
3319 ast_mutex_init(&gw->msgs_lock);
3320 strncpy(gw->name, cat, sizeof(gw->name) - 1);
3321 /* SC: check if the name is numeric ip */
3322 if (inet_addr(gw->name) != INADDR_NONE)
3323 gw->isnamedottedip = 1;
3326 if (!strcasecmp(v->name, "host")) {
3327 if (!strcasecmp(v->value, "dynamic")) {
3328 /* They'll register with us */
3330 memset(&gw->addr.sin_addr, 0, 4);
3331 if (gw->addr.sin_port) {
3332 /* If we've already got a port, make it the default rather than absolute */
3333 gw->defaddr.sin_port = gw->addr.sin_port;
3334 gw->addr.sin_port = 0;
3337 /* Non-dynamic. Make sure we become that way if we're not */
3338 if (gw->expire > -1)
3339 ast_sched_del(sched, gw->expire);
3342 if (ast_get_ip(&gw->addr, v->value)) {
3348 } else if (!strcasecmp(v->name, "defaultip")) {
3349 if (ast_get_ip(&gw->defaddr, v->value)) {
3354 } else if (!strcasecmp(v->name, "permit") ||
3355 !strcasecmp(v->name, "deny")) {
3356 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
3357 } else if (!strcasecmp(v->name, "port")) {
3358 gw->addr.sin_port = htons(atoi(v->value));
3359 } else if (!strcasecmp(v->name, "context")) {
3360 strncpy(context, v->value, sizeof(context) - 1);
3361 } else if (!strcasecmp(v->name, "inbanddtmf")) {
3362 inbanddtmf = atoi(v->value);
3363 } else if (!strcasecmp(v->name, "nat")) {
3364 nat = ast_true(v->value);
3365 } else if (!strcasecmp(v->name, "callerid")) {
3366 if (!strcasecmp(v->value, "asreceived"))
3367 strcpy(callerid, "");
3369 strncpy(callerid, v->value, sizeof(callerid) - 1);
3370 } else if (!strcasecmp(v->name, "language")) {
3371 strncpy(language, v->value, sizeof(language)-1);
3372 } else if (!strcasecmp(v->name, "accountcode")) {
3373 strncpy(accountcode, v->value, sizeof(accountcode)-1);
3374 } else if (!strcasecmp(v->name, "amaflags")) {
3375 y = ast_cdr_amaflags2int(v->value);
3377 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
3381 } else if (!strcasecmp(v->name, "musiconhold")) {
3382 strncpy(musicclass, v->value, sizeof(musicclass)-1);
3383 } else if (!strcasecmp(v->name, "callgroup")) {
3384 cur_callergroup = ast_get_group(v->value);
3385 } else if (!strcasecmp(v->name, "pickupgroup")) {
3386 cur_pickupgroup = ast_get_group(v->value);
3387 } else if (!strcasecmp(v->name, "immediate")) {
3388 immediate = ast_true(v->value);
3389 } else if (!strcasecmp(v->name, "cancallforward")) {
3390 cancallforward = ast_true(v->value);
3391 } else if (!strcasecmp(v->name, "canreinvite")) {
3392 canreinvite = ast_true(v->value);
3393 } else if (!strcasecmp(v->name, "mailbox")) {
3394 strncpy(mailbox, v->value, sizeof(mailbox) -1);
3395 } else if (!strcasecmp(v->name, "adsi")) {
3396 adsi = ast_true(v->value);
3397 } else if (!strcasecmp(v->name, "callreturn")) {
3398 callreturn = ast_true(v->value);
3399 } else if (!strcasecmp(v->name, "immediate")) {
3400 immediate = ast_true(v->value);
3401 } else if (!strcasecmp(v->name, "callwaiting")) {
3402 callwaiting = ast_true(v->value);
3403 } else if (!strcasecmp(v->name, "transfer")) {
3404 transfer = ast_true(v->value);
3405 } else if (!strcasecmp(v->name, "threewaycalling")) {
3406 threewaycalling = ast_true(v->value);
3407 } else if (!strcasecmp(v->name, "wcardep")) {
3408 /* SC: locate existing endpoint */
3411 if (!strcasecmp(v->value, e->name)) {
3412 /* endpoint already exists */
3421 e = malloc(sizeof(struct mgcp_endpoint));
3425 /* Allocate wildcard endpoint */
3426 e = malloc(sizeof(struct mgcp_endpoint));
3429 memset(e, 0, sizeof(struct mgcp_endpoint));
3430 strncpy(e->name, v->value, sizeof(e->name) - 1);
3433 strncpy(gw->wcardep, v->value, sizeof(gw->wcardep)-1);
3434 //strcpy(e->name, "aaln/*");
3435 /* XXX Should we really check for uniqueness?? XXX */
3436 strncpy(e->context, context, sizeof(e->context) - 1);
3437 strncpy(e->callerid, callerid, sizeof(e->callerid) - 1);
3438 strncpy(e->language, language, sizeof(e->language) - 1);
3439 strncpy(e->musicclass, musicclass, sizeof(e->musicclass)-1);
3440 strncpy(e->mailbox, mailbox, sizeof(e->mailbox)-1);
3442 e->capability = capability;
3444 e->dtmfinband = inbanddtmf;
3446 e->type = TYPE_LINE;
3447 e->immediate = immediate;
3448 e->callgroup=cur_callergroup;
3449 e->pickupgroup=cur_pickupgroup;
3450 e->callreturn = callreturn;
3451 e->cancallforward = cancallforward;
3452 e->canreinvite = canreinvite;
3453 e->callwaiting = callwaiting;
3454 e->transfer = transfer;
3455 e->threewaycalling = threewaycalling;
3456 e->onhooktime = time(NULL);
3457 /* ASSUME we're onhook */
3458 e->hookstate = MGCP_ONHOOK;
3459 /*snprintf(txident, sizeof(txident), "%08x", rand());*/
3460 for (i = 0; i < MAX_SUBS; i++) {
3461 sub = malloc(sizeof(struct mgcp_subchannel));
3463 ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
3464 memset(sub, 0, sizeof(struct mgcp_subchannel));
3467 snprintf(sub->txident, sizeof(sub->txident), "%08x", rand());
3468 /*strcpy(sub->txident, txident);*/
3469 sub->cxmode = MGCP_CX_INACTIVE;
3474 /* XXX Should find a way to clean up our memory */
3475 ast_log(LOG_WARNING, "Out of memory allocating subchannel");
3479 /* Make out subs a circular linked list so we can always sping through the whole bunch */
3481 /* find the end of the list */
3485 /* set the last sub->next to the first sub */
3488 e->next = gw->endpoints;
3491 } else if (!strcasecmp(v->name, "trunk") ||
3492 !strcasecmp(v->name, "line")) {
3494 /* SC: locate existing endpoint */
3497 if (!strcasecmp(v->value, e->name)) {
3498 /* endpoint already exists */
3507 e = malloc(sizeof(struct mgcp_endpoint));
3513 memset(e, 0, sizeof(struct mgcp_endpoint));
3514 strncpy(e->name, v->value, sizeof(e->name) - 1);
3517 /* XXX Should we really check for uniqueness?? XXX */
3518 strncpy(e->context, context, sizeof(e->context) - 1);
3519 strncpy(e->callerid, callerid, sizeof(e->callerid) - 1);
3520 strncpy(e->language, language, sizeof(e->language) - 1);
3521 strncpy(e->musicclass, musicclass, sizeof(e->musicclass)-1);
3522 strncpy(e->mailbox, mailbox, sizeof(e->mailbox)-1);
3523 if (strlen(mailbox)) {
3524 ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
3527 /* XXX SC: potential issue due to reload */
3531 e->capability = capability;
3532 e->dtmfinband = inbanddtmf;
3534 if (!strcasecmp(v->name, "trunk"))
3535 e->type = TYPE_TRUNK;
3537 e->type = TYPE_LINE;
3539 e->immediate = immediate;
3540 e->callgroup=cur_callergroup;
3541 e->pickupgroup=cur_pickupgroup;
3542 e->callreturn = callreturn;
3543 e->cancallforward = cancallforward;
3544 e->canreinvite = canreinvite;
3545 e->callwaiting = callwaiting;
3546 e->transfer = transfer;
3547 e->threewaycalling = threewaycalling;
3549 e->onhooktime = time(NULL);
3550 /* ASSUME we're onhook */
3551 e->hookstate = MGCP_ONHOOK;
3552 snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08x", rand());
3553 ast_mutex_init(&e->rqnt_queue_lock);