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