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