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