38a5483ed36f70123887bab40cb9320560ee5bd5
[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 && name) {
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                                 if (option_debug)
1064                         ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n", p->name, g->name);
1065                 if (msgid) {
1066                     sub = p->sub;
1067                     do {
1068                                                 if (option_debug)
1069                             ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n", p->name, g->name, sub->id, msgid);
1070                         if (sub->lastout == msgid) {
1071                                                         if (option_debug)
1072                                 ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n", sub->id, msgid, sub->lastout);
1073                             found = 1;
1074                             break;
1075                         }
1076                         sub = sub->next;
1077                     } while (sub != p->sub);
1078                     if (found) {
1079                         break;
1080                     }
1081                 } else if (name && !strcasecmp(p->name, tmp)) {
1082                     ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
1083                             p->name, g->name, p->sub->id);
1084                     sub = p->sub;
1085                     found = 1;
1086                     break;
1087                 }
1088                 p = p->next;
1089                         }
1090                         if (sub && found) {
1091                                 break;
1092             }
1093                 }
1094                 g = g->next;
1095         }
1096         ast_mutex_unlock(&gatelock);
1097         if (!sub) {
1098                 if (name) {
1099                         if (g)
1100                                 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp,at);
1101                         else
1102                                 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
1103                 } 
1104         }
1105         return sub;
1106 }
1107
1108 static void parse(struct mgcp_request *req)
1109 {
1110         /* Divide fields by NULL's */
1111         char *c;
1112         int f = 0;
1113         c = req->data;
1114
1115         /* First header starts immediately */
1116         req->header[f] = c;
1117         while(*c) {
1118                 if (*c == '\n') {
1119                         /* We've got a new header */
1120                         *c = 0;
1121
1122 #if 0
1123                         printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
1124 #endif                  
1125                         if (!strlen(req->header[f])) {
1126                                 /* Line by itself means we're now in content */
1127                                 c++;
1128                                 break;
1129                         }
1130                         if (f >= MGCP_MAX_HEADERS - 1) {
1131                                 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
1132                         } else
1133                                 f++;
1134                         req->header[f] = c + 1;
1135                 } else if (*c == '\r') {
1136                         /* Ignore but eliminate \r's */
1137                         *c = 0;
1138                 }
1139                 c++;
1140         }
1141         /* Check for last header */
1142         if (strlen(req->header[f])) 
1143                 f++;
1144         req->headers = f;
1145         /* Now we process any mime content */
1146         f = 0;
1147         req->line[f] = c;
1148         while(*c) {
1149                 if (*c == '\n') {
1150                         /* We've got a new line */
1151                         *c = 0;
1152 #if 0
1153                         printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
1154 #endif                  
1155                         if (f >= MGCP_MAX_LINES - 1) {
1156                                 ast_log(LOG_WARNING, "Too many SDP lines...\n");
1157                         } else
1158                                 f++;
1159                         req->line[f] = c + 1;
1160                 } else if (*c == '\r') {
1161                         /* Ignore and eliminate \r's */
1162                         *c = 0;
1163                 }
1164                 c++;
1165         }
1166         /* Check for last line */
1167         if (strlen(req->line[f])) 
1168                 f++;
1169         req->lines = f;
1170         /* Parse up the initial header */
1171         c = req->header[0];
1172         while(*c && *c < 33) c++;
1173         /* First the verb */
1174         req->verb = c;
1175         while(*c && (*c > 32)) c++;
1176         if (*c) {
1177                 *c = '\0';
1178                 c++;
1179                 while(*c && (*c < 33)) c++;
1180                 req->identifier = c;
1181                 while(*c && (*c > 32)) c++;
1182                 if (*c) {
1183                         *c = '\0';
1184                         c++;
1185                         while(*c && (*c < 33)) c++;
1186                         req->endpoint = c;
1187                         while(*c && (*c > 32)) c++;
1188                         if (*c) {
1189                                 *c = '\0';
1190                                 c++;
1191                                 while(*c && (*c < 33)) c++;
1192                                 req->version = c;
1193                                 while(*c && (*c > 32)) c++;
1194                                 while(*c && (*c < 33)) c++;
1195                                 while(*c && (*c > 32)) c++;
1196                                 *c = '\0';
1197                         }
1198                 }
1199         }
1200                 
1201         if (mgcpdebug) {
1202                 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
1203                     req->verb, req->identifier, req->endpoint, req->version);
1204                 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
1205         }
1206         if (*c) 
1207                 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
1208 }
1209
1210 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
1211 {
1212         char *m;
1213         char *c;
1214         char *a;
1215         char host[258];
1216         int len;
1217         int portno;
1218         int peercapability, peerNonCodecCapability;
1219         struct sockaddr_in sin;
1220         char *codecs;
1221         struct hostent *hp;
1222         int codec;
1223         int iterator;
1224     struct mgcp_endpoint *p = sub->parent;
1225
1226         /* Get codec and RTP info from SDP */
1227         m = get_sdp(req, "m");
1228         c = get_sdp(req, "c");
1229         if (!strlen(m) || !strlen(c)) {
1230                 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
1231                 return -1;
1232         }
1233         if (sscanf(c, "IN IP4 %256s", host) != 1) {
1234                 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
1235                 return -1;
1236         }
1237         /* XXX This could block for a long time, and block the main thread! XXX */
1238         hp = gethostbyname(host);
1239         if (!hp) {
1240                 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
1241                 return -1;
1242         }
1243         if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
1244                 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
1245                 return -1;
1246         }
1247         sin.sin_family = AF_INET;
1248         memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
1249         sin.sin_port = htons(portno);
1250         ast_rtp_set_peer(sub->rtp, &sin);
1251 #if 0
1252         printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1253 #endif  
1254         // Scan through the RTP payload types specified in a "m=" line:
1255     ast_rtp_pt_clear(sub->rtp);
1256         codecs = m + len;
1257         while(strlen(codecs)) {
1258                 if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
1259                         ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
1260                         return -1;
1261                 }
1262                 ast_rtp_set_m_type(sub->rtp, codec);
1263                 codecs += len;
1264         }
1265
1266         // Next, scan through each "a=rtpmap:" line, noting each
1267         // specified RTP payload type (with corresponding MIME subtype):
1268         sdpLineNum_iterator_init(&iterator);
1269         while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
1270           char* mimeSubtype = strdup(a); // ensures we have enough space
1271           if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
1272           // Note: should really look at the 'freq' and '#chans' params too
1273           ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype);
1274           free(mimeSubtype);
1275         }
1276
1277         // Now gather all of the codecs that were asked for:
1278         ast_rtp_get_current_formats(sub->rtp,
1279                                 &peercapability, &peerNonCodecCapability);
1280         p->capability = capability & peercapability;
1281         if (mgcpdebug) {
1282                 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
1283                     capability, peercapability, p->capability);
1284                 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
1285                     nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
1286         }
1287         if (!p->capability) {
1288                 ast_log(LOG_WARNING, "No compatible codecs!\n");
1289                 return -1;
1290         }
1291         return 0;
1292         
1293 }
1294
1295 static int add_header(struct mgcp_request *req, char *var, char *value)
1296 {
1297         if (req->len >= sizeof(req->data) - 4) {
1298                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1299                 return -1;
1300         }
1301         if (req->lines) {
1302                 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
1303                 return -1;
1304         }
1305         req->header[req->headers] = req->data + req->len;
1306         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
1307         req->len += strlen(req->header[req->headers]);
1308         if (req->headers < MGCP_MAX_HEADERS)
1309                 req->headers++;
1310         else {
1311                 ast_log(LOG_WARNING, "Out of header space\n");
1312                 return -1;
1313         }
1314         return 0;       
1315 }
1316
1317 static int add_line(struct mgcp_request *req, char *line)
1318 {
1319         if (req->len >= sizeof(req->data) - 4) {
1320                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
1321                 return -1;
1322         }
1323         if (!req->lines) {
1324                 /* Add extra empty return */
1325                 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
1326                 req->len += strlen(req->data + req->len);
1327         }
1328         req->line[req->lines] = req->data + req->len;
1329         snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
1330         req->len += strlen(req->line[req->lines]);
1331         if (req->lines < MGCP_MAX_LINES)
1332                 req->lines++;
1333         else {
1334                 ast_log(LOG_WARNING, "Out of line space\n");
1335                 return -1;
1336         }
1337         return 0;       
1338 }
1339
1340 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1341 {
1342         /* Initialize a response */
1343         if (req->headers || req->len) {
1344                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1345                 return -1;
1346         }
1347         req->header[req->headers] = req->data + req->len;
1348         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1349         req->len += strlen(req->header[req->headers]);
1350         if (req->headers < MGCP_MAX_HEADERS)
1351                 req->headers++;
1352         else
1353                 ast_log(LOG_WARNING, "Out of header space\n");
1354         return 0;
1355 }
1356
1357 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1358 {
1359         /* Initialize a response */
1360         if (req->headers || req->len) {
1361                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1362                 return -1;
1363         }
1364         req->header[req->headers] = req->data + req->len;
1365         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);
1366         req->len += strlen(req->header[req->headers]);
1367         if (req->headers < MGCP_MAX_HEADERS)
1368                 req->headers++;
1369         else
1370                 ast_log(LOG_WARNING, "Out of header space\n");
1371         return 0;
1372 }
1373
1374
1375 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1376 {
1377         memset(resp, 0, sizeof(*resp));
1378         init_resp(resp, msg, req, msgrest);
1379         return 0;
1380 }
1381
1382 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1383 {
1384         memset(req, 0, sizeof(struct mgcp_request));
1385         oseq++;
1386         init_req(p, req, verb);
1387         return 0;
1388 }
1389
1390 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest)
1391 {
1392         struct mgcp_request resp;
1393     struct mgcp_endpoint *p = sub->parent;
1394         respprep(&resp, p, msg, req, msgrest);
1395         return send_response(sub, &resp);
1396 }
1397
1398
1399 static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1400 {
1401         int len;
1402         int codec;
1403         char costr[80];
1404         struct sockaddr_in sin;
1405         char v[256];
1406         char s[256];
1407         char o[256];
1408         char c[256];
1409         char t[256];
1410         char m[256];
1411         char a[1024] = "";
1412         int x;
1413         struct sockaddr_in dest;
1414     struct mgcp_endpoint *p = sub->parent;
1415         /* XXX We break with the "recommendation" and send our IP, in order that our
1416                peer doesn't have to gethostbyname() us XXX */
1417         len = 0;
1418         if (!sub->rtp) {
1419                 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1420                 return -1;
1421         }
1422         ast_rtp_get_us(sub->rtp, &sin);
1423         if (rtp) {
1424                 ast_rtp_get_peer(rtp, &dest);
1425         } else {
1426                 if (sub->tmpdest.sin_addr.s_addr) {
1427                         dest.sin_addr = sub->tmpdest.sin_addr;
1428                         dest.sin_port = sub->tmpdest.sin_port;
1429                         /* Reset temporary destination */
1430                         memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
1431                 } else {
1432                         dest.sin_addr = p->parent->ourip;
1433                         dest.sin_port = sin.sin_port;
1434                 }
1435         }
1436         if (mgcpdebug) {
1437                 ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 
1438     }
1439         snprintf(v, sizeof(v), "v=0\r\n");
1440         snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
1441         snprintf(s, sizeof(s), "s=session\r\n");
1442         snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", inet_ntoa(dest.sin_addr));
1443         snprintf(t, sizeof(t), "t=0 0\r\n");
1444         snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
1445         for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1446                 if (p->capability & x) {
1447                         if (mgcpdebug) {
1448                                 ast_verbose("Answering with capability %d\n", x);
1449             }
1450                         codec = ast_rtp_lookup_code(sub->rtp, 1, x);
1451             if (codec > -1) {
1452                                 snprintf(costr, sizeof(costr), " %d", codec);
1453                                 strcat(m, costr);
1454                                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
1455                                 strcat(a, costr);
1456                         }
1457                 }
1458         }
1459         for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1460         if (p->nonCodecCapability & x) {
1461             if (mgcpdebug) {
1462                 ast_verbose("Answering with non-codec capability %d\n", x);
1463             }
1464             codec = ast_rtp_lookup_code(sub->rtp, 0, x);
1465             if (codec > -1) {
1466                 snprintf(costr, sizeof(costr), " %d", codec);
1467                 strcat(m, costr);
1468                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
1469                 strcat(a, costr);
1470                 if (x == AST_RTP_DTMF) {
1471                   /* Indicate we support DTMF...  Not sure about 16, but MSN supports it so dang it, we will too... */
1472                   snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n", codec);
1473                   strcat(a, costr);
1474                 }
1475             }
1476         }
1477     }
1478         strcat(m, "\r\n");
1479         len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
1480         snprintf(costr, sizeof(costr), "%d", len);
1481         add_line(resp, v);
1482         add_line(resp, o);
1483         add_line(resp, s);
1484         add_line(resp, c);
1485         add_line(resp, t);
1486         add_line(resp, m);
1487         add_line(resp, a);
1488         return 0;
1489 }
1490
1491 static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1492 {
1493         struct mgcp_request resp;
1494         char local[256];
1495         char tmp[80];
1496         int x;
1497     struct mgcp_endpoint *p = sub->parent;
1498         if (!strlen(sub->cxident) && rtp) {
1499                 /* We don't have a CXident yet, store the destination and
1500                    wait a bit */
1501                 ast_rtp_get_peer(rtp, &sub->tmpdest);
1502                 return 0;
1503         }
1504         snprintf(local, sizeof(local), "p:20");
1505         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1506                 if (p->capability & x) {
1507                         snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1508                         strcat(local, tmp);
1509                 }
1510         }
1511         reqprep(&resp, p, "MDCX");
1512         add_header(&resp, "C", sub->callid);
1513         add_header(&resp, "L", local);
1514         add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1515         add_header(&resp, "X", sub->txident);
1516         add_header(&resp, "I", sub->cxident);
1517         /*add_header(&resp, "S", "");*/
1518         add_sdp(&resp, sub, rtp);
1519         return send_request(sub, &resp, oseq);
1520 }
1521
1522 static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
1523 {
1524         struct mgcp_request resp;
1525         char local[256];
1526         char tmp[80];
1527         int x;
1528     struct mgcp_endpoint *p = sub->parent;
1529
1530         snprintf(local, sizeof(local), "p:20");
1531         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1532                 if (p->capability & x) {
1533                         snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1534                         strcat(local, tmp);
1535                 }
1536         }
1537     if (mgcpdebug) {
1538         ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 
1539                     p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
1540     }
1541         reqprep(&resp, p, "CRCX");
1542         add_header(&resp, "C", sub->callid);
1543         add_header(&resp, "L", local);
1544         add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1545         add_header(&resp, "X", sub->txident);
1546         /*add_header(&resp, "S", "");*/
1547         add_sdp(&resp, sub, rtp);
1548         return send_request(sub, &resp, oseq);
1549 }
1550
1551 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
1552 {
1553         struct mgcp_request resp;
1554     struct mgcp_endpoint *p = sub->parent;
1555
1556     if (mgcpdebug) {
1557         ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
1558                     tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
1559     }
1560         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1561         reqprep(&resp, p, "RQNT");
1562         add_header(&resp, "X", sub->txident);
1563     switch (p->hookstate) {
1564             case MGCP_ONHOOK:
1565             add_header(&resp, "R", "hd(N)");
1566             break;
1567         case MGCP_OFFHOOK:
1568             add_header(&resp, "R", "hu(N), hf(N), D/[0-9#*](N)");
1569             break;
1570     }
1571     if (strlen(tone)) {
1572         add_header(&resp, "S", tone);
1573     }
1574         return send_request(sub, &resp, oseq);
1575 }
1576
1577 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callerid)
1578 {
1579         struct mgcp_request resp;
1580         char cid[256];
1581         char tone2[256];
1582         char *l, *n;
1583         time_t t;
1584         struct tm tm;
1585     struct mgcp_endpoint *p = sub->parent;
1586         
1587         time(&t);
1588         localtime_r(&t,&tm);
1589         if (callerid)
1590                 strncpy(cid, callerid, sizeof(cid) - 1);
1591         else
1592                 strcpy(cid, "");
1593         ast_callerid_parse(cid, &n, &l);
1594         if (l) {
1595                 ast_shrink_phone_number(l);
1596                 if (!ast_isphonenumber(l)) {
1597                         n = l;
1598                         l = "";
1599                 }
1600         } 
1601         if (!n)
1602                 n = "O";
1603         if (!l)
1604                 l = "";
1605
1606     /* Keep track of last callerid for blacklist and callreturn */
1607     strncpy(p->lastcallerid, l, sizeof(p->lastcallerid) - 1);
1608
1609         snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
1610                         tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
1611         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1612         reqprep(&resp, p, "RQNT");
1613         add_header(&resp, "X", sub->txident);
1614     switch (p->hookstate) {
1615             case MGCP_ONHOOK:
1616             add_header(&resp, "R", "L/hd(N)");
1617             break;
1618         case MGCP_OFFHOOK:
1619             add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
1620             break;
1621     }
1622     if (strlen(tone2)) {
1623         add_header(&resp, "S", tone2);
1624     }
1625     if (mgcpdebug) {
1626         ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
1627                     tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
1628     }
1629         return send_request(sub, &resp, oseq);
1630 }
1631
1632 static int transmit_modify_request(struct mgcp_subchannel *sub)
1633 {
1634         struct mgcp_request resp;
1635     struct mgcp_endpoint *p = sub->parent;
1636         if (!strlen(sub->cxident)) {
1637                 /* We don't have a CXident yet, store the destination and
1638                    wait a bit */
1639                 return 0;
1640         }
1641     if (mgcpdebug) {
1642         ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n", 
1643                     p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
1644     }
1645         reqprep(&resp, p, "MDCX");
1646         add_header(&resp, "C", sub->callid);
1647         add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
1648         add_header(&resp, "X", sub->txident);
1649         add_header(&resp, "I", sub->cxident);
1650     switch (sub->parent->hookstate) {
1651             case MGCP_ONHOOK:
1652             add_header(&resp, "R", "L/hd(N)");
1653             break;
1654         case MGCP_OFFHOOK:
1655             add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
1656             break;
1657     }
1658         return send_request(sub, &resp, oseq);
1659 }
1660
1661
1662 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
1663 {
1664         struct mgcp_request resp;
1665         reqprep(&resp, p, "AUEP");
1666         add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,VS,E,MD,M");
1667         return send_request(p->sub, &resp, oseq);
1668 }
1669
1670 static int transmit_connection_del(struct mgcp_subchannel *sub)
1671 {
1672     struct mgcp_endpoint *p = sub->parent;
1673         struct mgcp_request resp;
1674     if (mgcpdebug) {
1675         ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 
1676                     sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
1677     }
1678         reqprep(&resp, p, "DLCX");
1679         add_header(&resp, "C", sub->callid);
1680         add_header(&resp, "X", sub->txident);
1681         add_header(&resp, "I", sub->cxident);
1682         return send_request(sub, &resp, oseq);
1683 }
1684
1685 static void handle_response(struct mgcp_subchannel *sub, int result, int ident)
1686 {
1687         struct mgcp_message *cur;
1688     struct mgcp_endpoint *p = sub->parent;
1689     time_t t;
1690     time(&t);
1691 #if 0
1692     ast_verbose(VERBOSE_PREFIX_3 "Got response back on sub%d for transaction %d our last send was %d)\n", 
1693             sub->id, ident, sub->msgs ? sub->msgs->seqno : -1);
1694     ast_verbose(VERBOSE_PREFIX_3 "Here's out outher chan sub%d for transaction %d our last send was %d)\n", 
1695             sub->next->id, ident, sub->next->msgs ? sub->next->msgs->seqno : -1);
1696 #endif
1697         if (sub->msgs && (sub->msgs->seqno == ident)) {
1698                 ast_log(LOG_DEBUG, "Got response back on tansaction %d\n", ident);
1699                 cur = sub->msgs;
1700                 sub->msgs = sub->msgs->next;
1701         ast_log(LOG_DEBUG, "Removing message from %s@%s-%d tansaction %d\n", sub->parent->name, sub->parent->parent->name, sub->id, ident);
1702                 free(cur);
1703                 if (sub->msgs) {
1704                         /* Send next pending message if appropriate */
1705                         sub->messagepending = 1;
1706                         sub->lastout = sub->msgs->seqno;
1707             sub->lastouttime = t;
1708                         __mgcp_xmit(sub, sub->msgs->buf, sub->msgs->len);
1709                         /* XXX Should schedule retransmission XXX */
1710                 } else {
1711                         sub->messagepending = 0;
1712         }
1713         } else {
1714         ast_log(LOG_NOTICE, "Got response back on %s@%s-%d for transaction %d we aren't sending? (current = %d)\n", 
1715                 sub->parent->name, sub->parent->parent->name, sub->id, ident, sub->msgs ? sub->msgs->seqno : -1);
1716         }
1717         if ((result >= 400) && (result <= 499)) {
1718         switch (result) {
1719             case 401:
1720                 p->hookstate = MGCP_OFFHOOK;
1721                 break;
1722             case 402:
1723                 p->hookstate = MGCP_ONHOOK;
1724                 break;
1725         }
1726         ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", result, p->name, p->parent->name, sub->id);
1727         if (sub->owner)
1728             ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
1729         }
1730 }
1731
1732 static void start_rtp(struct mgcp_subchannel *sub)
1733 {
1734                 ast_mutex_lock(&sub->lock);
1735                 /* Allocate the RTP now */
1736                 sub->rtp = ast_rtp_new(sched, io, 1, 0);
1737                 if (sub->rtp && sub->owner)
1738                         sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
1739                 if (sub->rtp)
1740                         ast_rtp_setnat(sub->rtp, sub->nat);
1741 #if 0
1742                 ast_rtp_set_callback(p->rtp, rtpready);
1743                 ast_rtp_set_data(p->rtp, p);
1744 #endif          
1745                 /* Make a call*ID */
1746         snprintf(sub->callid, sizeof(sub->callid), "%08x%s", rand(), sub->txident);
1747                 /* Transmit the connection create */
1748                 transmit_connect_with_sdp(sub, NULL);
1749                 ast_mutex_unlock(&sub->lock);
1750 }
1751
1752 static void *mgcp_ss(void *data)
1753 {
1754         struct ast_channel *chan = data;
1755         struct mgcp_subchannel *sub = chan->pvt->pvt;
1756         struct mgcp_endpoint *p = sub->parent;
1757         char exten[AST_MAX_EXTENSION] = "";
1758         int len = 0;
1759         int timeout = firstdigittimeout;
1760         int res;
1761         int getforward=0;
1762     while(len < AST_MAX_EXTENSION-1) {
1763         res = ast_waitfordigit(chan, timeout);
1764         timeout = 0;
1765         if (res < 0) {
1766             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
1767             /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
1768                         ast_indicate(chan, -1);
1769             ast_hangup(chan);
1770             return NULL;
1771         } else if (res)  {
1772             exten[len++]=res;
1773             exten[len] = '\0';
1774         }
1775         if (!ast_ignore_pattern(chan->context, exten)) {
1776             /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
1777                         ast_indicate(chan, -1);
1778         } else {
1779             /* XXX Redundant?  We should already be playing dialtone */
1780             /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
1781             transmit_notify_request(sub, "dl");
1782         }
1783         if (ast_exists_extension(chan, chan->context, exten, 1, p->callerid)) {
1784             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->callerid)) {
1785                 if (getforward) {
1786                     /* Record this as the forwarding extension */
1787                     strncpy(p->call_forward, exten, sizeof(p->call_forward)); 
1788                     if (option_verbose > 2) {
1789                         ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n", 
1790                                 p->call_forward, chan->name);
1791                     }
1792                     /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1793                     transmit_notify_request(sub, "sl");
1794                     if (res)
1795                         break;
1796                     usleep(500000);
1797                     /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
1798                     ast_indicate(chan, -1);
1799                     sleep(1);
1800                     memset(exten, 0, sizeof(exten));
1801                     /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
1802                     transmit_notify_request(sub, "dl");
1803                     len = 0;
1804                     getforward = 0;
1805                 } else  {
1806                     /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
1807                     ast_indicate(chan, -1);
1808                     strncpy(chan->exten, exten, sizeof(chan->exten)-1);
1809                     if (strlen(p->callerid)) {
1810                         if (!p->hidecallerid)
1811                             chan->callerid = strdup(p->callerid);
1812                         chan->ani = strdup(p->callerid);
1813                     }
1814                     ast_setstate(chan, AST_STATE_RING);
1815                     /*zt_enable_ec(p);*/
1816                     res = ast_pbx_run(chan);
1817                     if (res) {
1818                         ast_log(LOG_WARNING, "PBX exited non-zero\n");
1819                         /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
1820                         /*transmit_notify_request(p, "nbz", 1);*/
1821                         transmit_notify_request(sub, "cg");
1822                     }
1823                     return NULL;
1824                 }
1825             } else {
1826                 /* It's a match, but they just typed a digit, and there is an ambiguous match,
1827                    so just set the timeout to matchdigittimeout and wait some more */
1828                 timeout = matchdigittimeout;
1829             }
1830         } else if (res == 0) {
1831             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
1832             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
1833             transmit_notify_request(sub, "cg");
1834             /*zt_wait_event(p->subs[index].zfd);*/
1835             ast_hangup(chan);
1836             return NULL;
1837         } else if (p->callwaiting && !strcmp(exten, "*70")) {
1838             if (option_verbose > 2) {
1839                 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
1840             }
1841             /* Disable call waiting if enabled */
1842             p->callwaiting = 0;
1843             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1844             transmit_notify_request(sub, "sl");
1845             len = 0;
1846             memset(exten, 0, sizeof(exten));
1847             timeout = firstdigittimeout;
1848                 
1849         } else if (!strcmp(exten,ast_pickup_ext())) {
1850             /* Scan all channels and see if any there
1851              * ringing channqels with that have call groups
1852              * that equal this channels pickup group  
1853              */
1854             if (ast_pickup_call(chan)) {
1855                 ast_log(LOG_WARNING, "No call pickup possible...\n");
1856                 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
1857                 transmit_notify_request(sub, "cg");
1858             }
1859             ast_hangup(chan);
1860             return NULL;
1861             
1862         } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
1863             if (option_verbose > 2) {
1864                 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
1865             }
1866             /* Disable Caller*ID if enabled */
1867             p->hidecallerid = 1;
1868             if (chan->callerid)
1869                 free(chan->callerid);
1870             chan->callerid = NULL;
1871             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1872             transmit_notify_request(sub, "sl");
1873             len = 0;
1874             memset(exten, 0, sizeof(exten));
1875             timeout = firstdigittimeout;
1876         } else if (p->callreturn && !strcmp(exten, "*69")) {
1877             res = 0;
1878             if (strlen(p->lastcallerid)) {
1879                 res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
1880             }
1881             if (!res)
1882                 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1883                 transmit_notify_request(sub, "sl");
1884             break;
1885         } else if (!strcmp(exten, "*78")) {
1886             /* Do not disturb */
1887             if (option_verbose > 2) {
1888                 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
1889             }
1890             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1891             transmit_notify_request(sub, "sl");
1892             p->dnd = 1;
1893             getforward = 0;
1894             memset(exten, 0, sizeof(exten));
1895             len = 0;
1896         } else if (!strcmp(exten, "*79")) {
1897             /* Do not disturb */
1898             if (option_verbose > 2) {
1899                 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
1900             }
1901             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1902             transmit_notify_request(sub, "sl");
1903             p->dnd = 0;
1904             getforward = 0;
1905             memset(exten, 0, sizeof(exten));
1906             len = 0;
1907         } else if (p->cancallforward && !strcmp(exten, "*72")) {
1908             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1909             transmit_notify_request(sub, "sl");
1910             getforward = 1;
1911             memset(exten, 0, sizeof(exten));
1912             len = 0;
1913         } else if (p->cancallforward && !strcmp(exten, "*73")) {
1914             if (option_verbose > 2) {
1915                 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
1916             }
1917             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1918             transmit_notify_request(sub, "sl");
1919             memset(p->call_forward, 0, sizeof(p->call_forward));
1920             getforward = 0;
1921             memset(exten, 0, sizeof(exten));
1922             len = 0;
1923         } else if (!strcmp(exten, ast_parking_ext()) && 
1924                     sub->next->owner &&
1925                     sub->next->owner->bridge) {
1926             /* This is a three way call, the main call being a real channel, 
1927                 and we're parking the first call. */
1928             ast_masq_park_call(sub->next->owner->bridge, chan, 0, NULL);
1929             if (option_verbose > 2) {
1930                 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
1931             }
1932             break;
1933         } else if (strlen(p->lastcallerid) && !strcmp(exten, "*80")) {
1934             if (option_verbose > 2) {
1935                 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
1936             }
1937             res = ast_db_put("blacklist", p->lastcallerid, "1");
1938             if (!res) {
1939                 /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1940                 transmit_notify_request(sub, "sl");
1941                 memset(exten, 0, sizeof(exten));
1942                 len = 0;
1943             }
1944         } else if (p->hidecallerid && !strcmp(exten, "*82")) {
1945             if (option_verbose > 2) {
1946                 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
1947             }
1948             /* Enable Caller*ID if enabled */
1949             p->hidecallerid = 0;
1950             if (chan->callerid)
1951                 free(chan->callerid);
1952             if (strlen(p->callerid))
1953                 chan->callerid = strdup(p->callerid);
1954             /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
1955             transmit_notify_request(sub, "sl");
1956             len = 0;
1957             memset(exten, 0, sizeof(exten));
1958             timeout = firstdigittimeout;
1959         } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->callerid) &&
1960                         ((exten[0] != '*') || (strlen(exten) > 2))) {
1961             if (option_debug)
1962                 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->callerid ? chan->callerid : "<Unknown Caller>", chan->context);
1963             break;
1964         }
1965         if (!timeout)
1966             timeout = gendigittimeout;
1967         if (len && !ast_ignore_pattern(chan->context, exten))
1968             /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
1969                         ast_indicate(chan, -1);
1970     }
1971 #if 0
1972         for (;;) {
1973                 res = ast_waitfordigit(chan, to);
1974                 if (!res) {
1975                         ast_log(LOG_DEBUG, "Timeout...\n");
1976                         break;
1977                 }
1978                 if (res < 0) {
1979                         ast_log(LOG_DEBUG, "Got hangup...\n");
1980             ast_hangup(chan);
1981                         break;
1982                 }
1983                 exten[pos++] = res;
1984                 if (!ast_ignore_pattern(chan->context, exten))
1985                         ast_indicate(chan, -1);
1986                 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
1987                         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
1988                                 to = 3000;
1989                         else
1990                                 to = 8000;
1991                 } else
1992                         break;
1993         }
1994         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
1995                 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
1996         if (!p->rtp) {
1997             start_rtp(p);
1998         }
1999                 ast_setstate(chan, AST_STATE_RING);
2000                 chan->rings = 1;
2001                 if (ast_pbx_run(chan)) {
2002                         ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
2003                 } else
2004                         return NULL;
2005         }
2006 #endif
2007         ast_hangup(chan);
2008         return NULL;
2009 }
2010
2011 static int attempt_transfer(struct mgcp_endpoint *p)
2012 {
2013     /* *************************
2014      * I hope this works.
2015      * Copied out of chan_zap
2016      * Cross your fingers
2017      * *************************/
2018
2019         /* In order to transfer, we need at least one of the channels to
2020            actually be in a call bridge.  We can't conference two applications
2021            together (but then, why would we want to?) */
2022         if (p->sub->owner->bridge) {
2023                 /* The three-way person we're about to transfer to could still be in MOH, so
2024                    stop if now if appropriate */
2025                 if (p->sub->next->owner->bridge)
2026                         ast_moh_stop(p->sub->next->owner->bridge);
2027                 if (p->sub->owner->_state == AST_STATE_RINGING) {
2028                         ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING);
2029                 }
2030                 if (ast_channel_masquerade(p->sub->next->owner, p->sub->owner->bridge)) {
2031                         ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2032                                         p->sub->owner->bridge->name, p->sub->next->owner->name);
2033                         return -1;
2034                 }
2035                 /* Orphan the channel */
2036                 unalloc_sub(p->sub->next);
2037         } else if (p->sub->next->owner->bridge) {
2038                 if (p->sub->owner->_state == AST_STATE_RINGING) {
2039                         ast_indicate(p->sub->next->owner->bridge, AST_CONTROL_RINGING);
2040                 }
2041                 ast_moh_stop(p->sub->next->owner->bridge);
2042                 if (ast_channel_masquerade(p->sub->owner, p->sub->next->owner->bridge)) {
2043                         ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
2044                                         p->sub->next->owner->bridge->name, p->sub->owner->name);
2045                         return -1;
2046                 }
2047                 /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
2048         if (option_verbose > 2) {
2049             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);
2050         }
2051         p->sub = p->sub->next;
2052                 unalloc_sub(p->sub->next);
2053                 /* Tell the caller not to hangup */
2054                 return 1;
2055         } else {
2056                 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
2057                                         p->sub->owner->name, p->sub->next->owner->name);
2058                 p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
2059         if (p->sub->next->owner) {
2060             p->sub->next->alreadygone = 1;
2061             ast_queue_hangup(p->sub->next->owner, 1);
2062         }
2063         }
2064         return 0;
2065 }
2066
2067 static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) 
2068 {
2069     struct mgcp_endpoint *p = sub->parent;
2070     struct ast_channel *c;
2071         pthread_t t;
2072
2073     /* Off hook / answer */
2074     if (sub->outgoing) {
2075         /* Answered */
2076         if (sub->owner) {
2077             if (sub->owner->bridge) {
2078                 ast_moh_stop(sub->owner->bridge);
2079             }
2080             sub->cxmode = MGCP_CX_SENDRECV;
2081             if (!sub->rtp) {
2082                 start_rtp(sub);
2083             } else {
2084                 transmit_modify_request(sub);
2085             }
2086             /*transmit_notify_request(sub, "aw");*/
2087             transmit_notify_request(sub, "");
2088             ast_queue_control(sub->owner, AST_CONTROL_ANSWER, 1);
2089         }
2090     } else {
2091         /* Start switch */
2092         /*sub->cxmode = MGCP_CX_SENDRECV;*/
2093         if (!sub->owner) {
2094             if (!sub->rtp) {
2095                 start_rtp(sub);
2096             } else {
2097                 transmit_modify_request(sub);
2098             }
2099             if (p->immediate) {
2100                 /* The channel is immediately up.  Start right away */
2101                 transmit_notify_request(sub, "rt");
2102                 c = mgcp_new(sub, AST_STATE_RING);
2103                 if (!c) {
2104                     ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
2105                     transmit_notify_request(sub, "cg");
2106                     ast_hangup(c);
2107                 }
2108             } else {
2109                 if (has_voicemail(p)) {
2110                     transmit_notify_request(sub, "sl");
2111                 } else {
2112                     transmit_notify_request(sub, "dl");
2113                 }
2114                 c = mgcp_new(sub, AST_STATE_DOWN);
2115                 if (c) {
2116                     if (pthread_create(&t, NULL, mgcp_ss, c)) {
2117                         ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
2118                         ast_hangup(c);
2119                     }
2120                 } else {
2121                     ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
2122                 }
2123             }
2124         } else {
2125             if (p->hookstate == MGCP_OFFHOOK) {
2126                 ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
2127             } else {
2128                 ast_log(LOG_WARNING, "On hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
2129                 ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?");
2130             }
2131             if (sub->owner->bridge) {
2132                 ast_moh_stop(sub->owner->bridge);
2133             }
2134             sub->cxmode = MGCP_CX_SENDRECV;
2135             if (!sub->rtp) {
2136                 start_rtp(sub);
2137             } else {
2138                 transmit_modify_request(sub);
2139             }
2140             /*transmit_notify_request(sub, "aw");*/
2141             transmit_notify_request(sub, "");
2142             /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER, 1);*/
2143         }
2144     }
2145 }
2146
2147 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
2148 {
2149         char *ev, *s;
2150         struct ast_frame f = { 0, };
2151     struct mgcp_endpoint *p = sub->parent;
2152     int res;
2153         if (mgcpdebug) {
2154                 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
2155     }
2156         /* Clear out potential response */
2157         if (!strcasecmp(req->verb, "RSIP")) {
2158                 /* Test if this RSIP request is just a keepalive */
2159                 if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
2160                         if (option_verbose > 2)
2161                                 ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
2162                         transmit_response(sub, "200", req, "OK");
2163                 } else {
2164                         dump_queue(p);
2165                         if (option_verbose > 2) {
2166                                 ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
2167                         }
2168                         if (sub->owner) {
2169                                 ast_softhangup(sub->owner, AST_SOFTHANGUP_DEV);
2170                         }
2171                         transmit_response(sub, "200", req, "OK");
2172                         transmit_notify_request(sub, "");
2173                 }
2174         } else if (!strcasecmp(req->verb, "NTFY")) {
2175                 /* Acknowledge and be sure we keep looking for the same things */
2176                 transmit_response(sub, "200", req, "OK");
2177                 /* Notified of an event */
2178                 ev = get_header(req, "O");
2179                 s = strchr(ev, '/');
2180                 if (s) ev = s + 1;
2181         if (option_verbose > 2) {
2182             ast_verbose(VERBOSE_PREFIX_3 "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
2183         }
2184                 /* Keep looking for events unless this was a hangup */
2185                 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd")) {
2186                         transmit_notify_request(sub, p->curtone);
2187         }
2188                 if (!strcasecmp(ev, "hd")) {
2189             p->hookstate = MGCP_OFFHOOK;
2190             sub->cxmode = MGCP_CX_SENDRECV;
2191             handle_hd_hf(sub, ev);
2192                 } else if (!strcasecmp(ev, "hf")) {
2193             /* We can assume we are offhook if we received a hookflash */
2194             /* First let's just do call wait and ignore threeway */
2195             /* We're currently in charge */
2196             if (p->hookstate != MGCP_OFFHOOK) {
2197                 /* Cisco c7940 sends hf even if the phone is onhook */
2198                 /* Thanks to point on IRC for pointing this out */
2199                 return -1;
2200             }
2201             /* do not let * confrnce two down channels */  
2202             if( sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner) return -1;
2203
2204             if (p->callwaiting || p->transfer || p->threewaycalling) {
2205                 if (option_verbose > 2) {
2206                     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);
2207                 }
2208                 p->sub = p->sub->next;
2209
2210                 /* transfer control to our next subchannel */
2211                 if (!sub->next->owner) {
2212                     /* plave the first call on hold and start up a new call */
2213                     sub->cxmode = MGCP_CX_MUTE;
2214                     if (option_verbose > 2) {
2215                         ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
2216                     }
2217                     transmit_modify_request(sub);
2218                     if (sub->owner && sub->owner->bridge) {
2219                         ast_moh_start(sub->owner->bridge, NULL);
2220                     }
2221                     sub->next->cxmode = MGCP_CX_RECVONLY;
2222                     handle_hd_hf(sub->next, ev);
2223                 } else if (sub->owner && sub->next->owner) {
2224                     /* We've got two active calls lets decide whether or not to conference or just flip flop */
2225                     if ((!sub->outgoing) && (!sub->next->outgoing)) {
2226                         /* We made both calls lets conferenct */
2227                         if (option_verbose > 2) {
2228                             ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n", 
2229                                         sub->id, sub->next->id, p->name, p->parent->name);
2230                         }
2231                         sub->cxmode = MGCP_CX_CONF;
2232                         sub->next->cxmode = MGCP_CX_CONF;
2233                         if (sub->next->owner->bridge) {
2234                             ast_moh_stop(sub->next->owner->bridge);
2235                         }
2236                         transmit_modify_request(sub);
2237                         transmit_modify_request(sub->next);
2238                     } else {
2239                         /* Let's flipflop between calls */
2240                         /* XXX Need to check for state up ??? */
2241                         /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
2242                         if (option_verbose > 2) {
2243                             ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 
2244                                         sub->id, sub->next->id, p->name, p->parent->name);
2245                         }
2246                         sub->cxmode = MGCP_CX_MUTE;
2247                         if (option_verbose > 2) {
2248                             ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
2249                         }
2250                         transmit_modify_request(sub);
2251                         if (sub->owner->bridge) {
2252                             ast_moh_start(sub->owner->bridge, NULL);
2253                         }
2254                         if (sub->next->owner->bridge) {
2255                             ast_moh_stop(sub->next->owner->bridge);
2256                         }
2257                         handle_hd_hf(sub->next, ev);
2258 #if 0
2259                         if (sub->next->owner && (sub->next->owner->_state != AST_STATE_UP)) {
2260                             handle_hd_hf(sub->next, ev);
2261                         } else {
2262                             ast_verbose(VERBOSE_PREFIX_3 "MGCP Unmuting %d on %s@%s\n", sub->next->id, p->name, p->parent->name);
2263                             sub->next->cxmode = MGCP_CX_SENDRECV;
2264                             transmit_modify_request(sub->next);
2265                         }
2266 #endif
2267                     }
2268                 } else {
2269                     /* We've most likely lost one of our calls find an active call and bring it up */
2270                     if (sub->owner) {
2271                         p->sub = sub;
2272                     } else if (sub->next->owner) {
2273                         p->sub = sub->next;
2274                     } else {
2275                         /* We seem to have lost both our calls */
2276                         /* XXX - What do we do now? */
2277                         return -1;
2278                     }
2279                     if (p->sub->owner->bridge) {
2280                         ast_moh_stop(p->sub->owner->bridge);
2281                     }
2282                     p->sub->cxmode = MGCP_CX_SENDRECV;
2283                     transmit_modify_request(p->sub);
2284                 }
2285             } else {
2286                 ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 
2287                         p->name, p->parent->name);
2288             }
2289             /* ast_moh_stop(sub->owner->bridge); */
2290                 } else if (!strcasecmp(ev, "hu")) {
2291             p->hookstate = MGCP_ONHOOK;
2292             sub->cxmode = MGCP_CX_RECVONLY;
2293             ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
2294             if (sub->rtp) {
2295                 transmit_modify_request(sub);
2296             }
2297             if (p->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
2298                 /* We're allowed to transfer, we have two avtive calls and */
2299                 /* we made at least one of the calls.  Let's try and transfer */
2300                 if ((res = attempt_transfer(p)) < 0) {
2301                     if (p->sub->next->owner) {
2302                         sub->next->alreadygone = 1;
2303                         ast_queue_hangup(sub->next->owner,1);
2304                     }
2305                 } else if (res) {
2306                     ast_log(LOG_WARNING, "Transfer attempt failed\n");
2307                     return -1;
2308                 }
2309             } else {
2310                 /* Hangup the current call */
2311                 /* If there is another active call, mgcp_hangup will ring the phone with the other call */
2312                 if (sub->owner) {
2313                     sub->alreadygone = 1;
2314                     ast_queue_hangup(sub->owner, 1);
2315                 } else {
2316                     ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed\n", 
2317                                 p->name, p->parent->name, sub->id);
2318                 }
2319             }
2320             if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
2321                 if (has_voicemail(p)) {
2322                     if (option_verbose > 2) {
2323                         ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
2324                     }
2325                     transmit_notify_request(sub, "vmwi(+)");
2326                 } else {
2327                     if (option_verbose > 2) {
2328                         ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
2329                     }
2330                     transmit_notify_request(sub, "vmwi(-)");
2331                 }
2332             }
2333                 } else if ((strlen(ev) == 1) && 
2334                                         (((ev[0] >= '0') && (ev[0] <= '9')) ||
2335                                          ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
2336                                          (ev[0] == '*') || (ev[0] == '#'))) {
2337                         f.frametype = AST_FRAME_DTMF;
2338                         f.subclass = ev[0];
2339                         f.src = "mgcp";
2340                         if (sub->owner) {
2341                 /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
2342                                 ast_queue_frame(sub->owner, &f, 1);
2343                 if (sub->next->owner) {
2344                     ast_queue_frame(sub->next->owner, &f, 1);
2345                 }
2346             }
2347             if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
2348                 memset(p->curtone, 0, sizeof(p->curtone));
2349             }
2350                 } else if (!strcasecmp(ev, "T")) {
2351                         /* Digit timeout -- unimportant */
2352                 } else {
2353                         ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
2354                 }
2355         } else {
2356                 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, inet_ntoa(sin->sin_addr));
2357                 transmit_response(sub, "510", req, "Unknown verb");
2358         }
2359         return 0;
2360 }
2361
2362 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
2363 {
2364         struct mgcp_request req;
2365         struct sockaddr_in sin;
2366         struct mgcp_subchannel *sub;
2367         char *c;
2368         int res;
2369         int len;
2370         int result;
2371         int ident;
2372         len = sizeof(sin);
2373         memset(&req, 0, sizeof(req));
2374         res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
2375         if (res < 0) {
2376                 if (errno != ECONNREFUSED)
2377                         ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
2378                 return 1;
2379         }
2380         req.data[res] = '\0';
2381         req.len = res;
2382         if (mgcpdebug) {
2383                 ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
2384     }
2385         parse(&req);
2386         if (req.headers < 1) {
2387                 /* Must have at least one header */
2388                 return 1;
2389         }
2390         if (!req.identifier || !strlen(req.identifier)) {
2391                 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", inet_ntoa(sin.sin_addr));
2392                 return 1;
2393         }
2394
2395         if (sscanf(req.verb, "%d", &result) &&
2396                 sscanf(req.identifier, "%d", &ident)) {
2397                 /* Try to find who this message is for, if it's important */
2398                 sub = find_subchannel(NULL, ident, &sin);
2399                 if (sub) {
2400 #if 0
2401                         if ((c = get_header(&req, "X"))) {
2402                 if (strlen(c)) {
2403                     if ((strcasecmp(sub->txident, c)) && (!strcasecmp(sub->next->txident, c))) {
2404                         ast_log(LOG_WARNING, "Response on sub%d message %d appears to have come from out other subchannel", sub->id, ident);
2405                     }
2406                 }
2407             }
2408 #endif
2409                         handle_response(sub, result, ident);
2410
2411                         if ((c = get_header(&req, "I"))) {
2412                                 if (strlen(c)) {
2413                     if (strlen(sub->cxident)) {
2414                         if (strcasecmp(c, sub->cxident)) {
2415                             ast_log(LOG_WARNING, "Subchannel already has a cxident. sub->cxident: %s requested %s\n", sub->cxident, c);
2416                         }
2417                     }
2418                                         strncpy(sub->cxident, c, sizeof(sub->cxident) - 1);
2419                                         if (sub->tmpdest.sin_addr.s_addr) {
2420                                                 transmit_modify_with_sdp(sub, NULL);
2421                                         }
2422                                 }
2423                         }
2424             /* Try to determine the hookstate returned from an audit endpoint command */
2425                         if ((c = get_header(&req, "ES"))) {
2426                                 if (strlen(c)) {
2427                     if (strstr(c, "hu")) {
2428                         sub->parent->hookstate = MGCP_ONHOOK;
2429                         ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", sub->parent->name, sub->parent->parent->name);
2430                     } else if (strstr(c, "hd")) {
2431                         sub->parent->hookstate = MGCP_OFFHOOK;
2432                         ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", sub->parent->name, sub->parent->parent->name);
2433                     }
2434                                 }
2435                         }
2436
2437                         if (req.lines) {
2438                                 if (!sub->rtp) 
2439                                         start_rtp(sub);
2440                                 if (sub->rtp)
2441                                         process_sdp(sub, &req);
2442                         }
2443
2444                 }
2445         } else {
2446                 if (!req.endpoint || !strlen(req.endpoint) || 
2447                     !req.version || !strlen(req.version) || 
2448                         !req.verb || !strlen(req.verb)) {
2449                         ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
2450                         return 1;
2451                 }
2452                 /* Process request, with iflock held */
2453                 sub = find_subchannel(req.endpoint, 0, &sin);
2454                 if (sub) {
2455             /* pass the request off to the currently mastering subchannel */
2456                         handle_request(sub, &req, &sin);
2457                 }
2458         }
2459         return 1;
2460 }
2461
2462 static void *do_monitor(void *data)
2463 {
2464         int res;
2465         struct mgcp_pkt *p;
2466     /* struct mgcp_gateway *g; */
2467     /* struct mgcp_endpoint *e; */
2468         /*time_t thispass = 0, lastpass = 0;*/
2469
2470         sched = sched_context_create();
2471         if (!sched) {
2472                 ast_log(LOG_WARNING, "Unable to create schedule context\n");
2473                 return NULL;
2474         }
2475         io = io_context_create();
2476         if (!io) {
2477                 ast_log(LOG_WARNING, "Unable to create I/O context\n");
2478                 return NULL;
2479         }
2480         
2481         /* Add an I/O event to our UDP socket */
2482         if (mgcpsock > -1) 
2483                 ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
2484         
2485         /* This thread monitors all the frame relay interfaces which are not yet in use
2486            (and thus do not have a separate thread) indefinitely */
2487         /* From here on out, we die whenever asked */
2488         for(;;) {
2489                 /* Check for interfaces needing to be killed */
2490                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
2491                    and wait for the monitor list, but the other way around is okay. */
2492                 ast_mutex_lock(&monlock);
2493                 /* Lock the network interface */
2494                 ast_mutex_lock(&netlock);
2495                 p = packets;
2496                 while(p) {
2497                         /* Handle any retransmissions */
2498                         p = p->next;
2499                 }
2500
2501         /* XXX THIS IS COMPLETELY HOSED */
2502         /* The gateway goes into a state of panic */
2503         /* If the vmwi indicator is sent while it is reseting interfaces */
2504 #if 0
2505         lastpass = thispass;
2506         thispass = time(NULL);
2507         g = gateways;
2508         while(g) {
2509             if (thispass != lastpass) {
2510                 e = g->endpoints;
2511                 while(e) {
2512                     if (e->type == TYPE_LINE) {
2513                         res = has_voicemail(e);
2514                         if ((e->msgstate != res) && (e->hookstate == MGCP_ONHOOK) && (!e->rtp)){
2515                             if (res) {
2516                                 transmit_notify_request(e, "vmwi(+)");
2517                             } else {
2518                                 transmit_notify_request(e, "vmwi(-)");
2519                             }
2520                             e->msgstate = res;
2521                             e->onhooktime = thispass;
2522                         }
2523                     }
2524                     e = e->next;
2525                 }
2526             }
2527             g = g->next;
2528         }
2529 #endif
2530         
2531                 /* Okay, now that we know what to do, release the network lock */
2532                 ast_mutex_unlock(&netlock);
2533                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
2534                 ast_mutex_unlock(&monlock);
2535                 pthread_testcancel();
2536                 /* Wait for sched or io */
2537                 res = ast_sched_wait(sched);
2538                 res = ast_io_wait(io, res);
2539                 ast_mutex_lock(&monlock);
2540                 if (res >= 0) 
2541                         ast_sched_runq(sched);
2542                 ast_mutex_unlock(&monlock);
2543         }
2544         /* Never reached */
2545         return NULL;
2546         
2547 }
2548
2549 static int restart_monitor(void)
2550 {
2551         /* If we're supposed to be stopped -- stay stopped */
2552         if (monitor_thread == (pthread_t) -2)
2553                 return 0;
2554         if (ast_mutex_lock(&monlock)) {
2555                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
2556                 return -1;
2557         }
2558         if (monitor_thread == pthread_self()) {
2559                 ast_mutex_unlock(&monlock);
2560                 ast_log(LOG_WARNING, "Cannot kill myself\n");
2561                 return -1;
2562         }
2563         if (monitor_thread) {
2564                 /* Wake up the thread */
2565                 pthread_kill(monitor_thread, SIGURG);
2566         } else {
2567                 /* Start a new monitor */
2568                 if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
2569                         ast_mutex_unlock(&monlock);
2570                         ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
2571                         return -1;
2572                 }
2573         }
2574         ast_mutex_unlock(&monlock);
2575         return 0;
2576 }
2577
2578 static struct ast_channel *mgcp_request(char *type, int format, void *data)
2579 {
2580         int oldformat;
2581         struct mgcp_subchannel *sub;
2582         struct ast_channel *tmpc = NULL;
2583         char tmp[256];
2584         char *dest = data;
2585
2586         oldformat = format;
2587         format &= capability;
2588         if (!format) {
2589                 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
2590                 return NULL;
2591         }
2592         strncpy(tmp, dest, sizeof(tmp) - 1);
2593         if (!strlen(tmp)) {
2594                 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
2595                 return NULL;
2596         }
2597         sub = find_subchannel(tmp, 0, NULL);
2598         if (!sub) {
2599                 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
2600                 return NULL;
2601         }
2602         
2603     if (option_verbose > 2) {
2604         ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
2605         ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 
2606                     sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
2607     }
2608         /* Must be busy */
2609         if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
2610         ((!sub->parent->callwaiting) && (sub->owner)) ||
2611          (sub->parent->dnd && (!strlen(sub->parent->call_forward)))) {
2612          if (sub->parent->hookstate == MGCP_ONHOOK) {
2613              if (has_voicemail(sub->parent)) {
2614                  transmit_notify_request(sub,"vmwi(+)");
2615              } else {
2616                  transmit_notify_request(sub,"vmwi(-)");
2617              }
2618          }
2619                 return NULL;
2620     }
2621         tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
2622         if (!tmpc)
2623                 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
2624         restart_monitor();
2625         return tmpc;
2626 }
2627
2628 static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
2629 {
2630         struct mgcp_gateway *gw;
2631         struct mgcp_endpoint *e;
2632     struct mgcp_subchannel *sub;
2633     /*char txident[80];*/
2634     int i=0, y=0;
2635         canreinvite = CANREINVITE;
2636         gw = malloc(sizeof(struct mgcp_gateway));
2637         if (gw) {
2638                 memset(gw, 0, sizeof(struct mgcp_gateway));
2639                 gw->expire = -1;
2640                 strncpy(gw->name, cat, sizeof(gw->name) - 1);
2641                 while(v) {
2642                         if (!strcasecmp(v->name, "host")) {
2643                                 if (!strcasecmp(v->value, "dynamic")) {
2644                                         /* They'll register with us */
2645                                         gw->dynamic = 1;
2646                                         memset(&gw->addr.sin_addr, 0, 4);
2647                                         if (gw->addr.sin_port) {
2648                                                 /* If we've already got a port, make it the default rather than absolute */
2649                                                 gw->defaddr.sin_port = gw->addr.sin_port;
2650                                                 gw->addr.sin_port = 0;
2651                                         }
2652                                 } else {
2653                                         /* Non-dynamic.  Make sure we become that way if we're not */
2654                                         if (gw->expire > -1)
2655                                                 ast_sched_del(sched, gw->expire);
2656                                         gw->expire = -1;
2657                                         gw->dynamic = 0;
2658                                         if (ast_get_ip(&gw->addr, v->value)) {
2659                                                 free(gw);
2660                                                 return NULL;
2661                                         }
2662                                 }
2663                         } else if (!strcasecmp(v->name, "defaultip")) {
2664                                 if (ast_get_ip(&gw->defaddr, v->value)) {
2665                                         free(gw);
2666                                         return NULL;
2667                                 }
2668                         } else if (!strcasecmp(v->name, "permit") ||
2669                                            !strcasecmp(v->name, "deny")) {
2670                                 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
2671                         } else if (!strcasecmp(v->name, "port")) {
2672                                 gw->addr.sin_port = htons(atoi(v->value));
2673                         } else if (!strcasecmp(v->name, "context")) {
2674                                 strncpy(context, v->value, sizeof(context) - 1);
2675                         } else if (!strcasecmp(v->name, "inbanddtmf")) {
2676                                 inbanddtmf = atoi(v->value);
2677                         } else if (!strcasecmp(v->name, "nat")) {
2678                                 nat = ast_true(v->value);
2679                         } else if (!strcasecmp(v->name, "callerid")) {
2680                                 if (!strcasecmp(v->value, "asreceived"))
2681                                         strcpy(callerid, "");
2682                                 else
2683                                         strncpy(callerid, v->value, sizeof(callerid) - 1);
2684                         } else if (!strcasecmp(v->name, "language")) {
2685                                 strncpy(language, v->value, sizeof(language)-1);
2686             } else if (!strcasecmp(v->name, "accountcode")) {
2687                 strncpy(accountcode, v->value, sizeof(accountcode)-1);
2688             } else if (!strcasecmp(v->name, "amaflags")) {
2689                 y = ast_cdr_amaflags2int(v->value);
2690                 if (y < 0) {
2691                     ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
2692                 } else {
2693                     amaflags = y;
2694                 }
2695             } else if (!strcasecmp(v->name, "musiconhold")) {
2696                 strncpy(musicclass, v->value, sizeof(musicclass)-1);
2697             } else if (!strcasecmp(v->name, "callgroup")) {
2698                 cur_callergroup = ast_get_group(v->value);
2699             } else if (!strcasecmp(v->name, "pickupgroup")) {
2700                 cur_pickupgroup = ast_get_group(v->value);
2701             } else if (!strcasecmp(v->name, "immediate")) {
2702                 immediate = ast_true(v->value);
2703             } else if (!strcasecmp(v->name, "cancallforward")) {
2704                 cancallforward = ast_true(v->value);
2705             } else if (!strcasecmp(v->name, "canreinvite")) {
2706                 canreinvite = ast_true(v->value);
2707             } else if (!strcasecmp(v->name, "mailbox")) {
2708                 strncpy(mailbox, v->value, sizeof(mailbox) -1);
2709             } else if (!strcasecmp(v->name, "adsi")) {
2710                 adsi = ast_true(v->value);
2711             } else if (!strcasecmp(v->name, "callreturn")) {
2712                 callreturn = ast_true(v->value);
2713             } else if (!strcasecmp(v->name, "immediate")) {
2714                 immediate = ast_true(v->value);
2715             } else if (!strcasecmp(v->name, "callwaiting")) {
2716                 callwaiting = ast_true(v->value);
2717             } else if (!strcasecmp(v->name, "transfer")) {
2718                 transfer = ast_true(v->value);
2719             } else if (!strcasecmp(v->name, "threewaycalling")) {
2720                 threewaycalling = ast_true(v->value);
2721
2722                         } else if (!strcasecmp(v->name, "trunk") ||
2723                                    !strcasecmp(v->name, "line")) {
2724                                 e = malloc(sizeof(struct mgcp_endpoint));
2725                                 if (e) {
2726                                         memset(e, 0, sizeof(struct mgcp_endpoint));
2727                                         strncpy(e->name, v->value, sizeof(e->name) - 1);
2728                                         /* XXX Should we really check for uniqueness?? XXX */
2729                                         strncpy(e->context, context, sizeof(e->context) - 1);
2730                                         strncpy(e->callerid, callerid, sizeof(e->callerid) - 1);
2731                                         strncpy(e->language, language, sizeof(e->language) - 1);
2732                     strncpy(e->musicclass, musicclass, sizeof(e->musicclass)-1);
2733                     strncpy(e->mailbox, mailbox, sizeof(e->mailbox)-1);
2734                     if (strlen(mailbox)) {
2735                         ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
2736                     }
2737                     e->msgstate = -1;
2738                                         e->capability = capability;
2739                                         e->parent = gw;
2740                                         e->dtmfinband = inbanddtmf;
2741                                         e->adsi = adsi;
2742                                         if (!strcasecmp(v->name, "trunk"))
2743                                                 e->type = TYPE_TRUNK;
2744                                         else
2745                                                 e->type = TYPE_LINE;
2746
2747                     e->immediate = immediate;
2748                     e->callgroup=cur_callergroup;
2749                     e->pickupgroup=cur_pickupgroup;
2750                     e->callreturn = callreturn;
2751                     e->cancallforward = cancallforward;
2752                     e->canreinvite = canreinvite;
2753                     e->callwaiting = callwaiting;
2754                     e->transfer = transfer;
2755                     e->threewaycalling = threewaycalling;
2756                     e->onhooktime = time(NULL);
2757                     /* ASSUME we're onhook */
2758                     e->hookstate = MGCP_ONHOOK;
2759                     /*snprintf(txident, sizeof(txident), "%08x", rand());*/
2760
2761                     for (i = 0; i < MAX_SUBS; i++) {
2762                         sub = malloc(sizeof(struct mgcp_subchannel));
2763                         if (sub) {
2764                             ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
2765                             memset(sub, 0, sizeof(struct mgcp_subchannel));
2766                             sub->parent = e;
2767                             sub->id = i;
2768                             snprintf(sub->txident, sizeof(sub->txident), "%08x", rand());
2769                             /*strcpy(sub->txident, txident);*/
2770                             sub->cxmode = MGCP_CX_INACTIVE;
2771                             sub->nat = nat;
2772                             sub->next = e->sub;
2773                             e->sub = sub;
2774                         } else {
2775                             /* XXX Should find a way to clean up our memory */
2776                             ast_log(LOG_WARNING, "Out of memory allocating subchannel");
2777                             return NULL;
2778                         }
2779                     }
2780                     /* Make out subs a circular linked list so we can always sping through the whole bunch */
2781                     sub = e->sub;
2782                     /* find the end of the list */
2783                     while(sub->next){
2784                         sub = sub->next;
2785                     }
2786                     /* set the last sub->next to the first sub */
2787                     sub->next = e->sub;
2788
2789
2790                                         e->next = gw->endpoints;
2791                                         gw->endpoints = e;
2792                                 }
2793                         } else
2794                                 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
2795                         v = v->next;
2796                 }
2797                 
2798         }
2799         if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
2800                 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
2801                 free(gw);
2802                 return NULL;
2803         }
2804         if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 
2805                 gw->defaddr.sin_port = htons(DEFAULT_MGCP_PORT);
2806         if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
2807                 gw->addr.sin_port = htons(DEFAULT_MGCP_PORT);
2808         if (gw->addr.sin_addr.s_addr)
2809                 if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
2810                         memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
2811         return gw;
2812 }
2813
2814 static struct ast_rtp *mgcp_get_rtp_peer(struct ast_channel *chan)
2815 {
2816         struct mgcp_subchannel *sub;
2817         sub = chan->pvt->pvt;
2818         if (sub && sub->rtp && sub->parent->canreinvite)
2819                 return sub->rtp;
2820         return NULL;
2821 }
2822
2823 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp)
2824 {
2825         /* XXX Is there such thing as video support with MGCP? XXX */
2826         struct mgcp_subchannel *sub;
2827         sub = chan->pvt->pvt;
2828         if (sub) {
2829                 transmit_modify_with_sdp(sub, rtp);
2830                 return 0;
2831         }
2832         return -1;
2833 }
2834
2835 static struct ast_rtp_protocol mgcp_rtp = {
2836         get_rtp_info: mgcp_get_rtp_peer,
2837         set_rtp_peer: mgcp_set_rtp_peer,
2838 };
2839
2840 static int mgcp_do_debug(int fd, int argc, char *argv[])
2841 {
2842         if (argc != 2)
2843                 return RESULT_SHOWUSAGE;
2844         mgcpdebug = 1;
2845         ast_cli(fd, "MGCP Debugging Enabled\n");
2846         return RESULT_SUCCESS;
2847 }
2848
2849 static int mgcp_no_debug(int fd, int argc, char *argv[])
2850 {
2851         if (argc != 3)
2852                 return RESULT_SHOWUSAGE;
2853         mgcpdebug = 0;
2854         ast_cli(fd, "MGCP Debugging Disabled\n");
2855         return RESULT_SUCCESS;
2856 }
2857
2858 static char debug_usage[] = 
2859 "Usage: mgcp debug\n"
2860 "       Enables dumping of MGCP packets for debugging purposes\n";
2861
2862 static char no_debug_usage[] = 
2863 "Usage: mgcp no debug\n"
2864 "       Disables dumping of MGCP packets for debugging purposes\n";
2865
2866 static struct ast_cli_entry  cli_debug =
2867         { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage };
2868 static struct ast_cli_entry  cli_no_debug =
2869         { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage };
2870
2871
2872 int load_module()
2873 {
2874         struct ast_config *cfg;
2875         struct ast_variable *v;
2876         struct mgcp_gateway *g;
2877         struct mgcp_endpoint *e;
2878         char *cat;
2879         struct hostent *hp;
2880         int format;
2881         
2882         if (gethostname(ourhost, sizeof(ourhost))) {
2883                 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
2884                 return 0;
2885         }
2886         cfg = ast_load(config);
2887
2888         /* We *must* have a config file otherwise stop immediately */
2889         if (!cfg) {
2890                 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
2891                 return 0;
2892         }
2893         memset(&bindaddr, 0, sizeof(bindaddr));
2894         v = ast_variable_browse(cfg, "general");
2895         while(v) {
2896                 /* Create the interface list */
2897                 if (!strcasecmp(v->name, "bindaddr")) {
2898                         if (!(hp = gethostbyname(v->value))) {
2899                                 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
2900                         } else {
2901                                 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
2902                         }
2903                 } else if (!strcasecmp(v->name, "allow")) {
2904                         format = ast_getformatbyname(v->value);
2905                         if (format < 1) 
2906                                 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
2907                         else
2908                                 capability |= format;
2909                 } else if (!strcasecmp(v->name, "disallow")) {
2910                         format = ast_getformatbyname(v->value);
2911                         if (format < 1) 
2912                                 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
2913                         else
2914                                 capability &= ~format;
2915                 } else if (!strcasecmp(v->name, "tos")) {
2916                         if (sscanf(v->value, "%i", &format) == 1)
2917                                 tos = format & 0xff;
2918                         else if (!strcasecmp(v->value, "lowdelay"))
2919                                 tos = IPTOS_LOWDELAY;
2920                         else if (!strcasecmp(v->value, "throughput"))
2921                                 tos = IPTOS_THROUGHPUT;
2922                         else if (!strcasecmp(v->value, "reliability"))
2923                                 tos = IPTOS_RELIABILITY;
2924                         else if (!strcasecmp(v->value, "mincost"))
2925                                 tos = IPTOS_MINCOST;
2926                         else if (!strcasecmp(v->value, "none"))
2927                                 tos = 0;
2928                         else
2929                                 ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
2930                 } else if (!strcasecmp(v->name, "port")) {
2931                         if (sscanf(v->value, "%i", &ourport) == 1) {
2932                                 bindaddr.sin_port = htons(ourport);
2933                         } else {
2934                                 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
2935                         }
2936                 }
2937                 v = v->next;
2938         }
2939         
2940         cat = ast_category_browse(cfg, NULL);
2941         while(cat) {
2942                 if (strcasecmp(cat, "general")) {
2943                         g = build_gateway(cat, ast_variable_browse(cfg, cat));
2944                         if (g) {
2945                                 if (option_verbose > 2) {
2946                                         ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
2947                 }
2948                                 ast_mutex_lock(&gatelock);
2949                                 g->next = gateways;
2950                                 gateways = g;
2951                                 ast_mutex_unlock(&gatelock);
2952                         }
2953                 }
2954                 cat = ast_category_browse(cfg, cat);
2955         }
2956         
2957         if (ntohl(bindaddr.sin_addr.s_addr)) {
2958                 memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
2959         } else {
2960                 hp = gethostbyname(ourhost);
2961                 if (!hp) {
2962                         ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
2963                         return 0;
2964                 }
2965                 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
2966         }
2967         if (!ntohs(bindaddr.sin_port))
2968                 bindaddr.sin_port = ntohs(DEFAULT_MGCP_PORT);
2969         bindaddr.sin_family = AF_INET;
2970         ast_mutex_lock(&netlock);
2971         if (mgcpsock > -1)
2972                 close(mgcpsock);
2973         mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
2974         if (mgcpsock < 0) {
2975                 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
2976         } else {
2977                 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
2978                         ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
2979                                         inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
2980                                                 strerror(errno));
2981                         close(mgcpsock);
2982                         mgcpsock = -1;
2983                 } else {
2984                         if (option_verbose > 1) {
2985                                 ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n", 
2986                                         inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
2987                                 ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
2988                         }
2989                         if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
2990                                 ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
2991         }
2992         }
2993         ast_mutex_unlock(&netlock);
2994         ast_destroy(cfg);
2995
2996         /* Make sure we can register our mgcp channel type */
2997         if (ast_channel_register(type, tdesc, capability, mgcp_request)) {
2998                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
2999                 ast_destroy(cfg);
3000                 return -1;
3001         }
3002         mgcp_rtp.type = type;
3003         ast_rtp_proto_register(&mgcp_rtp);
3004         ast_cli_register(&cli_show_endpoints);
3005         ast_cli_register(&cli_audit_endpoint);
3006         ast_cli_register(&cli_debug);
3007         ast_cli_register(&cli_no_debug);
3008         /* And start the monitor for the first time */
3009         restart_monitor();
3010
3011     g = gateways;
3012     while (g) {
3013                 e = g->endpoints;
3014         while (e) {
3015             transmit_audit_endpoint(e);
3016                         ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
3017             e = e->next;
3018         }
3019         g = g->next;
3020     }
3021
3022         return 0;
3023 }
3024
3025 int unload_module()
3026 {
3027 #if 0
3028         struct mgcp_endpoint *p, *pl;
3029         /* First, take us out of the channel loop */
3030         ast_channel_unregister(type);
3031         if (!ast_mutex_lock(&gatelock)) {
3032                 /* Hangup all interfaces if they have an owner */
3033                 p = iflist;
3034                 while(p) {
3035                         if (p->owner)
3036                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
3037                         p = p->next;
3038                 }
3039                 iflist = NULL;
3040                 ast_mutex_unlock(&iflock);
3041         } else {
3042                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
3043                 return -1;
3044         }
3045         if (!ast_mutex_lock(&monlock)) {
3046                 if (monitor_thread && (monitor_thread != -2)) {
3047                         pthread_cancel(monitor_thread);
3048                         pthread_kill(monitor_thread, SIGURG);
3049                         pthread_join(monitor_thread, NULL);
3050                 }
3051                 monitor_thread = -2;
3052                 ast_mutex_unlock(&monlock);
3053         } else {
3054                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
3055                 return -1;
3056         }
3057
3058         if (!ast_mutex_lock(&iflock)) {
3059                 /* Destroy all the interfaces and free their memory */
3060                 p = iflist;
3061                 while(p) {
3062                         pl = p;
3063                         p = p->next;
3064                         /* Free associated memory */
3065                         free(pl);
3066                 }
3067                 iflist = NULL;
3068                 ast_mutex_unlock(&iflock);
3069         } else {
3070                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
3071                 return -1;
3072         }
3073 #endif          
3074         return -1;
3075 }
3076
3077 int usecount()
3078 {
3079         int res;