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