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