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