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