Remove extra argument from ast_set_*_format calls
[asterisk/asterisk.git] / channels / chan_mgcp.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Implementation of Media Gateway Control Protocol
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 /* SC: Changes
15    -- packet retransmit mechanism (simplistic)
16    -- per endpoint/subchannel mgcp command sequencing. 
17    -- better transaction handling
18    -- fixed some mem leaks
19    -- run-time configuration reload 
20    -- distinguish CA and GW default MGCP ports
21    -- prevent clipping of DTMF tones in an established call
22    -- fixed a few crash scenarios in 3-way
23    -- fix for a few cases where asterisk and MGW end-up in conflicting ep states 
24    -- enclose numeric IP in [] for outgoing requests
25 */
26
27 /* SC: TODO
28    -- piggyback support
29    -- responseAck support
30    -- enhance retransmit mechanism (RTO calc. etc.)
31    -- embedded command support
32 */
33
34 #include <stdio.h>
35 #include <pthread.h>
36 #include <string.h>
37 #include <asterisk/lock.h>
38 #include <asterisk/channel.h>
39 #include <asterisk/channel_pvt.h>
40 #include <asterisk/config.h>
41 #include <asterisk/logger.h>
42 #include <asterisk/module.h>
43 #include <asterisk/pbx.h>
44 #include <asterisk/options.h>
45 #include <asterisk/lock.h>
46 #include <asterisk/sched.h>
47 #include <asterisk/io.h>
48 #include <asterisk/rtp.h>
49 #include <asterisk/acl.h>
50 #include <asterisk/callerid.h>
51 #include <asterisk/cli.h>
52 #include <asterisk/say.h>
53 #include <asterisk/cdr.h>
54 #include <asterisk/astdb.h>
55 #include <asterisk/parking.h>
56 #include <asterisk/app.h>
57 #include <asterisk/musiconhold.h>
58 #include <sys/socket.h>
59 #include <sys/ioctl.h>
60 #include <net/if.h>
61 #include <errno.h>
62 #include <unistd.h>
63 #include <stdlib.h>
64 #include <fcntl.h>
65 #include <netdb.h>
66 #include <arpa/inet.h>
67 #include <sys/signal.h>
68 #include <signal.h>
69 #include <pthread.h>
70 #include <netinet/in_systm.h>
71 #include <netinet/ip.h>
72
73 #include <asterisk/dsp.h>
74 #include <ctype.h>
75
76 #ifndef IPTOS_MINCOST
77 #define IPTOS_MINCOST 0x02
78 #endif
79
80 #define MGCPDUMPER
81 #define DEFAULT_EXPIREY 120
82 #define MAX_EXPIREY     3600
83 #define CANREINVITE     1
84
85 static char *desc = "Media Gateway Control Protocol (MGCP)";
86 static char *type = "MGCP";
87 static char *tdesc = "Media Gateway Control Protocol (MGCP)";
88 static char *config = "mgcp.conf";
89
90 #define DEFAULT_MGCP_GW_PORT    2427/* From RFC 2705 */
91 #define DEFAULT_MGCP_CA_PORT    2727/* From RFC 2705 */
92 #define MGCP_MAX_PACKET 1500            /* Also from RFC 2543, should sub headers tho */
93 #define DEFAULT_RETRANS         1000   /* How frequently to retransmit */
94 #define MAX_RETRANS             5   /* Try only 5 times for retransmissions */
95
96 /* MGCP rtp stream modes */
97 #define MGCP_CX_SENDONLY 0
98 #define MGCP_CX_RECVONLY 1
99 #define MGCP_CX_SENDRECV 2
100 #define MGCP_CX_CONF     3
101 #define MGCP_CX_CONFERENCE 3
102 #define MGCP_CX_MUTE     4
103 #define MGCP_CX_INACTIVE 4
104
105 static char *mgcp_cxmodes[] = {
106     "sendonly",
107     "recvonly",
108     "sendrecv",
109     "confrnce",
110     "inactive"
111 };
112
113 /* SC: MGCP commands */
114 #define MGCP_CMD_EPCF 0
115 #define MGCP_CMD_CRCX 1
116 #define MGCP_CMD_MDCX 2
117 #define MGCP_CMD_DLCX 3
118 #define MGCP_CMD_RQNT 4
119 #define MGCP_CMD_NTFY 5
120 #define MGCP_CMD_AUEP 6
121 #define MGCP_CMD_AUCX 7
122 #define MGCP_CMD_RSIP 8
123
124 static char context[AST_MAX_EXTENSION] = "default";
125
126 static char language[MAX_LANGUAGE] = "";
127 static char musicclass[MAX_LANGUAGE] = "";
128 static char callerid[AST_MAX_EXTENSION] = "";
129
130 static int inbanddtmf = 0;
131 static int nat = 0;
132
133 /* Not used. Dosn't hurt for us to always send cid  */
134 /* to the mgcp box. */
135 /* static int use_callerid = 1;*/
136 /*static int cur_signalling = -1;*/
137
138 /*static unsigned int cur_group = 0;*/
139 static unsigned int cur_callergroup = 0;
140 static unsigned int cur_pickupgroup = 0;
141
142 /* XXX Is this needed? */
143 /*     Doesn't look like the dsp stuff for */
144 /*     inbanddtmf is actually hooked up.   */
145 /* static int relaxdtmf = 0; */
146
147 static int tos = 0;
148
149 static int immediate = 0;
150
151 static int callwaiting = 0;
152
153 /* Not used. Dosn't hurt for us to always send cid  */
154 /* to the mgcp box. */
155 /*static int callwaitingcallerid = 0;*/
156
157 /*static int hidecallerid = 0;*/
158
159 static int callreturn = 0;
160
161 static int threewaycalling = 0;
162
163 /* This is for flashhook transfers */
164 static int transfer = 0;
165
166 static int cancallforward = 0;
167
168 static int canreinvite = CANREINVITE;
169
170 /*static int busycount = 3;*/
171
172 /*static int callprogress = 0;*/
173
174 static char accountcode[20] = "";
175
176 static char mailbox[AST_MAX_EXTENSION];
177
178 static int amaflags = 0;
179
180 static int adsi = 0;
181
182
183 static int usecnt =0;
184 static ast_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
185 /* SC: transaction id should always be positive */
186 static unsigned int oseq;
187
188 /* Wait up to 16 seconds for first digit (FXO logic) */
189 static int firstdigittimeout = 16000;
190
191 /* How long to wait for following digits (FXO logic) */
192 static int gendigittimeout = 8000;
193
194 /* How long to wait for an extra digit, if there is an ambiguous match */
195 static int matchdigittimeout = 3000;
196
197 /* Protect the monitoring thread, so only one process can kill or start it, and not
198    when it's doing something critical. */
199 static ast_mutex_t netlock = AST_MUTEX_INITIALIZER;
200
201 static ast_mutex_t monlock = AST_MUTEX_INITIALIZER;
202
203 /* This is the thread for the monitor which checks for input on the channels
204    which are not currently in use.  */
205 static pthread_t monitor_thread = AST_PTHREADT_NULL;
206
207 static int restart_monitor(void);
208
209 /* Just about everybody seems to support ulaw, so make it a nice default */
210 static int capability = AST_FORMAT_ULAW;
211 static int nonCodecCapability = AST_RTP_DTMF;
212
213 static char ourhost[256];
214 static struct in_addr __ourip;
215 static int ourport;
216
217 static int mgcpdebug = 0;
218
219 static struct sched_context *sched;
220 static struct io_context *io;
221 /* The private structures of the  mgcp channels are linked for
222    selecting outgoing channels */
223    
224 #define MGCP_MAX_HEADERS                64
225 #define MGCP_MAX_LINES          64
226
227 struct mgcp_request {
228         int len;
229         char *verb;
230         char *identifier;
231         char *endpoint;
232         char *version;
233         int headers;                                    /* MGCP Headers */
234         char *header[MGCP_MAX_HEADERS];
235         int lines;                                              /* SDP Content */
236         char *line[MGCP_MAX_LINES];
237         char data[MGCP_MAX_PACKET];
238     int cmd;                        /* SC: int version of verb = command */
239     unsigned int trid;              /* SC: int version of identifier = transaction id */
240     struct mgcp_request *next;      /* SC: next in the queue */
241 };
242
243 /* SC: obsolete
244 static struct mgcp_pkt {
245         int retrans;
246         struct mgcp_endpoint *owner;
247         int packetlen;
248         char data[MGCP_MAX_PACKET];
249         struct mgcp_pkt *next;
250 } *packets = NULL;      
251 */
252
253 /* MGCP message for queuing up */
254 struct mgcp_message {
255     struct mgcp_endpoint *owner_ep;
256     struct mgcp_subchannel *owner_sub;
257     int retrans;
258     unsigned long expire;
259         unsigned int seqno;
260         int len;
261         struct mgcp_message *next;
262         unsigned char buf[0];
263 };
264
265 #define MAX_SUBS 2
266
267 #define SUB_REAL 0
268 #define SUB_ALT  1
269
270 struct mgcp_subchannel {
271     /* SC: subchannel magic string. 
272        Needed to prove that any subchannel pointer passed by asterisk 
273        really points to a valid subchannel memory area.
274        Ugly.. But serves the purpose for the time being.
275      */
276 #define MGCP_SUBCHANNEL_MAGIC "!978!"
277     char magic[6]; 
278         ast_mutex_t lock;
279     int id;
280     struct ast_channel *owner;
281     struct mgcp_endpoint *parent;
282     struct ast_rtp *rtp;
283         struct sockaddr_in tmpdest;
284         char txident[80];              /* FIXME SC: txident is replaced by rqnt_ident in endpoint. 
285                                       This should be obsoleted */
286     char cxident[80];
287     char callid[80];
288 /* SC: obsolete
289     time_t lastouttime;
290     int lastout;
291 */
292     int cxmode;
293     struct mgcp_request *cx_queue; /* SC: pending CX commands */
294         ast_mutex_t cx_queue_lock;     /* SC: CX queue lock */
295         int nat;
296         int iseq; /* Not used? RTP? */
297         int outgoing;
298         int alreadygone;
299 /* SC: obsolete
300         int messagepending;
301         struct mgcp_message *msgs;
302 */
303     struct mgcp_subchannel *next; /* for out circular linked list */
304 };
305
306 #define MGCP_ONHOOK 1
307 #define MGCP_OFFHOOK 2
308
309 #define TYPE_TRUNK              1
310 #define TYPE_LINE               2
311
312 struct mgcp_endpoint {
313         ast_mutex_t lock;
314         char name[80];
315     struct mgcp_subchannel *sub;        /* pointer to our current connection, channel and stuff */
316         char accountcode[80];
317         char exten[AST_MAX_EXTENSION];          /* Extention where to start */
318         char context[AST_MAX_EXTENSION];
319         char language[MAX_LANGUAGE];
320         char callerid[AST_MAX_EXTENSION];       /* Caller*ID */
321         char lastcallerid[AST_MAX_EXTENSION];   /* Last Caller*ID */
322         char call_forward[AST_MAX_EXTENSION];   /* Last Caller*ID */
323     char mailbox[AST_MAX_EXTENSION];
324     char musicclass[MAX_LANGUAGE];
325         char curtone[80];                                       /* Current tone */
326     unsigned int callgroup;
327     unsigned int pickupgroup;
328         int callwaiting;
329     int transfer;
330     int threewaycalling;
331         int cancallforward;
332         int canreinvite;
333         int callreturn;
334         int dnd; /* How does this affect callwait?  Do we just deny a mgcp_request if we're dnd? */
335         int hascallerid;
336         int hidecallerid;
337         int dtmfinband;
338         int amaflags;
339         int type;
340         int group;
341         int iseq; /* Not used? */
342         int lastout; /* tracking this on the subchannels.  Is it needed here? */
343         int needdestroy; /* Not used? */
344         int capability;
345         int nonCodecCapability;
346     int onhooktime;
347     int msgstate; /* voicemail message state */
348     int immediate;
349     int hookstate;
350     int adsi;
351         char rqnt_ident[80];             /* SC: request identifier */
352     struct mgcp_request *rqnt_queue; /* SC: pending RQNT commands */
353         ast_mutex_t rqnt_queue_lock;
354     struct mgcp_request *cmd_queue;  /* SC: pending commands other than RQNT */
355         ast_mutex_t cmd_queue_lock;
356     int delme;                       /* SC: needed for reload */
357     int needaudit;                   /* SC: needed for reload */
358         struct ast_dsp *dsp; /* XXX Should there be a dsp/subchannel? XXX */
359     /* owner is tracked on the subchannels, and the *sub indicates whos in charge */
360         /* struct ast_channel *owner; */
361         /* struct ast_rtp *rtp; */
362         /* struct sockaddr_in tmpdest; */
363     /* message go the the endpoint and not the channel so they stay here */
364         struct mgcp_endpoint *next;
365         struct mgcp_gateway *parent;
366 };
367
368 static struct mgcp_gateway {
369         /* A gateway containing one or more endpoints */
370         char name[80];
371     int isnamedottedip; /* SC: is the name FQDN or dotted ip */
372         struct sockaddr_in addr;
373         struct sockaddr_in defaddr;
374         struct in_addr ourip;
375         int dynamic;
376         int expire;             /* XXX Should we ever expire dynamic registrations? XXX */
377         struct mgcp_endpoint *endpoints;
378         struct ast_ha *ha;
379 /* SC: obsolete
380     time_t lastouttime;
381     int lastout;
382         int messagepending;
383 */
384         struct mgcp_message *msgs; /* SC: gw msg queue */
385         ast_mutex_t msgs_lock;     /* SC: queue lock */  
386     int retransid;             /* SC: retrans timer id */
387     int delme;                 /* SC: needed for reload */
388         struct mgcp_gateway *next;
389 } *gateways;
390
391 static ast_mutex_t mgcp_reload_lock = AST_MUTEX_INITIALIZER;
392 static int mgcp_reloading = 0;
393
394 static ast_mutex_t gatelock  = AST_MUTEX_INITIALIZER;
395
396 static int mgcpsock  = -1;
397
398 static struct sockaddr_in bindaddr;
399
400 static struct ast_frame  *mgcp_read(struct ast_channel *ast);
401 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
402 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
403 static int transmit_modify_request(struct mgcp_subchannel *sub);
404 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callerid);
405 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp);
406 static int transmit_connection_del(struct mgcp_subchannel *sub);
407 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
408 static void start_rtp(struct mgcp_subchannel *sub);
409 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,  
410                             int result, unsigned int ident, struct mgcp_request *resp);
411 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
412 static int mgcp_do_reload(void);
413 static int mgcp_reload(int fd, int argc, char *argv[]);
414
415 static int has_voicemail(struct mgcp_endpoint *p)
416 {
417         return ast_app_has_voicemail(p->mailbox);
418 }
419
420 static int unalloc_sub(struct mgcp_subchannel *sub)
421 {
422     struct mgcp_endpoint *p = sub->parent;
423         if (p->sub == sub) {
424                 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
425                 return -1;
426         }
427         ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
428
429         sub->owner = NULL;
430         if (strlen(sub->cxident)) {
431                 transmit_connection_del(sub);
432     }
433     sub->cxident[0] = '\0';
434     sub->callid[0] = '\0';
435     sub->cxmode = MGCP_CX_INACTIVE;
436         sub->outgoing = 0;
437         sub->alreadygone = 0;
438         memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
439         if (sub->rtp) {
440                 ast_rtp_destroy(sub->rtp);
441                 sub->rtp = NULL;
442         }
443     dump_cmd_queues(NULL, sub); /* SC */
444         return 0;
445 }
446
447 /* SC: modified for new transport mechanism */
448 static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
449 {
450         int res;
451         if (gw->addr.sin_addr.s_addr)
452             res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
453         else 
454             res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
455         if (res != len) {
456                 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
457         }
458         return res;
459 }
460
461 static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
462 {
463     struct mgcp_endpoint *p = sub->parent;
464         int res;
465         if (mgcpdebug) {
466                 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));
467     }
468         res = __mgcp_xmit(p->parent, req->data, req->len);
469         if (res > 0)
470                 res = 0;
471         return res;
472 }
473
474 /* SC: modified for new transport framework */
475 static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
476 {
477         struct mgcp_message *cur, *q = NULL, *w, *prev;
478
479     ast_mutex_lock(&gw->msgs_lock);
480     prev = NULL, cur = gw->msgs;
481     while (cur) {
482         if (!p || cur->owner_ep == p) {
483             if (prev)
484                 prev->next = cur->next;
485             else
486                 gw->msgs = cur->next;
487
488             ast_log(LOG_NOTICE, "Removing message from %s tansaction %u\n", 
489                     gw->name, cur->seqno);
490
491             w = cur;
492             cur = cur->next;
493             if (q) {
494                 w->next = q;
495             }
496             else {
497                 w->next = NULL;
498             }
499             q = w;
500         }
501         else {
502             prev = cur, cur=cur->next;
503         }
504     }
505     ast_mutex_unlock(&gw->msgs_lock);
506
507     while (q) {
508         cur = q;
509         q = q->next;
510         free(cur);
511     }
512 }
513
514 static int retrans_pkt(void *data)
515 {
516     struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
517         struct mgcp_message *cur, *exq = NULL, *w, *prev;
518         struct timeval tv;
519     unsigned long t;
520     int res = 0;
521
522         if (gettimeofday(&tv, NULL) < 0) {
523                 /* This shouldn't ever happen, but let's be sure */
524                 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
525         return 0;
526         }
527
528     t = tv.tv_sec * 1000 + tv.tv_usec / 1000;
529
530     /* find out expired msgs */
531     ast_mutex_lock(&gw->msgs_lock);
532
533     prev = NULL, cur = gw->msgs;
534     while (cur) {
535         if (cur->retrans < MAX_RETRANS) {
536             cur->retrans++;
537             if (mgcpdebug) {
538                 ast_verbose("Retransmitting #%d transaction %u on [%s]\n", cur->retrans, cur->seqno, gw->name);
539             }
540             __mgcp_xmit(gw, cur->buf, cur->len);
541
542             prev = cur;
543             cur = cur->next;
544         }
545         else {
546             if (prev)
547                 prev->next = cur->next;
548             else
549                 gw->msgs = cur->next;
550
551             ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n", cur->seqno, gw->name);
552
553             w = cur;
554             cur = cur->next;
555
556             if (exq) {
557                 w->next = exq;
558             }
559             else {
560                 w->next = NULL;
561             }
562             exq = w;
563         }
564     }
565
566     if (!gw->msgs) {
567         gw->retransid = -1;
568         res = 0;
569     }
570     else {
571         res = 1;
572     }
573     ast_mutex_unlock(&gw->msgs_lock);
574
575     while (exq) {
576         cur = exq;
577         /* time-out transaction */
578         handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
579         exq = exq->next;
580         free(cur);
581     }
582
583     return res;
584 }
585
586 /* SC: modified for the new transaction mechanism */
587 static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, 
588                             unsigned char *data, int len, unsigned int seqno)
589 {
590         struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
591         struct mgcp_message *cur;
592         struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
593         struct timeval tv;
594
595         if (!msg) {
596                 return -1;
597     }
598     if (!gw) {
599         return -1;
600     }
601 /* SC
602     time(&t);
603     if (gw->messagepending && (gw->lastouttime + 20 < t)) {
604         ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
605                 gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
606         dump_queue(sub->parent);
607     }
608 */
609         msg->owner_sub = sub;
610         msg->owner_ep = p;
611         msg->seqno = seqno;
612         msg->next = NULL;
613         msg->len = len;
614         msg->retrans = 0;
615         memcpy(msg->buf, data, msg->len);
616
617     ast_mutex_lock(&gw->msgs_lock);
618         cur = gw->msgs;
619         if (cur) {
620                 while(cur->next)
621                         cur = cur->next;
622                 cur->next = msg;
623         } else {
624                 gw->msgs = msg;
625     }
626
627         if (gettimeofday(&tv, NULL) < 0) {
628                 /* This shouldn't ever happen, but let's be sure */
629                 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
630         }
631     else {
632         msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
633
634         if (gw->retransid == -1)
635             gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
636     }
637     ast_mutex_unlock(&gw->msgs_lock);
638 /* SC
639         if (!gw->messagepending) {
640                 gw->messagepending = 1;
641                 gw->lastout = seqno;
642         gw->lastouttime = t;
643 */
644     __mgcp_xmit(gw, msg->buf, msg->len);
645                 /* XXX Should schedule retransmission XXX */
646 /* SC
647         } else
648                 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
649 */
650         return 0;
651 }
652
653 /* SC: modified for new transport */
654 static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, 
655                         struct mgcp_request *req, unsigned int seqno)
656 {
657     int res = 0;
658     struct mgcp_request **queue, *q, *r, *t;
659     ast_mutex_t *l;
660
661     switch (req->cmd) {
662         case MGCP_CMD_DLCX:
663             queue = &sub->cx_queue;
664             l = &sub->cx_queue_lock;
665             ast_mutex_lock(l);
666             q = sub->cx_queue;
667             /* delete pending cx cmds */
668             while (q) {
669                 r = q->next;
670                 free(q);
671                 q = r;
672             }
673             *queue = NULL;
674             break;
675
676         case MGCP_CMD_CRCX:
677         case MGCP_CMD_MDCX:
678             queue = &sub->cx_queue;
679             l = &sub->cx_queue_lock;
680             ast_mutex_lock(l);
681             break;
682
683         case MGCP_CMD_RQNT:
684             queue = &p->rqnt_queue;
685             l = &p->rqnt_queue_lock;
686             ast_mutex_lock(l);
687             break;
688
689         default:
690             queue = &p->cmd_queue;
691             l = &p->cmd_queue_lock;
692             ast_mutex_lock(l);
693             break;
694     }
695
696     r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
697     if (!r) {
698         ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
699         ast_mutex_unlock(l);
700         return -1;
701     }
702     memcpy(r, req, sizeof(struct mgcp_request));
703
704     if (!(*queue)) {
705         if (mgcpdebug) {
706             ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
707                         inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
708         }
709
710         res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
711     }
712     else {
713         if (mgcpdebug) {
714             ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
715                         inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
716         }
717     }
718
719     /* XXX SC: find tail. We could also keep tail in the data struct for faster access */
720     for (t = *queue; t && t->next; t = t->next);
721
722     r->next = NULL;
723     if (t)
724         t->next = r;
725     else
726         *queue = r;
727
728     ast_mutex_unlock(l);
729
730     return res;
731 }
732
733 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
734 {
735         int res;
736         struct mgcp_endpoint *p;
737     struct mgcp_subchannel *sub;
738     char *tone;
739
740     if (mgcpdebug) {
741         ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
742     }
743         sub = ast->pvt->pvt;
744     p = sub->parent;
745
746     switch (p->hookstate) {
747         case MGCP_OFFHOOK:
748             tone = "L/wt";
749             break;
750         case MGCP_ONHOOK:
751         default:
752             tone = "L/rg";
753             break;
754     }
755
756         if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
757                 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
758                 return -1;
759         }
760
761         res = 0;
762         sub->outgoing = 1;
763     sub->cxmode = MGCP_CX_RECVONLY;
764         if (p->type == TYPE_LINE) {
765         if (!sub->rtp) {
766             start_rtp(sub);
767         } else {
768             transmit_modify_request(sub);
769         }
770
771         if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
772             /* try to prevent a callwait from disturbing the other connection */
773             sub->next->cxmode = MGCP_CX_RECVONLY;
774             transmit_modify_request(sub->next);
775         }
776
777                 transmit_notify_request_with_callerid(sub, tone, ast->callerid);
778                 ast_setstate(ast, AST_STATE_RINGING);
779                 ast_queue_control(ast, AST_CONTROL_RINGING);
780
781         if (sub->next->owner && strlen(sub->next->cxident) && strlen(sub->next->callid)) {
782             /* Put the connection back in sendrecv */
783             sub->next->cxmode = MGCP_CX_SENDRECV;
784             transmit_modify_request(sub->next);
785         }
786
787         } else {
788                 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
789                 res = -1;
790         }
791         return res;
792 }
793
794 static int mgcp_hangup(struct ast_channel *ast)
795 {
796         struct mgcp_subchannel *sub = ast->pvt->pvt;
797         struct mgcp_endpoint *p = sub->parent;
798
799         if (option_debug)
800                 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
801         if (!ast->pvt->pvt) {
802                 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
803                 return 0;
804         }
805     if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
806                 ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
807                 return 0;
808     }
809     if (mgcpdebug) {
810         ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
811     }
812
813         if ((p->dtmfinband) && (p->dsp != NULL)){
814         /* SC: check whether other channel is active. */
815         if (!sub->next->owner)
816         {
817             if (mgcpdebug) {
818                 ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
819             }
820             ast_dsp_free(p->dsp);
821             p->dsp = NULL;
822         }
823     }
824         ast_mutex_lock(&sub->lock);
825
826         sub->owner = NULL;
827         if (strlen(sub->cxident)) {
828                 transmit_connection_del(sub);
829     }
830         strcpy(sub->cxident, "");
831     if ((sub == p->sub) && sub->next->owner) {
832         if (p->hookstate == MGCP_OFFHOOK) {
833             if (sub->next->owner && sub->next->owner->bridge) {
834                 transmit_notify_request_with_callerid(p->sub, "L/wt", sub->next->owner->bridge->callerid);
835             }
836         } else {
837             /* set our other connection as the primary and swith over to it */
838             p->sub = sub->next;
839             p->sub->cxmode = MGCP_CX_RECVONLY;
840             transmit_modify_request(p->sub);
841             if (sub->next->owner && sub->next->owner->bridge) {
842                 transmit_notify_request_with_callerid(p->sub, "L/rg", sub->next->owner->callerid);
843             }
844         }
845
846     } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
847         transmit_notify_request(sub, "v");
848     } else if (p->hookstate == MGCP_OFFHOOK) {
849         transmit_notify_request(sub, "ro");
850     } else {
851         transmit_notify_request(sub, "");
852     }
853
854         ast->pvt->pvt = NULL;
855         sub->alreadygone = 0;
856         sub->outgoing = 0;
857         sub->cxmode = MGCP_CX_INACTIVE;
858         strcpy(sub->callid, "");
859         /* Reset temporary destination */
860         memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
861         if (sub->rtp) {
862                 ast_rtp_destroy(sub->rtp);
863                 sub->rtp = NULL;
864         }
865
866         /* SC: Decrement use count */
867     ast_mutex_lock(&usecnt_lock);
868         usecnt--;
869         ast_mutex_unlock(&usecnt_lock);
870         ast_update_use_count();
871     /* SC: Decrement use count */
872
873     if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
874         if (has_voicemail(p)) {
875             if (mgcpdebug) {
876                 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", ast->name, p->name, p->parent->name);
877             }
878             transmit_notify_request(sub, "vmwi(+)");
879         } else {
880             if (mgcpdebug) {
881                 ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", ast->name, p->name, p->parent->name);
882             }
883             transmit_notify_request(sub, "vmwi(-)");
884         }
885     }
886         ast_mutex_unlock(&sub->lock);
887         return 0;
888 }
889
890 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
891 {
892         struct mgcp_gateway  *g;
893         struct mgcp_endpoint *e;
894         int hasendpoints = 0;
895         if (argc != 3) 
896                 return RESULT_SHOWUSAGE;
897         ast_mutex_lock(&gatelock);
898         g = gateways;
899         while(g) {
900                 e = g->endpoints;
901                 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");
902                 while(e) {
903                         ast_cli(fd, "   -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
904                         hasendpoints = 1;
905                         e = e->next;
906                 }
907                 if (!hasendpoints) {
908                         ast_cli(fd, "   << No Endpoints Defined >>     ");
909                 }
910                 g = g->next;
911         }
912         ast_mutex_unlock(&gatelock);
913         return RESULT_SUCCESS;
914 }
915
916 static char show_endpoints_usage[] = 
917 "Usage: mgcp show endpoints\n"
918 "       Lists all endpoints known to the MGCP (Media Gateawy Control Protocol) subsystem.\n";
919
920 static struct ast_cli_entry  cli_show_endpoints = 
921         { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage };
922
923 static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
924 {
925         struct mgcp_gateway  *g;
926         struct mgcp_endpoint *e;
927         int found = 0;
928     char *ename,*gname, *c;
929         if (!mgcpdebug) {
930                 return RESULT_SHOWUSAGE;
931     }
932         if (argc != 4) 
933                 return RESULT_SHOWUSAGE;
934     /* split the name into parts by null */
935     ename = argv[3];
936     gname = ename;
937     while (*gname) {
938         if (*gname == '@') {
939             *gname = 0;
940             gname++;
941             break;
942         }
943         gname++;
944     }
945         if (gname[0] == '[')
946                 gname++;
947         if ((c = strrchr(gname, ']')))
948                 *c = '\0';
949         ast_mutex_lock(&gatelock);
950         g = gateways;
951         while(g) {
952         if (!strcasecmp(g->name, gname)) {
953             e = g->endpoints;
954             while(e) {
955                 if (!strcasecmp(e->name, ename)) {
956                     found = 1;
957                     transmit_audit_endpoint(e);
958                     break;
959                 }
960                 e = e->next;
961             }
962             if (found) {
963                 break;
964             }
965         }
966         g = g->next;
967         }
968     if (!found) {
969         ast_cli(fd, "   << Could not find endpoint >>     ");
970     }
971         ast_mutex_unlock(&gatelock);
972         return RESULT_SUCCESS;
973 }
974
975 static char audit_endpoint_usage[] = 
976 "Usage: mgcp audit endpoint <endpointid>\n"
977 "       List the capabilities of an endpoint in the MGCP (Media Gateawy Control Protocol) subsystem.\n"
978 "       mgcp debug MUST be on to see the results of this command.\n";
979
980 static struct ast_cli_entry  cli_audit_endpoint = 
981         { { "mgcp", "audit", "endpoint", NULL }, mgcp_audit_endpoint, "Audit specified MGCP endpoint", audit_endpoint_usage };
982
983 static int mgcp_answer(struct ast_channel *ast)
984 {
985         int res = 0;
986         struct mgcp_subchannel *sub = ast->pvt->pvt;
987         struct mgcp_endpoint *p = sub->parent;
988     sub->cxmode = MGCP_CX_SENDRECV;
989     if (!sub->rtp) {
990         start_rtp(sub);
991     } else {
992         transmit_modify_request(sub);
993     }
994     /* SC: verbose level check */
995     if (option_verbose > 2) {
996         ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n", ast->name, p->name, p->parent->name, sub->id);
997     }
998         if (ast->_state != AST_STATE_UP) {
999                 ast_setstate(ast, AST_STATE_UP);
1000                 if (option_debug)
1001                         ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
1002                 transmit_notify_request(sub, "");
1003                 transmit_modify_request(sub);
1004         }
1005         return res;
1006 }
1007
1008 static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
1009 {
1010         /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
1011         struct ast_frame *f;
1012         f = ast_rtp_read(sub->rtp);
1013         if (sub->owner) {
1014                 /* We already hold the channel lock */
1015                 if (f->frametype == AST_FRAME_VOICE) {
1016                         if (f->subclass != sub->owner->nativeformats) {
1017                                 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1018                                 sub->owner->nativeformats = f->subclass;
1019                                 ast_set_read_format(sub->owner, sub->owner->readformat);
1020                                 ast_set_write_format(sub->owner, sub->owner->writeformat);
1021                         }
1022             /* Courtesy fearnor aka alex@pilosoft.com */
1023             if (sub->parent->dtmfinband) {
1024 #if 0
1025                 ast_log(LOG_NOTICE, "MGCP ast_dsp_process\n");
1026 #endif
1027                 f = ast_dsp_process(sub->owner, sub->parent->dsp, f);
1028             }
1029                 }
1030         }
1031         return f;
1032 }
1033
1034
1035 static struct ast_frame  *mgcp_read(struct ast_channel *ast)
1036 {
1037         struct ast_frame *fr;
1038         struct mgcp_subchannel *sub = ast->pvt->pvt;
1039         ast_mutex_lock(&sub->lock);
1040         fr = mgcp_rtp_read(sub);
1041         ast_mutex_unlock(&sub->lock);
1042         return fr;
1043 }
1044
1045 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
1046 {
1047         struct mgcp_subchannel *sub = ast->pvt->pvt;
1048         int res = 0;
1049         if (frame->frametype != AST_FRAME_VOICE) {
1050                 if (frame->frametype == AST_FRAME_IMAGE)
1051                         return 0;
1052                 else {
1053                         ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
1054                         return 0;
1055                 }
1056         } else {
1057                 if (!(frame->subclass & ast->nativeformats)) {
1058                         ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
1059                                 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
1060                         return -1;
1061                 }
1062         }
1063         if (sub) {
1064                 ast_mutex_lock(&sub->lock);
1065                 if (sub->rtp) {
1066                         res =  ast_rtp_write(sub->rtp, frame);
1067                 }
1068                 ast_mutex_unlock(&sub->lock);
1069         }
1070         return res;
1071 }
1072
1073 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
1074 {
1075         struct mgcp_subchannel *sub = newchan->pvt->pvt;
1076     ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
1077         if (sub->owner != oldchan) {
1078                 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
1079                 return -1;
1080         }
1081         sub->owner = newchan;
1082         return 0;
1083 }
1084
1085 static int mgcp_senddigit(struct ast_channel *ast, char digit)
1086 {
1087         struct mgcp_subchannel *sub = ast->pvt->pvt;
1088         char tmp[2];
1089         tmp[0] = digit;
1090         tmp[1] = '\0';
1091         transmit_notify_request(sub, tmp);
1092         return -1;
1093 }
1094
1095 static char *control2str(int ind) {
1096     switch (ind) {
1097         case AST_CONTROL_HANGUP:
1098             return "Other end has hungup";
1099         case AST_CONTROL_RING:
1100             return "Local ring";
1101         case AST_CONTROL_RINGING:
1102             return "Remote end is ringing";
1103         case AST_CONTROL_ANSWER:
1104             return "Remote end has answered";
1105         case AST_CONTROL_BUSY:
1106             return "Remote end is busy";
1107         case AST_CONTROL_TAKEOFFHOOK:
1108             return "Make it go off hook";
1109         case AST_CONTROL_OFFHOOK:
1110             return "Line is off hook";
1111         case AST_CONTROL_CONGESTION:
1112             return "Congestion (circuits busy)";
1113         case AST_CONTROL_FLASH:
1114             return "Flash hook";
1115         case AST_CONTROL_WINK:
1116             return "Wink";
1117         case AST_CONTROL_OPTION:
1118             return "Set a low-level option";
1119         case AST_CONTROL_RADIO_KEY:
1120             return "Key Radio";
1121         case AST_CONTROL_RADIO_UNKEY:
1122             return "Un-Key Radio";
1123     }
1124     return "UNKNOWN";
1125 }
1126
1127
1128 static int mgcp_indicate(struct ast_channel *ast, int ind)
1129 {
1130         struct mgcp_subchannel *sub = ast->pvt->pvt;
1131     if (mgcpdebug) {
1132         ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n", ind, control2str(ind), ast->name);
1133     }
1134         switch(ind) {
1135         case AST_CONTROL_RINGING:
1136                 transmit_notify_request(sub, "rt");
1137                 break;
1138         case AST_CONTROL_BUSY:
1139                 transmit_notify_request(sub, "bz");
1140                 break;
1141         case AST_CONTROL_CONGESTION:
1142                 transmit_notify_request(sub, "cg");
1143                 break;
1144         case -1:
1145                 transmit_notify_request(sub, "");
1146                 break;          
1147         default:
1148                 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
1149                 return -1;
1150         }
1151         return 0;
1152 }
1153
1154 static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
1155 {
1156         struct ast_channel *tmp;
1157     struct mgcp_endpoint *i = sub->parent;
1158         int fmt;
1159     i = sub->parent;
1160         tmp = ast_channel_alloc(1);
1161         if (tmp) {
1162                 tmp->nativeformats = i->capability;
1163                 if (!tmp->nativeformats)
1164                         tmp->nativeformats = capability;
1165                 fmt = ast_best_codec(tmp->nativeformats);
1166                 snprintf(tmp->name, sizeof(tmp->name), "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
1167                 if (sub->rtp)
1168                         tmp->fds[0] = ast_rtp_fd(sub->rtp);
1169                 tmp->type = type;
1170                 if (i->dtmfinband) {
1171                     i->dsp = ast_dsp_new();
1172                     ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
1173             /* SC: this is to prevent clipping of dtmf tones during dsp processing */
1174             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
1175                 } else {
1176                     i->dsp = NULL;
1177                 }
1178                 ast_setstate(tmp, state);
1179                 if (state == AST_STATE_RING)
1180                         tmp->rings = 1;
1181                 tmp->writeformat = fmt;
1182                 tmp->pvt->rawwriteformat = fmt;
1183                 tmp->readformat = fmt;
1184                 tmp->pvt->rawreadformat = fmt;
1185                 tmp->pvt->pvt = sub;
1186                 tmp->pvt->call = mgcp_call;
1187                 tmp->pvt->hangup = mgcp_hangup;
1188                 tmp->pvt->answer = mgcp_answer;
1189                 tmp->pvt->read = mgcp_read;
1190                 tmp->pvt->write = mgcp_write;
1191                 tmp->pvt->indicate = mgcp_indicate;
1192                 tmp->pvt->fixup = mgcp_fixup;
1193                 tmp->pvt->send_digit = mgcp_senddigit;
1194                 tmp->pvt->bridge = ast_rtp_bridge;
1195                 if (strlen(i->language))
1196                         strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
1197                 if (strlen(i->accountcode))
1198                         strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode)-1);
1199                 if (i->amaflags)
1200                         tmp->amaflags = i->amaflags;
1201                 sub->owner = tmp;
1202                 ast_mutex_lock(&usecnt_lock);
1203                 usecnt++;
1204                 ast_mutex_unlock(&usecnt_lock);
1205                 ast_update_use_count();
1206                 tmp->callgroup = i->callgroup;
1207                 tmp->pickupgroup = i->pickupgroup;
1208                 strncpy(tmp->call_forward, i->call_forward, sizeof(tmp->call_forward));
1209                 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
1210                 strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
1211                 if (strlen(i->callerid))
1212                         tmp->callerid = strdup(i->callerid);
1213                 if (!i->adsi)
1214                         tmp->adsicpe = AST_ADSI_UNAVAILABLE;
1215                 tmp->priority = 1;
1216                 if (state != AST_STATE_DOWN) {
1217                         if (ast_pbx_start(tmp)) {
1218                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
1219                                 ast_hangup(tmp);
1220                                 tmp = NULL;
1221                         }
1222                 }
1223         /* SC: verbose level check */
1224         if (option_verbose > 2) {
1225             ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n", tmp->name, ast_state2str(state));
1226         }
1227         } else {
1228                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1229     }
1230         return tmp;
1231 }
1232
1233 static char* get_sdp_by_line(char* line, char *name, int nameLen) {
1234   if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
1235     char* r = line + nameLen + 1;
1236     while (*r && (*r < 33)) ++r;
1237     return r;
1238   }
1239
1240   return "";
1241 }
1242
1243 static char *get_sdp(struct mgcp_request *req, char *name) {
1244   int x;
1245   int len = strlen(name);
1246   char *r;
1247
1248   for (x=0; x<req->lines; x++) {
1249     r = get_sdp_by_line(req->line[x], name, len);
1250     if (r[0] != '\0') return r;
1251   }
1252   return "";
1253 }
1254
1255 static void sdpLineNum_iterator_init(int* iterator) {
1256   *iterator = 0;
1257 }
1258
1259 static char* get_sdp_iterate(int* iterator,
1260                              struct mgcp_request *req, char *name) {
1261   int len = strlen(name);
1262   char *r;
1263   while (*iterator < req->lines) {
1264     r = get_sdp_by_line(req->line[(*iterator)++], name, len);
1265     if (r[0] != '\0') return r;
1266   }
1267   return "";
1268 }
1269
1270 static char *__get_header(struct mgcp_request *req, char *name, int *start)
1271 {
1272         int x;
1273         int len = strlen(name);
1274         char *r;
1275         for (x=*start;x<req->headers;x++) {
1276                 if (!strncasecmp(req->header[x], name, len) && 
1277                                 (req->header[x][len] == ':')) {
1278                                         r = req->header[x] + len + 1;
1279                                         while(*r && (*r < 33))
1280                                                         r++;
1281                                         *start = x+1;
1282                                         return r;
1283                 }
1284         }
1285         /* Don't return NULL, so get_header is always a valid pointer */
1286         return "";
1287 }
1288
1289 static char *get_header(struct mgcp_request *req, char *name)
1290 {
1291         int start = 0;
1292         return __get_header(req, name, &start);
1293 }
1294
1295 /* SC: get comma separated value */
1296 static char *get_csv(char *c, int *len, char **next) 
1297 {
1298     char *s;
1299
1300     *next = NULL, *len = 0;
1301     if (!c) return NULL;
1302
1303     while(*c && (*c < 33 || *c == ','))
1304         c++;
1305     
1306     s = c;
1307     while(*c && (*c >= 33 && *c != ','))
1308         c++, (*len)++;
1309     *next = c;
1310     
1311     if (*len == 0)
1312         s = NULL, *next = NULL;
1313     
1314     return s;
1315
1316
1317 #if 0
1318 static int rtpready(struct ast_rtp *rtp, struct ast_frame *f, void *data)
1319 {
1320         /* Just deliver the audio directly */
1321         struct mgcp_endpoint *p = data;
1322         ast_mutex_lock(&p->lock);
1323         if (p->owner) {
1324                 /* Generally, you lock in the order channel lock, followed by private
1325                    lock.  Since here we are doing the reverse, there is the possibility
1326                    of deadlock.  As a result, in the case of a deadlock, we simply fail out
1327                    here. */
1328                 if (!ast_mutex_trylock(&p->owner->lock)) {
1329                         if (f->frametype == AST_FRAME_VOICE) {
1330                                 if (f->subclass != p->owner->nativeformats) {
1331                                         ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
1332                                         p->owner->nativeformats = f->subclass;
1333                                         ast_set_read_format(p->owner, p->owner->readformat);
1334                                         ast_set_write_format(p->owner, p->owner->writeformat);
1335                                 }
1336                                 if (p->dtmfinband) {
1337                                     f = ast_dsp_process(p->owner,p->dsp,f,0);
1338                                 }
1339                         }
1340                         ast_queue_frame(p->owner, f);
1341                         ast_mutex_unlock(&p->owner->lock);
1342                 }
1343         }
1344         ast_mutex_unlock(&p->lock);
1345         return 0;
1346 }
1347 #endif
1348
1349 static struct mgcp_subchannel *find_subchannel(char *name, int msgid, struct sockaddr_in *sin)
1350 {
1351         struct mgcp_endpoint *p = NULL;
1352         struct mgcp_subchannel *sub = NULL;
1353         struct mgcp_gateway *g;
1354         char tmp[256] = "";
1355         char *at = NULL, *c;
1356     int found = 0;
1357         if (name) {
1358                 strncpy(tmp, name, sizeof(tmp) - 1);
1359                 at = strchr(tmp, '@');
1360                 if (!at) {
1361                         ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
1362                         return NULL;
1363                 }
1364                 *at = '\0';
1365                 at++;
1366         }
1367         ast_mutex_lock(&gatelock);
1368         if (at && (at[0] == '[')) {
1369                 at++;
1370                 c = strrchr(at, ']');
1371                 if (c)
1372                         *c = '\0';
1373         }
1374         g = gateways;
1375         while(g) {
1376                 if ((!name || !strcasecmp(g->name, at)) && 
1377                     (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
1378                         /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
1379                         if (sin && g->dynamic && name) {
1380                                 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1381                                         (g->addr.sin_port != sin->sin_port)) {
1382                                         memcpy(&g->addr, sin, sizeof(g->addr));
1383                                         if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
1384                                                 memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
1385                                         if (option_verbose > 2)
1386                                                 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));
1387                                 }
1388                         }
1389             /* SC: not dynamic, check if the name matches */
1390             else if (name) {
1391                 if (strcasecmp(g->name, at)) {
1392                     g = g->next;
1393                     continue;
1394                 }
1395             }
1396             /* SC: not dynamic, no name, check if the addr matches */
1397             else if (!name && sin) {
1398                                 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
1399                                         (g->addr.sin_port != sin->sin_port)) {
1400                     g = g->next;
1401                     continue;
1402                 }
1403             }
1404             else  {
1405                 g = g->next;
1406                 continue;
1407             }
1408             /* SC */
1409                         p = g->endpoints;
1410                         while(p) {
1411                                 if (option_debug)
1412                         ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n", p->name, g->name);
1413                 if (msgid) {
1414 #if 0 /* SC: new transport mech */
1415                     sub = p->sub;
1416                     do {
1417                                                 if (option_debug)
1418                             ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n", p->name, g->name, sub->id, msgid);
1419                         if (sub->lastout == msgid) {
1420                                                         if (option_debug)
1421                                 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", sub->id, msgid, sub->lastout);
1422                             found = 1;
1423                             break;
1424                         }
1425                         sub = sub->next;
1426                     } while (sub != p->sub);
1427                     if (found) {
1428                         break;
1429                     }
1430 #endif
1431                     /* SC */
1432                     sub = p->sub;
1433                     found = 1;
1434                     /* SC */
1435                     break;
1436                 } else if (name && !strcasecmp(p->name, tmp)) {
1437                     ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
1438                             p->name, g->name, p->sub->id);
1439                     sub = p->sub;
1440                     found = 1;
1441                     break;
1442                 }
1443                 p = p->next;
1444                         }
1445                         if (sub && found) {
1446                                 break;
1447             }
1448                 }
1449                 g = g->next;
1450         }
1451         ast_mutex_unlock(&gatelock);
1452         if (!sub) {
1453                 if (name) {
1454                         if (g)
1455                                 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp,at);
1456                         else
1457                                 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1458                 } 
1459         }
1460         return sub;
1461 }
1462
1463 static void parse(struct mgcp_request *req)
1464 {
1465         /* Divide fields by NULL's */
1466         char *c;
1467         int f = 0;
1468         c = req->data;
1469
1470         /* First header starts immediately */
1471         req->header[f] = c;
1472         while(*c) {
1473                 if (*c == '\n') {
1474                         /* We've got a new header */
1475                         *c = 0;
1476
1477 #if 0
1478                         printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
1479 #endif                  
1480                         if (!strlen(req->header[f])) {
1481                                 /* Line by itself means we're now in content */
1482                                 c++;
1483                                 break;
1484                         }
1485                         if (f >= MGCP_MAX_HEADERS - 1) {
1486                                 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1487                         } else
1488                                 f++;
1489                         req->header[f] = c + 1;
1490                 } else if (*c == '\r') {
1491                         /* Ignore but eliminate \r's */
1492                         *c = 0;
1493                 }
1494                 c++;
1495         }
1496         /* Check for last header */
1497         if (strlen(req->header[f])) 
1498                 f++;
1499         req->headers = f;
1500         /* Now we process any mime content */
1501         f = 0;
1502         req->line[f] = c;
1503         while(*c) {
1504                 if (*c == '\n') {
1505                         /* We've got a new line */
1506                         *c = 0;
1507 #if 0
1508                         printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
1509 #endif                  
1510                         if (f >= MGCP_MAX_LINES - 1) {
1511                                 ast_log(LOG_WARNING, "Too many SDP lines...\n");
1512                         } else
1513                                 f++;
1514                         req->line[f] = c + 1;
1515                 } else if (*c == '\r') {
1516                         /* Ignore and eliminate \r's */
1517                         *c = 0;
1518                 }
1519                 c++;
1520         }
1521         /* Check for last line */
1522         if (strlen(req->line[f])) 
1523                 f++;
1524         req->lines = f;
1525         /* Parse up the initial header */
1526         c = req->header[0];
1527         while(*c && *c < 33) c++;
1528         /* First the verb */
1529         req->verb = c;
1530         while(*c && (*c > 32)) c++;
1531         if (*c) {
1532                 *c = '\0';
1533                 c++;
1534                 while(*c && (*c < 33)) c++;
1535                 req->identifier = c;
1536                 while(*c && (*c > 32)) c++;
1537                 if (*c) {
1538                         *c = '\0';
1539                         c++;
1540                         while(*c && (*c < 33)) c++;
1541                         req->endpoint = c;
1542                         while(*c && (*c > 32)) c++;
1543                         if (*c) {
1544                                 *c = '\0';
1545                                 c++;
1546                                 while(*c && (*c < 33)) c++;
1547                                 req->version = c;
1548                                 while(*c && (*c > 32)) c++;
1549                                 while(*c && (*c < 33)) c++;
1550                                 while(*c && (*c > 32)) c++;
1551                                 *c = '\0';
1552                         }
1553                 }
1554         }
1555                 
1556         if (mgcpdebug) {
1557                 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1558                     req->verb, req->identifier, req->endpoint, req->version);
1559                 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
1560         }
1561         if (*c) 
1562                 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1563 }
1564
1565 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1566 {
1567         char *m;
1568         char *c;
1569         char *a;
1570         char host[258];
1571         int len;
1572         int portno;
1573         int peercapability, peerNonCodecCapability;
1574         struct sockaddr_in sin;
1575         char *codecs;
1576         struct hostent *hp;
1577         int codec;
1578         int iterator;
1579     struct mgcp_endpoint *p = sub->parent;
1580
1581         /* Get codec and RTP info from SDP */
1582         m = get_sdp(req, "m");
1583         c = get_sdp(req, "c");
1584         if (!strlen(m) || !strlen(c)) {
1585                 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1586                 return -1;
1587         }
1588         if (sscanf(c, "IN IP4 %256s", host) != 1) {
1589                 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1590                 return -1;
1591         }
1592         /* XXX This could block for a long time, and block the main thread! XXX */
1593         hp = gethostbyname(host);
1594         if (!hp) {
1595                 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1596                 return -1;
1597         }
1598         if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
1599                 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
1600                 return -1;
1601         }
1602         sin.sin_family = AF_INET;
1603         memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1604         sin.sin_port = htons(portno);
1605         ast_rtp_set_peer(sub->rtp, &sin);
1606 #if 0
1607         printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1608 #endif  
1609         // Scan through the RTP payload types specified in a "m=" line:
1610     ast_rtp_pt_clear(sub->rtp);
1611         codecs = m + len;
1612         while(strlen(codecs)) {
1613                 if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
1614                         ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
1615                         return -1;
1616                 }
1617                 ast_rtp_set_m_type(sub->rtp, codec);
1618                 codecs += len;
1619         }
1620
1621         // Next, scan through each "a=rtpmap:" line, noting each
1622         // specified RTP payload type (with corresponding MIME subtype):
1623         sdpLineNum_iterator_init(&iterator);
1624         while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
1625           char* mimeSubtype = strdup(a); // ensures we have enough space
1626           if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
1627           // Note: should really look at the 'freq' and '#chans' params too
1628           ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
1629           free(mimeSubtype);
1630         }
1631
1632         // Now gather all of the codecs that were asked for:
1633         ast_rtp_get_current_formats(sub->rtp,
1634                                 &peercapability, &peerNonCodecCapability);
1635         p->capability = capability & peercapability;
1636         if (mgcpdebug) {
1637                 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
1638                     capability, peercapability, p->capability);
1639                 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
1640                     nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
1641         }
1642         if (!p->capability) {
1643                 ast_log(LOG_WARNING, "No compatible codecs!\n");
1644                 return -1;
1645         }
1646         return 0;
1647         
1648 }
1649
1650 static int add_header(struct mgcp_request *req, char *var, char *value)
1651 {
1652         if (req->len >= sizeof(req->data) - 4) {
1653                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1654                 return -1;
1655         }
1656         if (req->lines) {
1657                 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
1658                 return -1;
1659         }
1660         req->header[req->headers] = req->data + req->len;
1661         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
1662         req->len += strlen(req->header[req->headers]);
1663         if (req->headers < MGCP_MAX_HEADERS)
1664                 req->headers++;
1665         else {
1666                 ast_log(LOG_WARNING, "Out of header space\n");
1667                 return -1;
1668         }
1669         return 0;       
1670 }
1671
1672 static int add_line(struct mgcp_request *req, char *line)
1673 {
1674         if (req->len >= sizeof(req->data) - 4) {
1675                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1676                 return -1;
1677         }
1678         if (!req->lines) {
1679                 /* Add extra empty return */
1680                 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
1681                 req->len += strlen(req->data + req->len);
1682         }
1683         req->line[req->lines] = req->data + req->len;
1684         snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
1685         req->len += strlen(req->line[req->lines]);
1686         if (req->lines < MGCP_MAX_LINES)
1687                 req->lines++;
1688         else {
1689                 ast_log(LOG_WARNING, "Out of line space\n");
1690                 return -1;
1691         }
1692         return 0;       
1693 }
1694
1695 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1696 {
1697         /* Initialize a response */
1698         if (req->headers || req->len) {
1699                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1700                 return -1;
1701         }
1702         req->header[req->headers] = req->data + req->len;
1703         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1704         req->len += strlen(req->header[req->headers]);
1705         if (req->headers < MGCP_MAX_HEADERS)
1706                 req->headers++;
1707         else
1708                 ast_log(LOG_WARNING, "Out of header space\n");
1709         return 0;
1710 }
1711
1712 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1713 {
1714         /* Initialize a response */
1715         if (req->headers || req->len) {
1716                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1717                 return -1;
1718         }
1719         req->header[req->headers] = req->data + req->len;
1720     /* SC: check if we need brackets around the gw name */
1721     if (p->parent->isnamedottedip)
1722         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);
1723     else
1724         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);
1725         req->len += strlen(req->header[req->headers]);
1726         if (req->headers < MGCP_MAX_HEADERS)
1727                 req->headers++;
1728         else
1729                 ast_log(LOG_WARNING, "Out of header space\n");
1730         return 0;
1731 }
1732
1733
1734 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1735 {
1736         memset(resp, 0, sizeof(*resp));
1737         init_resp(resp, msg, req, msgrest);
1738         return 0;
1739 }
1740
1741 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1742 {
1743         memset(req, 0, sizeof(struct mgcp_request));
1744         oseq++;
1745         init_req(p, req, verb);
1746         return 0;
1747 }
1748
1749 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
1750 {
1751         struct mgcp_request resp;
1752     struct mgcp_endpoint *p = sub->parent;
1753         respprep(&resp, p, msg, req, msgrest);
1754         return send_response(sub, &resp);
1755 }
1756
1757
1758 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1759 {
1760         int len;
1761         int codec;
1762         char costr[80];
1763         struct sockaddr_in sin;
1764         char v[256];
1765         char s[256];
1766         char o[256];
1767         char c[256];
1768         char t[256];
1769         char m[256];
1770         char a[1024] = "";
1771         int x;
1772         struct sockaddr_in dest;
1773     struct mgcp_endpoint *p = sub->parent;
1774         /* XXX We break with the "recommendation" and send our IP, in order that our
1775                peer doesn't have to gethostbyname() us XXX */
1776         len = 0;
1777         if (!sub->rtp) {
1778                 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1779                 return -1;
1780         }
1781         ast_rtp_get_us(sub->rtp, &sin);
1782         if (rtp) {
1783                 ast_rtp_get_peer(rtp, &dest);
1784         } else {
1785                 if (sub->tmpdest.sin_addr.s_addr) {
1786                         dest.sin_addr = sub->tmpdest.sin_addr;
1787                         dest.sin_port = sub->tmpdest.sin_port;
1788                         /* Reset temporary destination */
1789                         memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1790                 } else {
1791                         dest.sin_addr = p->parent->ourip;
1792                         dest.sin_port = sin.sin_port;
1793                 }
1794         }
1795         if (mgcpdebug) {
1796                 ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 
1797     }
1798         snprintf(v, sizeof(v), "v=0\r\n");
1799         snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
1800         snprintf(s, sizeof(s), "s=session\r\n");
1801         snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", inet_ntoa(dest.sin_addr));
1802         snprintf(t, sizeof(t), "t=0 0\r\n");
1803         snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
1804         for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1805                 if (p->capability & x) {
1806                         if (mgcpdebug) {
1807                                 ast_verbose("Answering with capability %d\n", x);
1808             }
1809                         codec = ast_rtp_lookup_code(sub->rtp, 1, x);
1810             if (codec > -1) {
1811                                 snprintf(costr, sizeof(costr), " %d", codec);
1812                                 strcat(m, costr);
1813                                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
1814                                 strcat(a, costr);
1815                         }
1816                 }
1817         }
1818         for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1819         if (p->nonCodecCapability & x) {
1820             if (mgcpdebug) {
1821                 ast_verbose("Answering with non-codec capability %d\n", x);
1822             }
1823             codec = ast_rtp_lookup_code(sub->rtp, 0, x);
1824             if (codec > -1) {
1825                 snprintf(costr, sizeof(costr), " %d", codec);
1826                 strcat(m, costr);
1827                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
1828                 strcat(a, costr);
1829                 if (x == AST_RTP_DTMF) {
1830                   /* Indicate we support DTMF...  Not sure about 16, but MSN supports it so dang it, we will too... */
1831                   snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
1832                   strcat(a, costr);
1833                 }
1834             }
1835         }
1836     }
1837         strcat(m, "\r\n");
1838         len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
1839         snprintf(costr, sizeof(costr), "%d", len);
1840         add_line(resp, v);
1841         add_line(resp, o);
1842         add_line(resp, s);
1843         add_line(resp, c);
1844         add_line(resp, t);
1845         add_line(resp, m);
1846         add_line(resp, a);
1847         return 0;
1848 }
1849
1850 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1851 {
1852         struct mgcp_request resp;
1853         char local[256];
1854         char tmp[80];
1855         int x;
1856     struct mgcp_endpoint *p = sub->parent;
1857         if (!strlen(sub->cxident) && rtp) {
1858                 /* We don't have a CXident yet, store the destination and
1859                    wait a bit */
1860                 ast_rtp_get_peer(rtp, &sub->tmpdest);
1861                 return 0;
1862         }
1863         snprintf(local, sizeof(local), "p:20");
1864         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1865                 if (p->capability & x) {
1866                         snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1867                         strcat(local, tmp);
1868                 }
1869         }
1870         reqprep(&resp, p, "MDCX");
1871         add_header(&resp, "C", sub->callid);
1872         add_header(&resp, "L", local);
1873         add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1874     /* SC: X header should not be sent. kept for compatibility */
1875         add_header(&resp, "X", sub->txident);
1876         add_header(&resp, "I", sub->cxident);
1877         /*add_header(&resp, "S", "");*/
1878         add_sdp(&resp, sub, rtp);
1879     /* SC: fill in new fields */
1880     resp.cmd = MGCP_CMD_MDCX;
1881     resp.trid = oseq;
1882         return send_request(p, sub, &resp, oseq); /* SC */
1883 }
1884
1885 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1886 {
1887         struct mgcp_request resp;
1888         char local[256];
1889         char tmp[80];
1890         int x;
1891     struct mgcp_endpoint *p = sub->parent;
1892
1893         snprintf(local, sizeof(local), "p:20");
1894         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1895                 if (p->capability & x) {
1896                         snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1897                         strcat(local, tmp);
1898                 }
1899         }
1900     if (mgcpdebug) {
1901         ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 
1902                     p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
1903     }
1904         reqprep(&resp, p, "CRCX");
1905         add_header(&resp, "C", sub->callid);
1906         add_header(&resp, "L", local);
1907         add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1908     /* SC: X header should not be sent. kept for compatibility */
1909         add_header(&resp, "X", sub->txident);
1910         /*add_header(&resp, "S", "");*/
1911         add_sdp(&resp, sub, rtp);
1912     /* SC: fill in new fields */
1913     resp.cmd = MGCP_CMD_CRCX;
1914     resp.trid = oseq;
1915         return send_request(p, sub, &resp, oseq);  /* SC */
1916 }
1917
1918 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
1919 {
1920         struct mgcp_request resp;
1921     struct mgcp_endpoint *p = sub->parent;
1922
1923     if (mgcpdebug) {
1924         ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
1925                     tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
1926     }
1927         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1928         reqprep(&resp, p, "RQNT");
1929         add_header(&resp, "X", p->rqnt_ident); /* SC */
1930     switch (p->hookstate) {
1931             case MGCP_ONHOOK:
1932             add_header(&resp, "R", "hd(N)");
1933             break;
1934         case MGCP_OFFHOOK:
1935             add_header(&resp, "R", "hu(N), hf(N), D/[0-9#*](N)");
1936             break;
1937     }
1938     if (strlen(tone)) {
1939         add_header(&resp, "S", tone);
1940     }
1941     /* SC: fill in new fields */
1942     resp.cmd = MGCP_CMD_RQNT;
1943     resp.trid = oseq;
1944         return send_request(p, NULL, &resp, oseq); /* SC */
1945 }
1946
1947 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callerid)
1948 {
1949         struct mgcp_request resp;
1950         char cid[256];
1951         char tone2[256];
1952         char *l, *n;
1953         time_t t;
1954         struct tm tm;
1955     struct mgcp_endpoint *p = sub->parent;
1956         
1957         time(&t);
1958         localtime_r(&t,&tm);
1959         if (callerid)
1960                 strncpy(cid, callerid, sizeof(cid) - 1);
1961         else
1962                 strcpy(cid, "");
1963         ast_callerid_parse(cid, &n, &l);
1964         if (l) {
1965                 ast_shrink_phone_number(l);
1966                 if (!ast_isphonenumber(l)) {
1967                         n = l;
1968                         l = "";
1969                 }
1970         } 
1971         if (!n)
1972                 n = "";
1973         if (!l)
1974                 l = "";
1975
1976     /* Keep track of last callerid for blacklist and callreturn */
1977     strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
1978
1979         snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
1980                         tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
1981         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1982         reqprep(&resp, p, "RQNT");
1983         add_header(&resp, "X", p->rqnt_ident); /* SC */
1984     switch (p->hookstate) {
1985             case MGCP_ONHOOK:
1986             add_header(&resp, "R", "L/hd(N)");
1987             break;
1988         case MGCP_OFFHOOK:
1989             add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
1990             break;
1991     }
1992     if (strlen(tone2)) {
1993         add_header(&resp, "S", tone2);
1994     }
1995     if (mgcpdebug) {
1996         ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
1997                     tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
1998     }
1999     /* SC: fill in new fields */
2000     resp.cmd = MGCP_CMD_RQNT;
2001     resp.trid = oseq;
2002         return send_request(p, NULL, &resp, oseq);  /* SC */
2003 }
2004
2005 static int transmit_modify_request(struct mgcp_subchannel *sub)
2006 {
2007         struct mgcp_request resp;
2008     struct mgcp_endpoint *p = sub->parent;
2009         if (!strlen(sub->cxident)) {
2010                 /* We don't have a CXident yet, store the destination and
2011                    wait a bit */
2012                 return 0;
2013         }
2014     if (mgcpdebug) {
2015         ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n", 
2016                     p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2017     }
2018         reqprep(&resp, p, "MDCX");
2019         add_header(&resp, "C", sub->callid);
2020         add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
2021     /* SC: X header should not be sent. kept for compatibility */
2022         add_header(&resp, "X", sub->txident);
2023         add_header(&resp, "I", sub->cxident);
2024     switch (sub->parent->hookstate) {
2025             case MGCP_ONHOOK:
2026             add_header(&resp, "R", "L/hd(N)");
2027             break;
2028         case MGCP_OFFHOOK:
2029             add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
2030             break;
2031     }
2032     /* SC: fill in new fields */
2033     resp.cmd = MGCP_CMD_MDCX;
2034     resp.trid = oseq;
2035         return send_request(p, sub, &resp, oseq); /* SC */
2036 }
2037
2038
2039 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
2040 {
2041         struct mgcp_request resp;
2042         reqprep(&resp, p, "AUEP");
2043     /* SC: removed unknown param VS */
2044         add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");
2045     /* SC: fill in new fields */
2046     resp.cmd = MGCP_CMD_AUEP;
2047     resp.trid = oseq;
2048         return send_request(p, NULL, &resp, oseq);  /* SC */
2049 }
2050
2051 static int transmit_connection_del(struct mgcp_subchannel *sub)
2052 {
2053     struct mgcp_endpoint *p = sub->parent;
2054         struct mgcp_request resp;
2055     if (mgcpdebug) {
2056         ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 
2057                     sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
2058     }
2059         reqprep(&resp, p, "DLCX");
2060     /* SC: check if call id is avail */
2061     if (sub->callid[0])
2062         add_header(&resp, "C", sub->callid);
2063     /* SC: X header should not be sent. kept for compatibility */
2064         add_header(&resp, "X", sub->txident);
2065     /* SC: check if cxident is avail */
2066     if (sub->cxident[0])
2067         add_header(&resp, "I", sub->cxident);
2068     /* SC: fill in new fields */
2069     resp.cmd = MGCP_CMD_DLCX;
2070     resp.trid = oseq;
2071         return send_request(p, sub, &resp, oseq);  /* SC */
2072 }
2073
2074 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
2075 {
2076         struct mgcp_request resp;
2077     if (mgcpdebug) {
2078         ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n", 
2079                     cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
2080     }
2081         reqprep(&resp, p, "DLCX");
2082     /* SC: check if call id is avail */
2083     if (callid && *callid)
2084         add_header(&resp, "C", callid);
2085     /* SC: check if cxident is avail */
2086     if (cxident && *cxident)
2087         add_header(&resp, "I", cxident);
2088     /* SC: fill in new fields */
2089     resp.cmd = MGCP_CMD_DLCX;
2090     resp.trid = oseq;
2091         return send_request(p, p->sub, &resp, oseq);
2092 }
2093
2094 /* SC: cleanup pendng commands */
2095 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub) 
2096 {
2097     struct mgcp_request *t, *q;
2098
2099     if (p) {
2100         ast_mutex_lock(&p->rqnt_queue_lock);
2101         for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
2102         p->rqnt_queue = NULL;
2103         ast_mutex_unlock(&p->rqnt_queue_lock);
2104
2105         ast_mutex_lock(&p->cmd_queue_lock);
2106         for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
2107         p->cmd_queue = NULL;
2108         ast_mutex_unlock(&p->cmd_queue_lock);
2109
2110         ast_mutex_lock(&p->sub->cx_queue_lock);
2111         for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
2112         p->sub->cx_queue = NULL;
2113         ast_mutex_unlock(&p->sub->cx_queue_lock);
2114
2115         ast_mutex_lock(&p->sub->next->cx_queue_lock);
2116         for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
2117         p->sub->next->cx_queue = NULL;
2118         ast_mutex_unlock(&p->sub->next->cx_queue_lock);
2119     }
2120     else if (sub){
2121         ast_mutex_lock(&sub->cx_queue_lock);
2122         for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
2123         sub->cx_queue = NULL;
2124         ast_mutex_unlock(&sub->cx_queue_lock);
2125     }
2126 }
2127
2128
2129 /* SC: remove command transaction from queue */
2130 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
2131                                          struct mgcp_request **queue, ast_mutex_t *l, int ident)
2132 {
2133     struct mgcp_request *prev, *req;
2134
2135     ast_mutex_lock(l);
2136     for (prev = NULL, req = *queue; req; prev = req, req = req->next) {
2137         if (req->trid == ident) {
2138             /* remove from queue */
2139             if (!prev)
2140                 *queue = req->next;
2141             else
2142                 prev->next = req->next;
2143
2144             /* send next pending command */
2145             if (*queue) {
2146                 if (mgcpdebug) {
2147                     ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 
2148                                 inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
2149                 }
2150
2151                 mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
2152             }
2153             break;
2154         }
2155     }
2156     ast_mutex_unlock(l);
2157     return req;
2158 }
2159
2160 /* SC: modified for new transport mechanism */
2161 static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,  
2162                             int result, unsigned int ident, struct mgcp_request *resp)
2163 {
2164     char *c;
2165     struct mgcp_request *req;
2166     struct mgcp_gateway *gw = p->parent;
2167
2168     if (result < 200) {
2169         /* provisional response */
2170         return;
2171     }
2172
2173     if (sub)
2174         req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
2175     else if (!(req = find_command(p, sub, &p->rqnt_queue, &p->rqnt_queue_lock, ident)))
2176         req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
2177
2178     if (!req) {
2179         if (option_verbose > 2) {
2180             ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n", 
2181                         gw->name, ident);
2182         }
2183         return;
2184     }
2185
2186     if (p && (result >= 400) && (result <= 599)) {
2187         switch (result) {
2188             case 401:
2189                 p->hookstate = MGCP_OFFHOOK;
2190                 break;
2191             case 402:
2192                 p->hookstate = MGCP_ONHOOK;
2193                 break;
2194             case 406:
2195                 ast_log(LOG_NOTICE, "Transaction %d timed out\n", ident);
2196                 break;
2197             case 407:
2198                 ast_log(LOG_NOTICE, "Transaction %d aborted\n", ident);
2199                 break;
2200         }
2201         if (sub)
2202         {
2203             if (sub->owner) {
2204                 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
2205                         result, p->name, p->parent->name, sub ? sub->id:-1);
2206                 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2207             }
2208         }
2209         else {
2210             if (p->sub->next->owner) {
2211                 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
2212                         result, p->name, p->parent->name, sub ? sub->id:-1);
2213                 ast_softhangup(p->sub->next->owner, AST_SOFTHANGUP_DEV);
2214             }
2215
2216             if (p->sub->owner) {
2217                 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
2218                         result, p->name, p->parent->name, sub ? sub->id:-1);
2219                 ast_softhangup(p->sub->owner, AST_SOFTHANGUP_DEV);
2220             }
2221
2222             dump_cmd_queues(p, NULL);
2223         }
2224     }
2225
2226     if (resp) {
2227         if (req->cmd == MGCP_CMD_CRCX) {
2228             if ((c = get_header(resp, "I"))) {
2229                 if (strlen(c)) {
2230                     /* SC: if we are hanging up do not process this conn. */
2231                     if (sub->owner) {
2232                         if (strlen(sub->cxident)) {
2233                             if (strcasecmp(c, sub->cxident)) {
2234                                 ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2235                             }
2236                         }
2237                         strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
2238                         if (sub->tmpdest.sin_addr.s_addr) {
2239                             transmit_modify_with_sdp(sub, NULL);
2240                         }
2241                     }
2242                     else {
2243                         /* XXX SC: delete this one
2244                            callid and conn id may already be lost. 
2245                            so the following del conn may have a side effect of 
2246                            cleaning up the next subchannel */
2247                         transmit_connection_del(sub);
2248                     }
2249                 }
2250             }
2251         }
2252
2253         if (req->cmd == MGCP_CMD_AUEP) {
2254             /* SC: check stale connection ids */
2255             if ((c = get_header(resp, "I"))) {
2256                 char *v, *n;
2257                 int len;
2258                 while ((v = get_csv(c, &len, &n))) {
2259                     if (len) {
2260                         if(strncasecmp(v, p->sub->cxident, len) &&
2261                            strncasecmp(v, p->sub->next->cxident, len)) {
2262                             /* connection id not found. delete it */
2263                             char cxident[80];
2264                             memcpy(cxident, v, len);
2265                             cxident[len] = '\0';
2266                             if (option_verbose > 2) {
2267                                 ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n", 
2268                                             cxident, p->name, gw->name);
2269                             }
2270                             transmit_connection_del_w_params(p, NULL, cxident);
2271                         }
2272                     }
2273                     c = n;
2274                 }
2275             }
2276
2277             /* Try to determine the hookstate returned from an audit endpoint command */
2278             if ((c = get_header(resp, "ES"))) {
2279                 if (strlen(c)) {
2280                     if (strstr(c, "hu")) {
2281                         if (p->hookstate != MGCP_ONHOOK) {
2282                             /* SC: XXX cleanup if we think we are offhook XXX */
2283                             if ((p->sub->owner || p->sub->next->owner ) && 
2284                                 p->hookstate == MGCP_OFFHOOK)
2285                                 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2286                             p->hookstate = MGCP_ONHOOK;
2287
2288                             /* SC: update the requested events according to the new hookstate */
2289                             transmit_notify_request(p->sub, "");
2290
2291                             /* SC: verbose level check */
2292                             if (option_verbose > 2) {
2293                                 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
2294                             }
2295                         }
2296                     } else if (strstr(c, "hd")) {
2297                         if (p->hookstate != MGCP_OFFHOOK) {
2298                             p->hookstate = MGCP_OFFHOOK;
2299
2300                             /* SC: update the requested events according to the new hookstate */
2301                             transmit_notify_request(p->sub, "");
2302
2303                             /* SC: verbose level check */
2304                             if (option_verbose > 2) {
2305                                 ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
2306                             }
2307                         }
2308                     }
2309                 }
2310            }
2311         }
2312
2313         if (resp && resp->lines) {
2314             /* SC: do not process sdp if we are hanging up. this may be a late response */
2315             if (sub && sub->owner) {
2316                 if (!sub->rtp)
2317                     start_rtp(sub);
2318                 if (sub->rtp)
2319                     process_sdp(sub, resp);
2320             }
2321         }
2322     }
2323
2324     free(req);
2325 }
2326
2327 static void start_rtp(struct mgcp_subchannel *sub)
2328 {
2329                 ast_mutex_lock(&sub->lock);
2330         /* SC: check again to be on the safe side */
2331         if (sub->rtp) {
2332             ast_rtp_destroy(sub->rtp);
2333             sub->rtp = NULL;
2334         }
2335                 /* Allocate the RTP now */
2336                 sub->rtp = ast_rtp_new(sched, io, 1, 0);
2337                 if (sub->rtp && sub->owner)
2338                         sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
2339                 if (sub->rtp)
2340                         ast_rtp_setnat(sub->rtp, sub->nat);
2341 #if 0
2342                 ast_rtp_set_callback(p->rtp, rtpready);
2343                 ast_rtp_set_data(p->rtp, p);
2344 #endif          
2345                 /* Make a call*ID */
2346         snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
2347                 /* Transmit the connection create */
2348                 transmit_connect_with_sdp(sub, NULL);
2349                 ast_mutex_unlock(&sub->lock);
2350 }
2351
2352 static void *mgcp_ss(void *data)
2353 {
2354         struct ast_channel *chan = data;
2355         struct mgcp_subchannel *sub = chan->pvt->pvt;
2356         struct mgcp_endpoint *p = sub->parent;
2357         char exten[AST_MAX_EXTENSION] = "";
2358         int len = 0;
2359         int timeout = firstdigittimeout;
2360         int res;
2361         int getforward=0;
2362     while(len < AST_MAX_EXTENSION-1) {
2363         res = ast_waitfordigit(chan, timeout);
2364         timeout = 0;
2365         if (res < 0) {
2366             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
2367             /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2368                         ast_indicate(chan, -1);
2369             ast_hangup(chan);
2370             return NULL;
2371         } else if (res)  {
2372             exten[len++]=res;
2373             exten[len] = '\0';
2374         }
2375         if (!ast_ignore_pattern(chan->context, exten)) {
2376             /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2377                         ast_indicate(chan, -1);
2378         } else {
2379             /* XXX Redundant?  We should already be playing dialtone */
2380             /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2381             transmit_notify_request(sub, "dl");
2382         }
2383         if (ast_exists_extension(chan, chan->context, exten, 1, p->callerid)) {
2384             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->callerid)) {
2385                 if (getforward) {
2386                     /* Record this as the forwarding extension */
2387                     strncpy(p->call_forward, exten, sizeof(p->call_forward)); 
2388                     if (option_verbose > 2) {
2389                         ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n", 
2390                                 p->call_forward, chan->name);
2391                     }
2392                     /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2393                     transmit_notify_request(sub, "sl");
2394                     if (res)
2395                         break;
2396                     usleep(500000);
2397                     /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2398                     ast_indicate(chan, -1);
2399                     sleep(1);
2400                     memset(exten, 0, sizeof(exten));
2401                     /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
2402                     transmit_notify_request(sub, "dl");
2403                     len = 0;
2404                     getforward = 0;
2405                 } else  {
2406                     /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
2407                     ast_indicate(chan, -1);
2408                     strncpy(chan->exten, exten, sizeof(chan->exten)-1);
2409                     if (strlen(p->callerid)) {
2410                         if (!p->hidecallerid) {
2411                             /* SC: free existing chan->callerid */
2412                             if (chan->callerid)
2413                                 free(chan->callerid);
2414                             chan->callerid = strdup(p->callerid);
2415                         }
2416                         if (chan->ani)
2417                             free(chan->ani);
2418                         chan->ani = strdup(p->callerid);
2419                     }
2420                     ast_setstate(chan, AST_STATE_RING);
2421                     /*zt_enable_ec(p);*/
2422                     res = ast_pbx_run(chan);
2423                     if (res) {
2424                         ast_log(LOG_WARNING, "PBX exited non-zero\n");
2425                         /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2426                         /*transmit_notify_request(p, "nbz", 1);*/
2427                         transmit_notify_request(sub, "cg");
2428                     }
2429                     return NULL;
2430                 }
2431             } else {
2432                 /* It's a match, but they just typed a digit, and there is an ambiguous match,
2433                    so just set the timeout to matchdigittimeout and wait some more */
2434                 timeout = matchdigittimeout;
2435             }
2436         } else if (res == 0) {
2437             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
2438             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2439             transmit_notify_request(sub, "cg");
2440             /*zt_wait_event(p->subs[index].zfd);*/
2441             ast_hangup(chan);
2442             return NULL;
2443         } else if (p->callwaiting && !strcmp(exten, "*70")) {
2444             if (option_verbose > 2) {
2445                 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
2446             }
2447             /* Disable call waiting if enabled */
2448             p->callwaiting = 0;
2449             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2450             transmit_notify_request(sub, "sl");
2451             len = 0;
2452             memset(exten, 0, sizeof(exten));
2453             timeout = firstdigittimeout;
2454                 
2455         } else if (!strcmp(exten,ast_pickup_ext())) {
2456             /* Scan all channels and see if any there
2457              * ringing channqels with that have call groups
2458              * that equal this channels pickup group  
2459              */
2460             if (ast_pickup_call(chan)) {
2461                 ast_log(LOG_WARNING, "No call pickup possible...\n");
2462                 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
2463                 transmit_notify_request(sub, "cg");
2464             }
2465             ast_hangup(chan);
2466             return NULL;
2467             
2468         } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
2469             if (option_verbose > 2) {
2470                 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
2471             }
2472             /* Disable Caller*ID if enabled */
2473             p->hidecallerid = 1;
2474             if (chan->callerid)
2475                 free(chan->callerid);
2476             chan->callerid = NULL;
2477             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2478             transmit_notify_request(sub, "sl");
2479             len = 0;
2480             memset(exten, 0, sizeof(exten));
2481             timeout = firstdigittimeout;
2482         } else if (p->callreturn && !strcmp(exten, "*69")) {
2483             res = 0;
2484             if (strlen(p->lastcallerid)) {
2485                 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
2486             }
2487             if (!res)
2488                 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2489                 transmit_notify_request(sub, "sl");
2490             break;
2491         } else if (!strcmp(exten, "*78")) {
2492             /* Do not disturb */
2493             if (option_verbose > 2) {
2494                 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
2495             }
2496             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2497             transmit_notify_request(sub, "sl");
2498             p->dnd = 1;
2499             getforward = 0;
2500             memset(exten, 0, sizeof(exten));
2501             len = 0;
2502         } else if (!strcmp(exten, "*79")) {
2503             /* Do not disturb */
2504             if (option_verbose > 2) {
2505                 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
2506             }
2507             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2508             transmit_notify_request(sub, "sl");
2509             p->dnd = 0;
2510             getforward = 0;
2511             memset(exten, 0, sizeof(exten));
2512             len = 0;
2513         } else if (p->cancallforward && !strcmp(exten, "*72")) {
2514             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2515             transmit_notify_request(sub, "sl");
2516             getforward = 1;
2517             memset(exten, 0, sizeof(exten));
2518             len = 0;
2519         } else if (p->cancallforward && !strcmp(exten, "*73")) {
2520             if (option_verbose > 2) {
2521                 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
2522             }
2523             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2524             transmit_notify_request(sub, "sl");
2525             memset(p->call_forward, 0, sizeof(p->call_forward));
2526             getforward = 0;
2527             memset(exten, 0, sizeof(exten));
2528             len = 0;
2529         } else if (!strcmp(exten, ast_parking_ext()) && 
2530                     sub->next->owner &&
2531                     sub->next->owner->bridge) {
2532             /* This is a three way call, the main call being a real channel, 
2533                 and we're parking the first call. */
2534             ast_masq_park_call(sub->next->owner->bridge, chan, 0, NULL);
2535             if (option_verbose > 2) {
2536                 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
2537             }
2538             break;
2539         } else if (strlen(p->lastcallerid) && !strcmp(exten, "*80")) {
2540             if (option_verbose > 2) {
2541                 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
2542             }
2543             res = ast_db_put("blacklist", p->lastcallerid, "1");
2544             if (!res) {
2545                 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2546                 transmit_notify_request(sub, "sl");
2547                 memset(exten, 0, sizeof(exten));
2548                 len = 0;
2549             }
2550         } else if (p->hidecallerid && !strcmp(exten, "*82")) {
2551             if (option_verbose > 2) {
2552                 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
2553             }
2554             /* Enable Caller*ID if enabled */
2555             p->hidecallerid = 0;
2556             if (chan->callerid)
2557                 free(chan->callerid);
2558             if (strlen(p->callerid))
2559                 chan->callerid = strdup(p->callerid);
2560             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
2561             transmit_notify_request(sub, "sl");
2562             len = 0;
2563             memset(exten, 0, sizeof(exten));
2564             timeout = firstdigittimeout;
2565         } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->callerid) &&
2566                         ((exten[0] != '*') || (strlen(exten) > 2))) {
2567             if (option_debug)
2568                 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->callerid ? chan->callerid : "<Unknown Caller>", chan->context);
2569             break;
2570         }
2571         if (!timeout)
2572             timeout = gendigittimeout;
2573         if (len && !ast_ignore_pattern(chan->context, exten))
2574             /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
2575                         ast_indicate(chan, -1);
2576     }
2577 #if 0
2578         for (;;) {
2579                 res = ast_waitfordigit(chan, to);
2580                 if (!res) {
2581                         ast_log(LOG_DEBUG, "Timeout...\n");
2582                         break;
2583                 }
2584                 if (res < 0) {
2585                         ast_log(LOG_DEBUG, "Got hangup...\n");
2586             ast_hangup(chan);
2587                         break;
2588                 }
2589                 exten[pos++] = res;
2590                 if (!ast_ignore_pattern(chan->context, exten))
2591                         ast_indicate(chan, -1);
2592                 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
2593                         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
2594                                 to = 3000;
2595                         else
2596                                 to = 8000;
2597                 } else
2598                         break;
2599         }
2600         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
2601                 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
2602         if (!p->rtp) {
2603             start_rtp(p);
2604         }
2605                 ast_setstate(chan, AST_STATE_RING);
2606                 chan->rings = 1;
2607                 if (ast_pbx_run(chan)) {
2608                         ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
2609                 } else
2610                         return NULL;
2611         }
2612 #endif
2613         ast_hangup(chan);
2614         return NULL;
2615 }
2616
2617 static int attempt_transfer(struct mgcp_endpoint *p)
2618 {
2619     /* *************************
2620      * I hope this works.
2621      * Copied out of chan_zap
2622      * Cross your fingers
2623      * *************************/
2624
2625         /* In order to transfer, we need at least one of the channels to
2626            actually be in a call bridge.  We can't conference two applications
2627            together (but then, why would we want to?) */
2628         if (p->sub->owner->bridge) {
2629                 /* The three-way person we're about to transfer to could still be in MOH, so
2630                    stop if now if appropriate */
2631                 if (p->sub->next->owner->bridge)
2632                         ast_moh_stop(p->sub->next->owner->bridge);
2633                 if (p->sub->owner->_state == AST_STATE_RINGING) {
2634                         ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING);
2635                 }
2636                 if (ast_channel_masquerade(p->sub->next->owner, p->sub->owner->bridge)) {
2637                         ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2638                                         p->sub->owner->bridge->name, p->sub->next->owner->name);
2639                         return -1;
2640                 }
2641                 /* Orphan the channel */
2642                 unalloc_sub(p->sub->next);
2643         } else if (p->sub->next->owner->bridge) {
2644                 if (p->sub->owner->_state == AST_STATE_RINGING) {
2645                         ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING);
2646                 }
2647                 ast_moh_stop(p->sub->next->owner->bridge);
2648                 if (ast_channel_masquerade(p->sub->owner, p->sub->next->owner->bridge)) {
2649                         ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2650                                         p->sub->next->owner->bridge->name, p->sub->owner->name);
2651                         return -1;
2652                 }
2653                 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
2654         if (option_verbose > 2) {
2655             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);
2656         }
2657         p->sub = p->sub->next;
2658                 unalloc_sub(p->sub->next);
2659                 /* Tell the caller not to hangup */
2660                 return 1;
2661         } else {
2662                 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
2663                                         p->sub->owner->name, p->sub->next->owner->name);
2664                 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2665         if (p->sub->next->owner) {
2666             p->sub->next->alreadygone = 1;
2667             ast_queue_hangup(p->sub->next->owner);
2668         }
2669         }
2670         return 0;
2671 }
2672
2673 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) 
2674 {
2675     struct mgcp_endpoint *p = sub->parent;
2676     struct ast_channel *c;
2677         pthread_t t;
2678         pthread_attr_t attr;
2679         pthread_attr_init(&attr);
2680         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    
2681
2682     /* Off hook / answer */
2683     if (sub->outgoing) {
2684         /* Answered */
2685         if (sub->owner) {
2686             if (sub->owner->bridge) {
2687                 ast_moh_stop(sub->owner->bridge);
2688             }
2689             sub->cxmode = MGCP_CX_SENDRECV;
2690             if (!sub->rtp) {
2691                 start_rtp(sub);
2692             } else {
2693                 transmit_modify_request(sub);
2694             }
2695             /*transmit_notify_request(sub, "aw");*/
2696             transmit_notify_request(sub, "");
2697             ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
2698         }
2699     } else {
2700         /* Start switch */
2701         /*sub->cxmode = MGCP_CX_SENDRECV;*/
2702         if (!sub->owner) {
2703             if (!sub->rtp) {
2704                 start_rtp(sub);
2705             } else {
2706                 transmit_modify_request(sub);
2707             }
2708             if (p->immediate) {
2709                 /* The channel is immediately up.  Start right away */
2710                 transmit_notify_request(sub, "rt");
2711                 c = mgcp_new(sub, AST_STATE_RING);
2712                 if (!c) {
2713                     ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
2714                     transmit_notify_request(sub, "cg");
2715                     ast_hangup(c);
2716                 }
2717             } else {
2718                 if (has_voicemail(p)) {
2719                     transmit_notify_request(sub, "sl");
2720                 } else {
2721                     transmit_notify_request(sub, "dl");
2722                 }
2723                 c = mgcp_new(sub, AST_STATE_DOWN);
2724                 if (c) {
2725                     if (pthread_create(&t, &attr, mgcp_ss, c)) {
2726                         ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
2727                         ast_hangup(c);
2728                     }
2729                 } else {
2730                     ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
2731                 }
2732             }
2733         } else {
2734             if (p->hookstate == MGCP_OFFHOOK) {
2735                 ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
2736             } else {
2737                 ast_log(LOG_WARNING, "On hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
2738                 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
2739             }
2740             if (sub->owner->bridge) {
2741                 ast_moh_stop(sub->owner->bridge);
2742             }
2743             sub->cxmode = MGCP_CX_SENDRECV;
2744             if (!sub->rtp) {
2745                 start_rtp(sub);
2746             } else {
2747                 transmit_modify_request(sub);
2748             }
2749             /*transmit_notify_request(sub, "aw");*/
2750             transmit_notify_request(sub, "");
2751             /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
2752         }
2753     }
2754 }
2755
2756 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
2757 {
2758         char *ev, *s;
2759         struct ast_frame f = { 0, };
2760     struct mgcp_endpoint *p = sub->parent;
2761     int res;
2762         if (mgcpdebug) {
2763                 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
2764     }
2765         /* Clear out potential response */
2766         if (!strcasecmp(req->verb, "RSIP")) {
2767                 /* Test if this RSIP request is just a keepalive */
2768                 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
2769                         if (option_verbose > 2)
2770                                 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
2771                         transmit_response(sub, "200", req, "OK");
2772                 } else {
2773                         dump_queue(p->parent, p);
2774             dump_cmd_queues(p, NULL);
2775                         if (option_verbose > 2) {
2776                                 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
2777                         }
2778                         if (sub->owner) {
2779                                 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2780                         }
2781                         transmit_response(sub, "200", req, "OK");
2782                         transmit_notify_request(sub, "");
2783             /* SC: Audit endpoint. 
2784                Idea is to prevent lost lines due to race conditions 
2785              */
2786             transmit_audit_endpoint(p);
2787                 }
2788         } else if (!strcasecmp(req->verb, "NTFY")) {
2789                 /* Acknowledge and be sure we keep looking for the same things */
2790                 transmit_response(sub, "200", req, "OK");
2791                 /* Notified of an event */
2792                 ev = get_header(req, "O");
2793                 s = strchr(ev, '/');
2794                 if (s) ev = s + 1;
2795         if (option_verbose > 2) {
2796             ast_verbose(VERBOSE_PREFIX_3 "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
2797         }
2798                 /* Keep looking for events unless this was a hangup */
2799                 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd")) {
2800                         transmit_notify_request(sub, p->curtone);
2801         }
2802                 if (!strcasecmp(ev, "hd")) {
2803             p->hookstate = MGCP_OFFHOOK;
2804             sub->cxmode = MGCP_CX_SENDRECV;
2805             handle_hd_hf(sub, ev);
2806                 } else if (!strcasecmp(ev, "hf")) {
2807             /* We can assume we are offhook if we received a hookflash */
2808             /* First let's just do call wait and ignore threeway */
2809             /* We're currently in charge */
2810             if (p->hookstate != MGCP_OFFHOOK) {
2811                 /* Cisco c7940 sends hf even if the phone is onhook */
2812                 /* Thanks to point on IRC for pointing this out */
2813                 return -1;
2814             }
2815             /* do not let * confrnce two down channels */  
2816             if( sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1;
2817
2818             if (p->callwaiting || p->transfer || p->threewaycalling) {
2819                 if (option_verbose > 2) {
2820                     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);
2821                 }
2822                 p->sub = p->sub->next;
2823
2824                 /* transfer control to our next subchannel */
2825                 if (!sub->next->owner) {
2826                     /* plave the first call on hold and start up a new call */
2827                     sub->cxmode = MGCP_CX_MUTE;
2828                     if (option_verbose > 2) {
2829                         ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
2830                     }
2831                     transmit_modify_request(sub);
2832                     if (sub->owner && sub->owner->bridge) {
2833                         ast_moh_start(sub->owner->bridge, NULL);
2834                     }
2835                     sub->next->cxmode = MGCP_CX_RECVONLY;
2836                     handle_hd_hf(sub->next, ev);
2837                 } else if (sub->owner && sub->next->owner) {
2838                     /* We've got two active calls lets decide whether or not to conference or just flip flop */
2839                     if ((!sub->outgoing) && (!sub->next->outgoing)) {
2840                         /* We made both calls lets conferenct */
2841                         if (option_verbose > 2) {
2842                             ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n", 
2843                                         sub->id, sub->next->id, p->name, p->parent->name);
2844                         }
2845                         sub->cxmode = MGCP_CX_CONF;
2846                         sub->next->cxmode = MGCP_CX_CONF;
2847                         if (sub->next->owner->bridge) {
2848                             ast_moh_stop(sub->next->owner->bridge);
2849                         }
2850                         transmit_modify_request(sub);
2851                         transmit_modify_request(sub->next);
2852                     } else {
2853                         /* Let's flipflop between calls */
2854                         /* XXX Need to check for state up ??? */
2855                         /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
2856                         if (option_verbose > 2) {
2857                             ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 
2858                                         sub->id, sub->next->id, p->name, p->parent->name);
2859                         }
2860                         sub->cxmode = MGCP_CX_MUTE;
2861                         if (option_verbose > 2) {
2862                             ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
2863                         }
2864                         transmit_modify_request(sub);
2865                         if (sub->owner->bridge) {
2866                             ast_moh_start(sub->owner->bridge, NULL);
2867                         }
2868                         if (sub->next->owner->bridge) {
2869                             ast_moh_stop(sub->next->owner->bridge);
2870                         }
2871                         handle_hd_hf(sub->next, ev);
2872 #if 0
2873                         if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) {
2874                             handle_hd_hf(sub->next, ev);
2875                         } else {
2876                             ast_verbose(VERBOSE_PREFIX_3 "MGCP Unmuting %d on %s@%s\n", sub->next->id, p->name, p->parent->name);
2877                             sub->next->cxmode = MGCP_CX_SENDRECV;
2878                             transmit_modify_request(sub->next);
2879                         }
2880 #endif
2881                     }
2882                 } else {
2883                     /* We've most likely lost one of our calls find an active call and bring it up */
2884                     if (sub->owner) {
2885                         p->sub = sub;
2886                     } else if (sub->next->owner) {
2887                         p->sub = sub->next;
2888                     } else {
2889                         /* We seem to have lost both our calls */
2890                         /* XXX - What do we do now? */
2891                         return -1;
2892                     }
2893                     if (p->sub->owner->bridge) {
2894                         ast_moh_stop(p->sub->owner->bridge);
2895                     }
2896                     p->sub->cxmode = MGCP_CX_SENDRECV;
2897                     transmit_modify_request(p->sub);
2898                 }
2899             } else {
2900                 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 
2901                         p->name, p->parent->name);
2902             }
2903             /* ast_moh_stop(sub->owner->bridge); */
2904                 } else if (!strcasecmp(ev, "hu")) {
2905             p->hookstate = MGCP_ONHOOK;
2906             sub->cxmode = MGCP_CX_RECVONLY;
2907             ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
2908             if (sub->rtp) {
2909                 transmit_modify_request(sub);
2910             }
2911             if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
2912                 /* We're allowed to transfer, we have two avtive calls and */
2913                 /* we made at least one of the calls.  Let's try and transfer */
2914                 if ((res = attempt_transfer(p)) < 0) {
2915                     if (p->sub->next->owner) {
2916                         sub->next->alreadygone = 1;
2917                         ast_queue_hangup(sub->next->owner);
2918                     }
2919                 } else if (res) {
2920                     ast_log(LOG_WARNING, "Transfer attempt failed\n");
2921                     return -1;
2922                 }
2923             } else {
2924                 /* Hangup the current call */
2925                 /* If there is another active call, mgcp_hangup will ring the phone with the other call */
2926                 if (sub->owner) {
2927                     sub->alreadygone = 1;
2928                     ast_queue_hangup(sub->owner);
2929                 } else {
2930                     /* SC: verbose level check */
2931                     if (option_verbose > 2) {
2932                         ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed\n", 
2933                                     p->name, p->parent->name, sub->id);
2934                     }
2935                 }
2936             }
2937             if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
2938                 if (has_voicemail(p)) {
2939                     if (option_verbose > 2) {
2940                         ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
2941                     }
2942                     transmit_notify_request(sub, "vmwi(+)");
2943                 } else {
2944                     if (option_verbose > 2) {
2945                         ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
2946                     }
2947                     transmit_notify_request(sub, "vmwi(-)");
2948                 }
2949             }
2950                 } else if ((strlen(ev) == 1) && 
2951                                         (((ev[0] >= '0') && (ev[0] <= '9')) ||
2952                                          ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
2953                                          (ev[0] == '*') || (ev[0] == '#'))) {
2954                         f.frametype = AST_FRAME_DTMF;
2955                         f.subclass = ev[0];
2956                         f.src = "mgcp";
2957                         if (sub->owner) {
2958                 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
2959                                 ast_queue_frame(sub->owner, &f);
2960                 if (sub->next->owner) {
2961                     ast_queue_frame(sub->next->owner, &f);
2962                 }
2963             }
2964             if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
2965                 memset(p->curtone, 0, sizeof(p->curtone));
2966             }
2967                 } 
2968         else if (!strcasecmp(ev, "T")) {
2969                         /* Digit timeout -- unimportant */
2970                 } else {
2971                         ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
2972                 }
2973         } else {
2974                 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, inet_ntoa(sin->sin_addr));
2975                 transmit_response(sub, "510", req, "Unknown verb");
2976         }
2977         return 0;
2978 }
2979
2980 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
2981 {
2982         struct mgcp_request req;
2983         struct sockaddr_in sin;
2984         struct mgcp_subchannel *sub;
2985         int res;
2986         int len;
2987         int result;
2988         int ident;
2989         len = sizeof(sin);
2990         memset(&req, 0, sizeof(req));
2991         res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
2992         if (res < 0) {
2993                 if (errno != ECONNREFUSED)
2994                         ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
2995                 return 1;
2996         }
2997         req.data[res] = '\0';
2998         req.len = res;
2999         if (mgcpdebug) {
3000                 ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
3001     }
3002         parse(&req);
3003         if (req.headers < 1) {
3004                 /* Must have at least one header */
3005                 return 1;
3006         }
3007         if (!req.identifier || !strlen(req.identifier)) {
3008                 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", inet_ntoa(sin.sin_addr));
3009                 return 1;
3010         }
3011
3012         if (sscanf(req.verb, "%d", &result) &&
3013                 sscanf(req.identifier, "%d", &ident)) {
3014                 /* Try to find who this message is for, if it's important */
3015                 sub = find_subchannel(NULL, ident, &sin);
3016                 if (sub) {
3017             struct mgcp_gateway *gw = sub->parent->parent;
3018             struct mgcp_message *cur, *prev;
3019
3020             ast_mutex_lock(&gw->msgs_lock);
3021             for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
3022                 if (cur->seqno == ident) {
3023                     ast_log(LOG_DEBUG, "Got response back on tansaction %d\n", ident);
3024                     if (prev)
3025                         prev->next = cur->next;
3026                     else 
3027                         gw->msgs = cur->next;
3028                     break;
3029                 }
3030             }
3031
3032             /* stop retrans timer if the queue is empty */
3033             if (!gw->msgs && (gw->retransid != -1)) {
3034                 ast_sched_del(sched, gw->retransid);
3035                 gw->retransid = -1;
3036             }
3037
3038             ast_mutex_unlock(&gw->msgs_lock);
3039
3040             if (cur) {
3041                 handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
3042                 free(cur);
3043                 return 1;
3044             }
3045
3046             ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 
3047                     gw->name, ident);
3048                 }
3049         } else {
3050                 if (!req.endpoint || !strlen(req.endpoint) || 
3051                     !req.version || !strlen(req.version) || 
3052                         !req.verb || !strlen(req.verb)) {
3053                         ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
3054                         return 1;
3055                 }
3056                 /* Process request, with iflock held */
3057                 sub = find_subchannel(req.endpoint, 0, &sin);
3058                 if (sub) {
3059             /* pass the request off to the currently mastering subchannel */
3060                         handle_request(sub, &req, &sin);
3061                 }
3062         }
3063         return 1;
3064 }
3065
3066 static void *do_monitor(void *data)
3067 {
3068         int res;
3069         int reloading;
3070     /* struct mgcp_gateway *g; */
3071     /* struct mgcp_endpoint *e; */
3072         /*time_t thispass = 0, lastpass = 0;*/
3073
3074         /* Add an I/O event to our UDP socket */
3075         if (mgcpsock > -1) 
3076                 ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
3077         
3078         /* This thread monitors all the frame relay interfaces which are not yet in use
3079            (and thus do not have a separate thread) indefinitely */
3080         /* From here on out, we die whenever asked */
3081         for(;;) {
3082         /* Check for a reload request */
3083                 ast_mutex_lock(&mgcp_reload_lock);
3084                 reloading = mgcp_reloading;
3085                 mgcp_reloading = 0;
3086                 ast_mutex_unlock(&mgcp_reload_lock);
3087                 if (reloading) {
3088                         if (option_verbose > 0)
3089                                 ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
3090                         mgcp_do_reload();
3091                 }
3092
3093         /* Check for interfaces needing to be killed */
3094                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
3095                    and wait for the monitor list, but the other way around is okay. */
3096                 ast_mutex_lock(&monlock);
3097                 /* Lock the network interface */
3098                 ast_mutex_lock(&netlock);
3099
3100         /* XXX THIS IS COMPLETELY HOSED */
3101         /* The gateway goes into a state of panic */
3102         /* If the vmwi indicator is sent while it is reseting interfaces */
3103 #if 0
3104         lastpass = thispass;
3105         thispass = time(NULL);
3106         g = gateways;
3107         while(g) {
3108             if (thispass != lastpass) {
3109                 e = g->endpoints;
3110                 while(e) {
3111                     if (e->type == TYPE_LINE) {
3112                         res = has_voicemail(e);
3113                         if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
3114                             if (res) {
3115                                 transmit_notify_request(e, "vmwi(+)");
3116                             } else {
3117                                 transmit_notify_request(e, "vmwi(-)");
3118                             }
3119                             e->msgstate = res;
3120                             e->onhooktime = thispass;
3121                         }
3122                     }
3123                     e = e->next;
3124                 }
3125             }
3126             g = g->next;
3127         }
3128 #endif
3129         
3130                 /* Okay, now that we know what to do, release the network lock */
3131                 ast_mutex_unlock(&netlock);
3132                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
3133                 ast_mutex_unlock(&monlock);
3134                 pthread_testcancel();
3135                 /* Wait for sched or io */
3136                 res = ast_sched_wait(sched);
3137         /* SC: copied from chan_sip.c */
3138                 if ((res < 0) || (res > 1000))
3139                         res = 1000;
3140                 res = ast_io_wait(io, res);
3141                 ast_mutex_lock(&monlock);
3142                 if (res >= 0) 
3143                         ast_sched_runq(sched);
3144                 ast_mutex_unlock(&monlock);
3145         }
3146         /* Never reached */
3147         return NULL;
3148         
3149 }
3150
3151 static int restart_monitor(void)
3152 {
3153         pthread_attr_t attr;
3154         pthread_attr_init(&attr);
3155         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    
3156
3157         /* If we're supposed to be stopped -- stay stopped */
3158         if (monitor_thread == AST_PTHREADT_STOP)
3159                 return 0;
3160         if (ast_mutex_lock(&monlock)) {
3161                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
3162                 return -1;
3163         }
3164         if (monitor_thread == pthread_self()) {
3165                 ast_mutex_unlock(&monlock);
3166                 ast_log(LOG_WARNING, "Cannot kill myself\n");