More specifics in MGCP
[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 <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <net/if.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <fcntl.h>
39 #include <netdb.h>
40 #include <arpa/inet.h>
41 #include <sys/signal.h>
42 #include <asterisk/dsp.h>
43 #include <ctype.h>
44
45 #define MGCPDUMPER
46 #define DEFAULT_EXPIREY 120
47 #define MAX_EXPIREY     3600
48
49 static char *desc = "Media Gateway Control Protocol (MGCP)";
50 static char *type = "MGCP";
51 static char *tdesc = "Media Gateway Control Protocol (MGCP)";
52 static char *config = "mgcp.conf";
53
54 #define DEFAULT_MGCP_PORT       2427/* From RFC 2705 */
55 #define MGCP_MAX_PACKET 1500            /* Also from RFC 2543, should sub headers tho */
56
57 static int usecnt =0;
58 static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
59 static int oseq;
60
61 /* Protect the monitoring thread, so only one process can kill or start it, and not
62    when it's doing something critical. */
63 static pthread_mutex_t netlock = AST_MUTEX_INITIALIZER;
64
65 static pthread_mutex_t monlock = AST_MUTEX_INITIALIZER;
66
67 /* This is the thread for the monitor which checks for input on the channels
68    which are not currently in use.  */
69 static pthread_t monitor_thread = 0;
70
71 static int restart_monitor(void);
72
73 /* Just about everybody seems to support ulaw, so make it a nice default */
74 static int capability = AST_FORMAT_ULAW;
75 static int nonCodecCapability = AST_RTP_DTMF;
76
77 static char ourhost[256];
78 static struct in_addr __ourip;
79 static int ourport;
80
81 static int mgcpdebug = 0;
82
83 static struct sched_context *sched;
84 static struct io_context *io;
85 /* The private structures of the  mgcp channels are linked for
86    selecting outgoing channels */
87    
88 #define MGCP_MAX_HEADERS                64
89 #define MGCP_MAX_LINES          64
90
91 struct mgcp_request {
92         int len;
93         char *verb;
94         char *identifier;
95         char *endpoint;
96         char *version;
97         int headers;                                    /* MGCP Headers */
98         char *header[MGCP_MAX_HEADERS];
99         int lines;                                              /* SDP Content */
100         char *line[MGCP_MAX_LINES];
101         char data[MGCP_MAX_PACKET];
102 };
103
104 static struct mgcp_pkt {
105         int retrans;
106         struct mgcp_endpoint *owner;
107         int packetlen;
108         char data[MGCP_MAX_PACKET];
109         struct mgcp_pkt *next;
110 } *packets = NULL;      
111
112 /* MGCP message for queuing up */
113 struct mgcp_message {
114         unsigned int seqno;
115         int len;
116         struct mgcp_message *next;
117         unsigned char buf[0];
118 };
119
120 #define TYPE_TRUNK              1
121 #define TYPE_LINE               2
122
123 struct mgcp_endpoint {
124         pthread_mutex_t lock;
125         char name[80];
126         char accountcode[80];
127         char exten[AST_MAX_EXTENSION];          /* Extention where to start */
128         char context[AST_MAX_EXTENSION];
129         char language[MAX_LANGUAGE];
130         char callerid[256];                                     /* Caller*ID */
131         char curtone[80];                                       /* Current tone */
132         char txident[80];
133         char cxident[80];
134         char callid[80];
135         int hascallerid;
136         int dtmfinband;
137         int amaflags;
138         int type;
139         int group;
140         int iseq;
141         int nat;
142         int lastout;
143         int alreadygone;
144         int needdestroy;
145         int capability;
146         int nonCodecCapability;
147         int outgoing;
148         struct ast_dsp *vad;
149         struct ast_channel *owner;
150         struct ast_rtp *rtp;
151         struct sockaddr_in tmpdest;
152         struct mgcp_message *msgs;                      /* Message queue */
153         int messagepending;
154         struct mgcp_endpoint *next;
155         struct mgcp_gateway *parent;
156 };
157
158 struct mgcp_gateway {
159         /* A gateway containing one or more endpoints */
160         char name[80];
161         struct sockaddr_in addr;
162         struct sockaddr_in defaddr;
163         struct in_addr ourip;
164         int dynamic;
165         int expire;             /* XXX Should we ever expire dynamic registrations? XXX */
166         struct mgcp_endpoint *endpoints;
167         struct ast_ha *ha;
168         struct mgcp_gateway *next;
169 } *gateways;
170
171 static pthread_mutex_t gatelock  = AST_MUTEX_INITIALIZER;
172
173 static int mgcpsock  = -1;
174
175 static struct sockaddr_in bindaddr;
176
177 static struct ast_frame  *mgcp_read(struct ast_channel *ast);
178 static int transmit_response(struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest);
179 static int transmit_notify_request(struct mgcp_endpoint *p, char *tone, int offhook);
180 static int transmit_connection_del(struct mgcp_endpoint *p);
181 static int transmit_notify_request_with_callerid(struct mgcp_endpoint *p, char *tone, int offhook, char *callerid);
182
183 static int __mgcp_xmit(struct mgcp_endpoint *p, char *data, int len)
184 {
185         int res;
186         if (p->parent->addr.sin_addr.s_addr)
187             res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->addr, sizeof(struct sockaddr_in));
188         else 
189             res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&p->parent->defaddr, sizeof(struct sockaddr_in));
190         if (res != len) {
191                 ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
192         }
193         return res;
194 }
195
196 static int send_response(struct mgcp_endpoint *p, struct mgcp_request *req)
197 {
198         int res;
199         if (mgcpdebug)
200                 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));
201         res = __mgcp_xmit(p, req->data, req->len);
202         if (res > 0)
203                 res = 0;
204         return res;
205 }
206
207 static void dump_queue(struct mgcp_endpoint *p)
208 {
209         struct mgcp_message *cur;
210         while(p->msgs) {
211                 cur = p->msgs;
212                 p->msgs = p->msgs->next;
213                 free(cur);
214         }
215         p->messagepending = 0;
216         p->msgs = NULL;
217 }
218
219 static int mgcp_postrequest(struct mgcp_endpoint *p, unsigned char *data, int len, unsigned int seqno)
220 {
221         struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
222         struct mgcp_message *cur;
223         if (!msg)
224                 return -1;
225         msg->seqno = seqno;
226         msg->next = NULL;
227         msg ->len = len;
228         memcpy(msg->buf, data, msg->len);
229         cur = p->msgs;
230         if (cur) {
231                 while(cur->next)
232                         cur = cur->next;
233                 cur->next = msg;
234         } else
235                 p->msgs = msg;
236         if (!p->messagepending) {
237                 p->messagepending = 1;
238                 p->lastout = seqno;
239                 __mgcp_xmit(p, msg->buf, msg->len);
240                 /* XXX Should schedule retransmission XXX */
241         } else
242                 ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
243         return 0;
244 }
245
246 static int send_request(struct mgcp_endpoint *p, struct mgcp_request *req, unsigned int seqno)
247 {
248         int res;
249         if (mgcpdebug)
250                 ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
251                 
252         res = mgcp_postrequest(p, req->data, req->len, seqno);
253         return res;
254 }
255
256 static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
257 {
258         int res;
259         struct mgcp_endpoint *p;
260         
261         p = ast->pvt->pvt;
262         if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
263                 ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
264                 return -1;
265         }
266
267         res = 0;
268         p->outgoing = 1;
269         if (p->type == TYPE_LINE) {
270                 transmit_notify_request_with_callerid(p, "L/rg", 0, ast->callerid);
271                 ast_setstate(ast, AST_STATE_RINGING);
272                 ast_queue_control(ast, AST_CONTROL_RINGING, 0);
273         } else {
274                 ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");
275                 res = -1;
276         }
277         return res;
278 }
279
280 /* Interface lookup code courtesy Tilghman of DrunkCoder.com.  Thanks! */
281
282 struct my_ifreq {
283     union
284       {
285         char ifrn_name[IFNAMSIZ];       /* Interface name, e.g. "en0".  */
286       } ifr_ifrn;
287
288     union
289       {
290         struct sockaddr_in ifru_addr;
291         char ifru_data[512];
292       } ifr_ifru;
293 };
294
295 struct in_addr *lookup_iface(char *iface) {
296         int mysock;
297         int res;
298         static struct  my_ifreq ifreq;
299         strncpy(ifreq.ifr_ifrn.ifrn_name,iface,sizeof(ifreq.ifr_ifrn.ifrn_name));
300
301         mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
302         res = ioctl(mysock,SIOCGIFADDR,&ifreq);
303         
304         close(mysock);
305         if (res < 0) {
306                 ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
307                 return &__ourip;
308         }
309         return( (struct in_addr *) &ifreq.ifr_ifru.ifru_addr.sin_addr );
310 }
311
312 static struct in_addr *myaddrfor(struct in_addr *them)
313 {
314         FILE *PROC;
315         struct in_addr *temp = NULL;
316         unsigned int remote_ip;
317         char line[256];
318         remote_ip = them->s_addr;
319         
320         PROC = fopen("/proc/net/route","r");
321         if (!PROC) {
322                 /* If /proc/net/route doesn't exist, fall back to the old method */
323                 return &__ourip;
324         }
325         /* First line contains headers */
326         fgets(line,sizeof(line),PROC);
327
328         while (!feof(PROC)) {
329                 char iface[8];
330                 unsigned int dest, gateway, mask;
331                 int i,aoffset;
332                 char *fields[40];
333
334                 fgets(line,sizeof(line),PROC);
335
336                 aoffset = 0;
337                 for (i=0;i<sizeof(line);i++) {
338                         char *boffset;
339
340                         fields[aoffset++] = line + i;
341                         boffset = strchr(line + i,'\t');
342                         if (boffset == NULL) {
343                                 /* Exit loop */
344                                 break;
345                         } else {
346                                 *boffset = '\0';
347                                 i = boffset - line;
348                         }
349                 }
350
351                 sscanf(fields[0],"%s",iface);
352                 sscanf(fields[1],"%x",&dest);
353                 sscanf(fields[2],"%x",&gateway);
354                 sscanf(fields[7],"%x",&mask);
355 #if 0
356                 printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
357 #endif          
358                 if (((remote_ip & mask) ^ dest) == 0) {
359
360                         if (mgcpdebug)
361                                         ast_verbose("Interface is %s\n",iface);
362                         temp = lookup_iface(iface);
363                         if (mgcpdebug)
364                                 ast_verbose("IP Address is %s\n",inet_ntoa(*temp));
365                         break;
366                 }
367         }
368         fclose(PROC);
369         if (!temp) {
370                 ast_log(LOG_WARNING, "Couldn't figure out how to get to %s.  Using default\n", inet_ntoa(*them));
371                 temp = &__ourip;
372         }
373         return temp;
374 }
375
376
377 static int mgcp_hangup(struct ast_channel *ast)
378 {
379         struct mgcp_endpoint *p = ast->pvt->pvt;
380         if (option_debug)
381                 ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
382         if (!ast->pvt->pvt) {
383                 ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
384                 return 0;
385         }
386         if ((p->dtmfinband) && (p->vad != NULL)){
387             ast_dsp_free(p->vad);
388         }
389         ast_pthread_mutex_lock(&p->lock);
390         p->owner = NULL;
391         if (strlen(p->cxident))
392                 transmit_connection_del(p);
393         strcpy(p->cxident, "");
394         if (!p->alreadygone && (!p->outgoing || (ast->_state == AST_STATE_UP)))
395                 transmit_notify_request(p, "ro", 1);
396         else
397                 transmit_notify_request(p, "", 0);
398         ast->pvt->pvt = NULL;
399         p->alreadygone = 0;
400         p->outgoing = 0;
401         strcpy(p->callid, "");
402         /* Reset temporary destination */
403         memset(&p->tmpdest, 0, sizeof(p->tmpdest));
404         if (p->rtp) {
405                 ast_rtp_destroy(p->rtp);
406                 p->rtp = NULL;
407         }
408         ast_pthread_mutex_unlock(&p->lock);
409         return 0;
410 }
411
412 static int mgcp_show_endpoints(int fd, int argc, char *argv[])
413 {
414         struct mgcp_gateway  *g;
415         struct mgcp_endpoint *e;
416         int hasendpoints = 0;
417         if (argc != 3) 
418                 return RESULT_SHOWUSAGE;
419         ast_pthread_mutex_lock(&gatelock);
420         g = gateways;
421         while(g) {
422                 e = g->endpoints;
423                 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");
424                 while(e) {
425                         ast_cli(fd, "   -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->owner ? "active" : "idle");
426                         hasendpoints = 1;
427                         e = e->next;
428                 }
429                 if (!hasendpoints) {
430                         ast_cli(fd, "   << No Endpoints Defined >>     ");
431                 }
432                 g = g->next;
433         }
434         ast_pthread_mutex_unlock(&gatelock);
435         return RESULT_SUCCESS;
436 }
437
438 static char show_endpoints_usage[] = 
439 "Usage: mgcp show endpoints\n"
440 "       Lists all endpoints known to the MGCP (Media Gateawy Control Protocol) subsystem.\n";
441
442 static struct ast_cli_entry  cli_show_endpoints = 
443         { { "mgcp", "show", "endpoints", NULL }, mgcp_show_endpoints, "Show defined MGCP endpoints", show_endpoints_usage };
444
445 static int mgcp_answer(struct ast_channel *ast)
446 {
447         int res = 0;
448         struct mgcp_endpoint *p = ast->pvt->pvt;
449         if (ast->_state != AST_STATE_UP) {
450                 ast_setstate(ast, AST_STATE_UP);
451                 if (option_debug)
452                         ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
453                 transmit_notify_request(p, "", 1);
454         }
455         return res;
456 }
457
458 static struct ast_frame *mgcp_rtp_read(struct mgcp_endpoint *p)
459 {
460         /* Retrieve audio/etc from channel.  Assumes p->lock is already held. */
461         struct ast_frame *f;
462         f = ast_rtp_read(p->rtp);
463         if (p->owner) {
464                 /* We already hold the channel lock */
465                 if (f->frametype == AST_FRAME_VOICE) {
466                         if (f->subclass != p->owner->nativeformats) {
467                                 ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
468                                 p->owner->nativeformats = f->subclass;
469                                 ast_set_read_format(p->owner, p->owner->readformat);
470                                 ast_set_write_format(p->owner, p->owner->writeformat);
471                         }
472                 }
473         }
474         return f;
475 }
476
477
478 static struct ast_frame  *mgcp_read(struct ast_channel *ast)
479 {
480         struct ast_frame *fr;
481         struct mgcp_endpoint *p = ast->pvt->pvt;
482         ast_pthread_mutex_lock(&p->lock);
483         fr = mgcp_rtp_read(p);
484         ast_pthread_mutex_unlock(&p->lock);
485         return fr;
486 }
487
488 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
489 {
490         struct mgcp_endpoint *p = ast->pvt->pvt;
491         int res = 0;
492         if (frame->frametype != AST_FRAME_VOICE) {
493                 if (frame->frametype == AST_FRAME_IMAGE)
494                         return 0;
495                 else {
496                         ast_log(LOG_WARNING, "Can't send %d type frames with MGCP write\n", frame->frametype);
497                         return 0;
498                 }
499         } else {
500                 if (!(frame->subclass & ast->nativeformats)) {
501                         ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
502                                 frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
503                         return -1;
504                 }
505         }
506         if (p) {
507                 ast_pthread_mutex_lock(&p->lock);
508                 if (p->rtp) {
509                         res =  ast_rtp_write(p->rtp, frame);
510                 }
511                 ast_pthread_mutex_unlock(&p->lock);
512         }
513         return res;
514 }
515
516 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
517 {
518         struct mgcp_endpoint *p = newchan->pvt->pvt;
519         ast_pthread_mutex_lock(&p->lock);
520         if (p->owner != oldchan) {
521                 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
522                 return -1;
523         }
524         p->owner = newchan;
525         ast_pthread_mutex_unlock(&p->lock);
526         return 0;
527 }
528
529 static int mgcp_senddigit(struct ast_channel *ast, char digit)
530 {
531         struct mgcp_endpoint *p = ast->pvt->pvt;
532         char tmp[2];
533         tmp[0] = digit;
534         tmp[1] = '\0';
535         transmit_notify_request(p, tmp, 1);
536         return -1;
537 }
538
539
540 static int mgcp_indicate(struct ast_channel *ast, int ind)
541 {
542         struct mgcp_endpoint *p = ast->pvt->pvt;
543         switch(ind) {
544         case AST_CONTROL_RINGING:
545                 transmit_notify_request(p, "rt", 1);
546                 break;
547         case AST_CONTROL_BUSY:
548                 transmit_notify_request(p, "bz", 1);
549                 break;
550         case AST_CONTROL_CONGESTION:
551                 transmit_notify_request(p, "nbz", 1);
552                 break;
553         case -1:
554                 transmit_notify_request(p, "", 1);
555                 break;          
556         default:
557                 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
558                 return -1;
559         }
560         return 0;
561 }
562
563 static struct ast_channel *mgcp_new(struct mgcp_endpoint *i, int state)
564 {
565         struct ast_channel *tmp;
566         int fmt;
567         tmp = ast_channel_alloc(1);
568         if (tmp) {
569                 tmp->nativeformats = i->capability;
570                 if (!tmp->nativeformats)
571                         tmp->nativeformats = capability;
572                 fmt = ast_best_codec(tmp->nativeformats);
573                 snprintf(tmp->name, sizeof(tmp->name), "MGCP/%s@%s", i->name, i->parent->name);
574                 if (i->rtp)
575                         tmp->fds[0] = ast_rtp_fd(i->rtp);
576                 tmp->type = type;
577                 if (i->dtmfinband) {
578                     i->vad = ast_dsp_new();
579                     ast_dsp_set_features(i->vad,DSP_FEATURE_DTMF_DETECT);
580                 } else {
581                     i->vad = NULL;
582                 }
583                 ast_setstate(tmp, state);
584                 if (state == AST_STATE_RING)
585                         tmp->rings = 1;
586                 tmp->writeformat = fmt;
587                 tmp->pvt->rawwriteformat = fmt;
588                 tmp->readformat = fmt;
589                 tmp->pvt->rawreadformat = fmt;
590                 tmp->pvt->pvt = i;
591                 tmp->pvt->call = mgcp_call;
592                 tmp->pvt->hangup = mgcp_hangup;
593                 tmp->pvt->answer = mgcp_answer;
594                 tmp->pvt->read = mgcp_read;
595                 tmp->pvt->write = mgcp_write;
596                 tmp->pvt->indicate = mgcp_indicate;
597                 tmp->pvt->fixup = mgcp_fixup;
598                 tmp->pvt->send_digit = mgcp_senddigit;
599                 tmp->pvt->bridge = ast_rtp_bridge;
600                 if (strlen(i->language))
601                         strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
602                 i->owner = tmp;
603                 ast_pthread_mutex_lock(&usecnt_lock);
604                 usecnt++;
605                 ast_pthread_mutex_unlock(&usecnt_lock);
606                 ast_update_use_count();
607                 strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
608                 strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
609                 if (strlen(i->callerid))
610                         tmp->callerid = strdup(i->callerid);
611                 tmp->priority = 1;
612                 if (state != AST_STATE_DOWN) {
613                         if (ast_pbx_start(tmp)) {
614                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
615                                 ast_hangup(tmp);
616                                 tmp = NULL;
617                         }
618                 }
619         } else
620                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
621         return tmp;
622 }
623
624 static char* get_sdp_by_line(char* line, char *name, int nameLen) {
625   if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
626     char* r = line + nameLen + 1;
627     while (*r && (*r < 33)) ++r;
628     return r;
629   }
630
631   return "";
632 }
633
634 static char *get_sdp(struct mgcp_request *req, char *name) {
635   int x;
636   int len = strlen(name);
637   char *r;
638
639   for (x=0; x<req->lines; x++) {
640     r = get_sdp_by_line(req->line[x], name, len);
641     if (r[0] != '\0') return r;
642   }
643   return "";
644 }
645
646 static void sdpLineNum_iterator_init(int* iterator) {
647   *iterator = 0;
648 }
649
650 static char* get_sdp_iterate(int* iterator,
651                              struct mgcp_request *req, char *name) {
652   int len = strlen(name);
653   char *r;
654   while (*iterator < req->lines) {
655     r = get_sdp_by_line(req->line[(*iterator)++], name, len);
656     if (r[0] != '\0') return r;
657   }
658   return "";
659 }
660
661 static char *__get_header(struct mgcp_request *req, char *name, int *start)
662 {
663         int x;
664         int len = strlen(name);
665         char *r;
666         for (x=*start;x<req->headers;x++) {
667                 if (!strncasecmp(req->header[x], name, len) && 
668                                 (req->header[x][len] == ':')) {
669                                         r = req->header[x] + len + 1;
670                                         while(*r && (*r < 33))
671                                                         r++;
672                                         *start = x+1;
673                                         return r;
674                 }
675         }
676         /* Don't return NULL, so get_header is always a valid pointer */
677         return "";
678 }
679
680 static char *get_header(struct mgcp_request *req, char *name)
681 {
682         int start = 0;
683         return __get_header(req, name, &start);
684 }
685
686 #if 0
687 static int rtpready(struct ast_rtp *rtp, struct ast_frame *f, void *data)
688 {
689         /* Just deliver the audio directly */
690         struct mgcp_endpoint *p = data;
691         ast_pthread_mutex_lock(&p->lock);
692         if (p->owner) {
693                 /* Generally, you lock in the order channel lock, followed by private
694                    lock.  Since here we are doing the reverse, there is the possibility
695                    of deadlock.  As a result, in the case of a deadlock, we simply fail out
696                    here. */
697                 if (!pthread_mutex_trylock(&p->owner->lock)) {
698                         if (f->frametype == AST_FRAME_VOICE) {
699                                 if (f->subclass != p->owner->nativeformats) {
700                                         ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
701                                         p->owner->nativeformats = f->subclass;
702                                         ast_set_read_format(p->owner, p->owner->readformat);
703                                         ast_set_write_format(p->owner, p->owner->writeformat);
704                                 }
705                                 if (p->dtmfinband) {
706                                     f = ast_dsp_process(p->owner,p->vad,f,0);
707                                 }
708                         }
709                         ast_queue_frame(p->owner, f, 0);
710                         pthread_mutex_unlock(&p->owner->lock);
711                 }
712         }
713         ast_pthread_mutex_unlock(&p->lock);
714         return 0;
715 }
716 #endif
717
718 static struct mgcp_endpoint *find_endpoint(char *name, int msgid, struct sockaddr_in *sin)
719 {
720         struct mgcp_endpoint *p = NULL;
721         struct mgcp_gateway *g;
722         char tmp[256] = "";
723         char *at = NULL;
724         if (name) {
725                 strncpy(tmp, name, sizeof(tmp) - 1);
726                 at = strchr(tmp, '@');
727                 if (!at) {
728                         ast_log(LOG_NOTICE, "Endpoint '%s' has no at sign!\n", name);
729                         return NULL;
730                 }
731                 *at = '\0';
732                 at++;
733         }
734         ast_pthread_mutex_lock(&gatelock);
735         g = gateways;
736         while(g) {
737                 if ((!name || !strcasecmp(g->name, at)) && 
738                     (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
739                         /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
740                         if (sin && g->dynamic) {
741                                 if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
742                                         (g->addr.sin_port != sin->sin_port)) {
743                                         memcpy(&g->addr, sin, sizeof(g->addr));
744                                         memcpy(&g->ourip, myaddrfor(&g->addr.sin_addr), sizeof(g->ourip));
745                                         if (option_verbose > 2)
746                                                 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));
747                                 }
748                         }
749                         p = g->endpoints;
750                         while(p) {
751                                 if ((name && !strcasecmp(p->name, tmp)) ||
752                                     (msgid && (p->lastout == msgid)))
753                                         break;
754                                 p = p->next;
755                         }
756                         if (name || p)
757                                 break;
758                 }
759                 g = g->next;
760         }
761         ast_pthread_mutex_unlock(&gatelock);
762         if (!p) {
763                 if (name) {
764                         if (g)
765                                 ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp,at);
766                         else
767                                 ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
768                 } 
769         }
770         return p;
771 }
772
773 static void parse(struct mgcp_request *req)
774 {
775         /* Divide fields by NULL's */
776         char *c;
777         int f = 0;
778         c = req->data;
779
780         /* First header starts immediately */
781         req->header[f] = c;
782         while(*c) {
783                 if (*c == '\n') {
784                         /* We've got a new header */
785                         *c = 0;
786
787 #if 0
788                         printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
789 #endif                  
790                         if (!strlen(req->header[f])) {
791                                 /* Line by itself means we're now in content */
792                                 c++;
793                                 break;
794                         }
795                         if (f >= MGCP_MAX_HEADERS - 1) {
796                                 ast_log(LOG_WARNING, "Too many MGCP headers...\n");
797                         } else
798                                 f++;
799                         req->header[f] = c + 1;
800                 } else if (*c == '\r') {
801                         /* Ignore but eliminate \r's */
802                         *c = 0;
803                 }
804                 c++;
805         }
806         /* Check for last header */
807         if (strlen(req->header[f])) 
808                 f++;
809         req->headers = f;
810         /* Now we process any mime content */
811         f = 0;
812         req->line[f] = c;
813         while(*c) {
814                 if (*c == '\n') {
815                         /* We've got a new line */
816                         *c = 0;
817 #if 0
818                         printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
819 #endif                  
820                         if (f >= MGCP_MAX_LINES - 1) {
821                                 ast_log(LOG_WARNING, "Too many SDP lines...\n");
822                         } else
823                                 f++;
824                         req->line[f] = c + 1;
825                 } else if (*c == '\r') {
826                         /* Ignore and eliminate \r's */
827                         *c = 0;
828                 }
829                 c++;
830         }
831         /* Check for last line */
832         if (strlen(req->line[f])) 
833                 f++;
834         req->lines = f;
835         /* Parse up the initial header */
836         c = req->header[0];
837         while(*c && *c < 33) c++;
838         /* First the verb */
839         req->verb = c;
840         while(*c && (*c > 32)) c++;
841         if (*c) {
842                 *c = '\0';
843                 c++;
844                 while(*c && (*c < 33)) c++;
845                 req->identifier = c;
846                 while(*c && (*c > 32)) c++;
847                 if (*c) {
848                         *c = '\0';
849                         c++;
850                         while(*c && (*c < 33)) c++;
851                         req->endpoint = c;
852                         while(*c && (*c > 32)) c++;
853                         if (*c) {
854                                 *c = '\0';
855                                 c++;
856                                 while(*c && (*c < 33)) c++;
857                                 req->version = c;
858                                 while(*c && (*c > 32)) c++;
859                                 while(*c && (*c < 33)) c++;
860                                 while(*c && (*c > 32)) c++;
861                                 *c = '\0';
862                         }
863                 }
864         }
865                 
866         if (mgcpdebug) {
867                 ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
868                 req->verb, req->identifier, req->endpoint, req->version);
869                 ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
870         }
871         if (*c) 
872                 ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
873 }
874
875 static int process_sdp(struct mgcp_endpoint *p, struct mgcp_request *req)
876 {
877         char *m;
878         char *c;
879         char *a;
880         char host[258];
881         int len;
882         int portno;
883         int peercapability, peerNonCodecCapability;
884         struct sockaddr_in sin;
885         char *codecs;
886         struct hostent *hp;
887         int codec;
888         int iterator;
889
890         /* Get codec and RTP info from SDP */
891         m = get_sdp(req, "m");
892         c = get_sdp(req, "c");
893         if (!strlen(m) || !strlen(c)) {
894                 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
895                 return -1;
896         }
897         if (sscanf(c, "IN IP4 %256s", host) != 1) {
898                 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
899                 return -1;
900         }
901         /* XXX This could block for a long time, and block the main thread! XXX */
902         hp = gethostbyname(host);
903         if (!hp) {
904                 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
905                 return -1;
906         }
907         if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
908                 ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
909                 return -1;
910         }
911         sin.sin_family = AF_INET;
912         memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
913         sin.sin_port = htons(portno);
914         ast_rtp_set_peer(p->rtp, &sin);
915 #if 0
916         printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
917 #endif  
918         // Scan through the RTP payload types specified in a "m=" line:
919     ast_rtp_pt_clear(p->rtp);
920         codecs = m + len;
921         while(strlen(codecs)) {
922                 if (sscanf(codecs, "%d %n", &codec, &len) != 1) {
923                         ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
924                         return -1;
925                 }
926                 ast_rtp_set_m_type(p->rtp, codec);
927                 codecs += len;
928         }
929
930         // Next, scan through each "a=rtpmap:" line, noting each
931         // specified RTP payload type (with corresponding MIME subtype):
932         sdpLineNum_iterator_init(&iterator);
933         while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
934           char* mimeSubtype = strdup(a); // ensures we have enough space
935           if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
936           // Note: should really look at the 'freq' and '#chans' params too
937           ast_rtp_set_rtpmap_type(p->rtp, codec, "audio", mimeSubtype);
938           free(mimeSubtype);
939         }
940
941         // Now gather all of the codecs that were asked for:
942         ast_rtp_get_current_formats(p->rtp,
943                                 &peercapability, &peerNonCodecCapability);
944         p->capability = capability & peercapability;
945         if (mgcpdebug) {
946                 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
947                 capability, peercapability, p->capability);
948                 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
949                             nonCodecCapability, peerNonCodecCapability,
950                             p->nonCodecCapability);
951         }
952         if (!p->capability) {
953                 ast_log(LOG_WARNING, "No compatible codecs!\n");
954                 return -1;
955         }
956         return 0;
957         
958 }
959
960 static int add_header(struct mgcp_request *req, char *var, char *value)
961 {
962         if (req->len >= sizeof(req->data) - 4) {
963                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
964                 return -1;
965         }
966         if (req->lines) {
967                 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
968                 return -1;
969         }
970         req->header[req->headers] = req->data + req->len;
971         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
972         req->len += strlen(req->header[req->headers]);
973         if (req->headers < MGCP_MAX_HEADERS)
974                 req->headers++;
975         else {
976                 ast_log(LOG_WARNING, "Out of header space\n");
977                 return -1;
978         }
979         return 0;       
980 }
981
982 static int add_line(struct mgcp_request *req, char *line)
983 {
984         if (req->len >= sizeof(req->data) - 4) {
985                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
986                 return -1;
987         }
988         if (!req->lines) {
989                 /* Add extra empty return */
990                 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
991                 req->len += strlen(req->data + req->len);
992         }
993         req->line[req->lines] = req->data + req->len;
994         snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
995         req->len += strlen(req->line[req->lines]);
996         if (req->lines < MGCP_MAX_LINES)
997                 req->lines++;
998         else {
999                 ast_log(LOG_WARNING, "Out of line space\n");
1000                 return -1;
1001         }
1002         return 0;       
1003 }
1004
1005 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
1006 {
1007         /* Initialize a response */
1008         if (req->headers || req->len) {
1009                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1010                 return -1;
1011         }
1012         req->header[req->headers] = req->data + req->len;
1013         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
1014         req->len += strlen(req->header[req->headers]);
1015         if (req->headers < MGCP_MAX_HEADERS)
1016                 req->headers++;
1017         else
1018                 ast_log(LOG_WARNING, "Out of header space\n");
1019         return 0;
1020 }
1021
1022 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
1023 {
1024         /* Initialize a response */
1025         if (req->headers || req->len) {
1026                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
1027                 return -1;
1028         }
1029         req->header[req->headers] = req->data + req->len;
1030         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);
1031         req->len += strlen(req->header[req->headers]);
1032         if (req->headers < MGCP_MAX_HEADERS)
1033                 req->headers++;
1034         else
1035                 ast_log(LOG_WARNING, "Out of header space\n");
1036         return 0;
1037 }
1038
1039
1040 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1041 {
1042         memset(resp, 0, sizeof(*resp));
1043         init_resp(resp, msg, req, msgrest);
1044         return 0;
1045 }
1046
1047 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1048 {
1049         memset(req, 0, sizeof(struct mgcp_request));
1050         oseq++;
1051         init_req(p, req, verb);
1052         return 0;
1053 }
1054
1055 static int transmit_response(struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1056 {
1057         struct mgcp_request resp;
1058         respprep(&resp, p, msg, req, msgrest);
1059         return send_response(p, &resp);
1060 }
1061
1062
1063 static int add_sdp(struct mgcp_request *resp, struct mgcp_endpoint *p, struct ast_rtp *rtp)
1064 {
1065         int len;
1066         int codec;
1067         char costr[80];
1068         struct sockaddr_in sin;
1069         char v[256];
1070         char s[256];
1071         char o[256];
1072         char c[256];
1073         char t[256];
1074         char m[256];
1075         char a[1024] = "";
1076         int x;
1077         struct sockaddr_in dest;
1078         /* XXX We break with the "recommendation" and send our IP, in order that our
1079                peer doesn't have to gethostbyname() us XXX */
1080         len = 0;
1081         if (!p->rtp) {
1082                 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1083                 return -1;
1084         }
1085         ast_rtp_get_us(p->rtp, &sin);
1086         if (rtp) {
1087                 ast_rtp_get_peer(rtp, &dest);
1088         } else {
1089                 if (p->tmpdest.sin_addr.s_addr) {
1090                         dest.sin_addr = p->tmpdest.sin_addr;
1091                         dest.sin_port = p->tmpdest.sin_port;
1092                         /* Reset temporary destination */
1093                         memset(&p->tmpdest, 0, sizeof(p->tmpdest));
1094                 } else {
1095                         dest.sin_addr = p->parent->ourip;
1096                         dest.sin_port = sin.sin_port;
1097                 }
1098         }
1099         if (mgcpdebug)
1100                 ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 
1101         snprintf(v, sizeof(v), "v=0\r\n");
1102         snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
1103         snprintf(s, sizeof(s), "s=session\r\n");
1104         snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", inet_ntoa(dest.sin_addr));
1105         snprintf(t, sizeof(t), "t=0 0\r\n");
1106         snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
1107         for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1108                 if (p->capability & x) {
1109                         if (mgcpdebug)
1110                                 ast_verbose("Answering with capability %d\n", x);
1111                         codec = ast_rtp_lookup_code(p->rtp, 1, x);
1112                         if (codec > -1) {
1113                                 snprintf(costr, sizeof(costr), " %d", codec);
1114                                 strcat(m, costr);
1115                                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
1116                                 strcat(a, costr);
1117                         }
1118                 }
1119         }
1120         for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1121                 if (p->nonCodecCapability & x) {
1122                         if (mgcpdebug)
1123                                 ast_verbose("Answering with non-codec capability %d\n", x);
1124                         codec = ast_rtp_lookup_code(p->rtp, 0, x);
1125                         if (codec > -1) {
1126                                 snprintf(costr, sizeof(costr), " %d", codec);
1127                                 strcat(m, costr);
1128                                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x));
1129                                 strcat(a, costr);
1130                                 if (x == AST_RTP_DTMF) {
1131                                   /* Indicate we support DTMF...  Not sure about 16, but MSN supports it so dang it, we will too... */
1132                                   snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n",
1133                                            codec);
1134                                   strcat(a, costr);
1135                                 }
1136                         }
1137                 }
1138         }
1139         strcat(m, "\r\n");
1140         len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
1141         snprintf(costr, sizeof(costr), "%d", len);
1142         add_line(resp, v);
1143         add_line(resp, o);
1144         add_line(resp, s);
1145         add_line(resp, c);
1146         add_line(resp, t);
1147         add_line(resp, m);
1148         add_line(resp, a);
1149         return 0;
1150 }
1151
1152 static int transmit_modify_with_sdp(struct mgcp_endpoint *p, struct ast_rtp *rtp)
1153 {
1154         struct mgcp_request resp;
1155         char local[256];
1156         char tmp[80];
1157         int x;
1158         if (!strlen(p->cxident) && rtp) {
1159                 /* We don't have a CXident yet, store the destination and
1160                    wait a bit */
1161                 ast_rtp_get_peer(rtp, &p->tmpdest);
1162                 return 0;
1163         }
1164         snprintf(local, sizeof(local), "p:20");
1165         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1166                 if (p->capability & x) {
1167                         snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1168                         strcat(local, tmp);
1169                 }
1170         }
1171         reqprep(&resp, p, "MDCX");
1172         add_header(&resp, "C", p->callid);
1173         add_header(&resp, "L", local);
1174         add_header(&resp, "M", "sendrecv");
1175         add_header(&resp, "X", p->txident);
1176         add_header(&resp, "I", p->cxident);
1177         add_header(&resp, "S", "");
1178         add_sdp(&resp, p, rtp);
1179         return send_request(p, &resp, oseq);
1180 }
1181
1182 static int transmit_connect_with_sdp(struct mgcp_endpoint *p, struct ast_rtp *rtp)
1183 {
1184         struct mgcp_request resp;
1185         char local[256];
1186         char tmp[80];
1187         int x;
1188         snprintf(local, sizeof(local), "p:20");
1189         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1190                 if (p->capability & x) {
1191                         snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x));
1192                         strcat(local, tmp);
1193                 }
1194         }
1195         reqprep(&resp, p, "CRCX");
1196         add_header(&resp, "C", p->callid);
1197         add_header(&resp, "L", local);
1198         add_header(&resp, "M", "sendrecv");
1199         add_header(&resp, "X", p->txident);
1200         add_header(&resp, "S", "");
1201         add_sdp(&resp, p, rtp);
1202         return send_request(p, &resp, oseq);
1203 }
1204
1205 static int transmit_notify_request(struct mgcp_endpoint *p, char *tone, int offhook)
1206 {
1207         struct mgcp_request resp;
1208         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1209         reqprep(&resp, p, "RQNT");
1210         add_header(&resp, "X", p->txident);
1211         if (offhook)
1212                 add_header(&resp, "R", "hu(N), hf(N), D/[0-9#*](N)");
1213         else
1214                 add_header(&resp, "R", "hd(N)");
1215         add_header(&resp, "S", tone);
1216         return send_request(p, &resp, oseq);
1217 }
1218
1219 static int transmit_notify_request_with_callerid(struct mgcp_endpoint *p, char *tone, int offhook, char *callerid)
1220 {
1221         struct mgcp_request resp;
1222         char cid[256];
1223         char tone2[256];
1224         char *l, *n;
1225         time_t t;
1226         struct tm *tm;
1227         
1228         time(&t);
1229         tm = localtime(&t);
1230         if (callerid)
1231                 strncpy(cid, callerid, sizeof(cid) - 1);
1232         else
1233                 strcpy(cid, "");
1234         ast_callerid_parse(cid, &n, &l);
1235         if (l) {
1236                 ast_shrink_phone_number(l);
1237                 if (!ast_isphonenumber(l)) {
1238                         n = l;
1239                         l = "";
1240                 }
1241         } 
1242         if (!n)
1243                 n = "O";
1244         if (!l)
1245                 l = "";
1246         snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
1247                         tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, l, n);
1248         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1249         reqprep(&resp, p, "RQNT");
1250         add_header(&resp, "X", p->txident);
1251         if (offhook)
1252                 add_header(&resp, "R", "L/hu(N),L/hf(N),D/[0-9#*](N)");
1253         else
1254                 add_header(&resp, "R", "L/hd(N)");
1255         add_header(&resp, "S", tone2);
1256         return send_request(p, &resp, oseq);
1257 }
1258 static int transmit_connection_del(struct mgcp_endpoint *p)
1259 {
1260         struct mgcp_request resp;
1261         reqprep(&resp, p, "DLCX");
1262         add_header(&resp, "C", p->callid);
1263         add_header(&resp, "I", p->cxident);
1264         return send_request(p, &resp, oseq);
1265 }
1266
1267 static void handle_response(struct mgcp_endpoint *p, int result, int ident)
1268 {
1269         struct mgcp_message *cur;
1270         if (p->msgs && (p->msgs->seqno == ident)) {
1271                 ast_log(LOG_DEBUG, "Got response back on tansaction %d\n", ident);
1272                 cur = p->msgs;
1273                 p->msgs = p->msgs->next;
1274                 free(cur);
1275                 if (p->msgs) {
1276                         /* Send next pending message if appropriate */
1277                         p->messagepending = 1;
1278                         p->lastout = p->msgs->seqno;
1279                         __mgcp_xmit(p, p->msgs->buf, p->msgs->len);
1280                         /* XXX Should schedule retransmission XXX */
1281                 } else
1282                         p->messagepending = 0;
1283         } else {
1284                 ast_log(LOG_NOTICE, "Got response back on transaction %d we aren't sending? (current = %d)\n", ident, p->msgs ? p->msgs->seqno : -1);
1285         }
1286         if ((result >= 400) && (result <= 499)) {
1287                 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s\n", result, p->name, p->parent->name);
1288                 if (p->owner)
1289                         ast_softhangup(p->owner, AST_SOFTHANGUP_DEV);
1290         }
1291 }
1292
1293 static void start_rtp(struct mgcp_endpoint *p)
1294 {
1295                 ast_pthread_mutex_lock(&p->lock);
1296                 /* Allocate the RTP now */
1297                 p->rtp = ast_rtp_new(NULL, NULL);
1298                 if (p->rtp && p->owner)
1299                         p->owner->fds[0] = ast_rtp_fd(p->rtp);
1300                 if (p->rtp)
1301                         ast_rtp_setnat(p->rtp, p->nat);
1302 #if 0
1303                 ast_rtp_set_callback(p->rtp, rtpready);
1304                 ast_rtp_set_data(p->rtp, p);
1305 #endif          
1306                 /* Make a call*ID */
1307                 snprintf(p->callid, sizeof(p->callid), "%08x%s", rand(), p->txident);
1308                 /* Transmit the connection create */
1309                 transmit_connect_with_sdp(p, NULL);
1310                 ast_pthread_mutex_unlock(&p->lock);
1311 }
1312
1313 static void *mgcp_ss(void *data)
1314 {
1315         struct ast_channel *chan = data;
1316         struct mgcp_endpoint *p = chan->pvt->pvt;
1317         char exten[AST_MAX_EXTENSION] = "";
1318         int pos = 0;
1319         int to = 16000;
1320         int res;
1321         for (;;) {
1322                 res = ast_waitfordigit(chan, to);
1323                 if (!res) {
1324                         ast_log(LOG_DEBUG, "Timeout...\n");
1325                         break;
1326                 }
1327                 if (res < 0) {
1328                         ast_log(LOG_DEBUG, "Got hangup...\n");
1329                         break;
1330                 }
1331                 exten[pos++] = res;
1332                 if (!ast_ignore_pattern(chan->context, exten))
1333                         ast_indicate(chan, -1);
1334                 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
1335                         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
1336                                 to = 3000;
1337                         else
1338                                 to = 8000;
1339                 } else
1340                         break;
1341         }
1342         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
1343                 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
1344                 start_rtp(p);
1345                 ast_setstate(chan, AST_STATE_RING);
1346                 chan->rings = 1;
1347                 if (ast_pbx_run(chan)) {
1348                         ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
1349                 } else
1350                         return NULL;
1351         }
1352         ast_hangup(chan);
1353         return NULL;
1354 }
1355
1356 static int handle_request(struct mgcp_endpoint *p, struct mgcp_request *req, struct sockaddr_in *sin)
1357 {
1358         char *ev, *s;
1359         struct ast_channel *c;
1360         pthread_t t;
1361         struct ast_frame f = { 0, };
1362         if (mgcpdebug)
1363                 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
1364         /* Clear out potential response */
1365         if (!strcasecmp(req->verb, "RSIP")) {
1366                 dump_queue(p);
1367                 if (option_verbose > 2)
1368                         ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
1369                 if (p->owner)
1370                         ast_softhangup(p->owner, AST_SOFTHANGUP_DEV);
1371                 transmit_response(p, "200", req, "OK");
1372                 transmit_notify_request(p, "", 0);
1373         } else if (!strcasecmp(req->verb, "NTFY")) {
1374                 /* Acknowledge and be sure we keep looking for the same things */
1375                 transmit_response(p, "200", req, "OK");
1376                 /* Notified of an event */
1377                 ev = get_header(req, "O");
1378                 s = strchr(ev, '/');
1379                 if (s) ev = s + 1;
1380                 ast_log(LOG_DEBUG, "Endpoint '%s@%s' observed '%s'\n", p->name, p->parent->name, ev);
1381                 /* Keep looking for events unless this was a hangup */
1382                 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd"))
1383                         transmit_notify_request(p, p->curtone, 1);
1384                 if (!strcasecmp(ev, "hd")) {
1385                         /* Off hook / answer */
1386                         if (p->outgoing) {
1387                                 /* Answered */
1388                                 if (p->owner) {
1389                                         start_rtp(p);
1390                                         ast_queue_control(p->owner, AST_CONTROL_ANSWER, 1);
1391                                 }
1392                         } else {
1393                                 /* Start switch */
1394                                 if (!p->owner) {
1395                                         transmit_notify_request(p, "dl", 1);
1396                                         c = mgcp_new(p, AST_STATE_DOWN);
1397                                         if (c) {
1398                                                 if (pthread_create(&t, NULL, mgcp_ss, c)) {
1399                                                         ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
1400                                                         ast_hangup(c);
1401                                                 }
1402                                         } else
1403                                                 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
1404                                 } else {
1405                                         ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
1406                                 }
1407                         }
1408                 } else if (!strcasecmp(ev, "hu")) {
1409                         ast_log(LOG_DEBUG, "Went on hook\n");
1410                         if (p->owner) {
1411                                 p->alreadygone = 1;
1412                                 ast_queue_hangup(p->owner, 1);
1413                         }
1414                         transmit_notify_request(p, "", 0);
1415                 } else if ((strlen(ev) == 1) && 
1416                                         (((ev[0] >= '0') && (ev[0] <= '9')) ||
1417                                          ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
1418                                          (ev[0] == '*') || (ev[0] == '#'))) {
1419                         f.frametype = AST_FRAME_DTMF;
1420                         f.subclass = ev[0];
1421                         f.src = "mgcp";
1422                         if (p->owner)
1423                                 ast_queue_frame(p->owner, &f, 1);
1424                 } else if (!strcasecmp(ev, "T")) {
1425                         /* Digit timeout -- unimportant */
1426                 } else {
1427                         ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
1428                 }
1429         } else {
1430                 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, inet_ntoa(sin->sin_addr));
1431                 transmit_response(p, "510", req, "Unknown verb");
1432         }
1433         return 0;
1434 }
1435
1436 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
1437 {
1438         struct mgcp_request req;
1439         struct sockaddr_in sin;
1440         struct mgcp_endpoint *p;
1441         char *c;
1442         int res;
1443         int len;
1444         int result;
1445         int ident;
1446         len = sizeof(sin);
1447         memset(&req, 0, sizeof(req));
1448         res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
1449         if (res < 0) {
1450                 if (errno != ECONNREFUSED)
1451                         ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
1452                 return 1;
1453         }
1454         req.data[res] = '\0';
1455         req.len = res;
1456         if (mgcpdebug)
1457                 ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1458         parse(&req);
1459         if (req.headers < 1) {
1460                 /* Must have at least one header */
1461                 return 1;
1462         }
1463         if (!req.identifier || !strlen(req.identifier)) {
1464                 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", inet_ntoa(sin.sin_addr));
1465                 return 1;
1466         }
1467
1468         if (sscanf(req.verb, "%d", &result) &&
1469                 sscanf(req.identifier, "%d", &ident)) {
1470                 /* Try to find who this message is for, if it's important */
1471                 p = find_endpoint(NULL, ident, &sin);
1472                 if (p) {
1473                         handle_response(p, result, ident);
1474                         if ((c = get_header(&req, "I"))) {
1475                                 if (strlen(c)) {
1476                                         strncpy(p->cxident, c, sizeof(p->cxident) - 1);
1477                                         if (p->tmpdest.sin_addr.s_addr) {
1478                                                 transmit_modify_with_sdp(p, NULL);
1479                                         }
1480                                 }
1481                         }
1482                         if (req.lines) {
1483                                 if (!p->rtp) 
1484                                         start_rtp(p);
1485                                 if (p->rtp)
1486                                         process_sdp(p, &req);
1487                         }
1488                 }
1489         } else {
1490                 if (!req.endpoint || !strlen(req.endpoint) || 
1491                     !req.version || !strlen(req.version) || 
1492                         !req.verb || !strlen(req.verb)) {
1493                         ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
1494                         return 1;
1495                 }
1496                 /* Process request, with iflock held */
1497                 p = find_endpoint(req.endpoint, 0, &sin);
1498                 if (p) {
1499                         handle_request(p, &req, &sin);
1500                 }
1501         }
1502         return 1;
1503 }
1504
1505 static void *do_monitor(void *data)
1506 {
1507         int res;
1508         struct mgcp_pkt *p;
1509         sched = sched_context_create();
1510         if (!sched) {
1511                 ast_log(LOG_WARNING, "Unable to create schedule context\n");
1512                 return NULL;
1513         }
1514         io = io_context_create();
1515         if (!io) {
1516                 ast_log(LOG_WARNING, "Unable to create I/O context\n");
1517                 return NULL;
1518         }
1519         
1520         /* Add an I/O event to our UDP socket */
1521         if (mgcpsock > -1) 
1522                 ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
1523         
1524         /* This thread monitors all the frame relay interfaces which are not yet in use
1525            (and thus do not have a separate thread) indefinitely */
1526         /* From here on out, we die whenever asked */
1527         for(;;) {
1528                 /* Check for interfaces needing to be killed */
1529                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
1530                    and wait for the monitor list, but the other way around is okay. */
1531                 ast_pthread_mutex_lock(&monlock);
1532                 /* Lock the network interface */
1533                 ast_pthread_mutex_lock(&netlock);
1534                 p = packets;
1535                 while(p) {
1536                         /* Handle any retransmissions */
1537                         p = p->next;
1538                 }
1539                 /* Okay, now that we know what to do, release the network lock */
1540                 ast_pthread_mutex_unlock(&netlock);
1541                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
1542                 ast_pthread_mutex_unlock(&monlock);
1543                 pthread_testcancel();
1544                 /* Wait for sched or io */
1545                 res = ast_sched_wait(sched);
1546                 res = ast_io_wait(io, res);
1547                 ast_pthread_mutex_lock(&monlock);
1548                 if (res >= 0) 
1549                         ast_sched_runq(sched);
1550                 ast_pthread_mutex_unlock(&monlock);
1551         }
1552         /* Never reached */
1553         return NULL;
1554         
1555 }
1556
1557 static int restart_monitor(void)
1558 {
1559         /* If we're supposed to be stopped -- stay stopped */
1560         if (monitor_thread == -2)
1561                 return 0;
1562         if (ast_pthread_mutex_lock(&monlock)) {
1563                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
1564                 return -1;
1565         }
1566         if (monitor_thread == pthread_self()) {
1567                 ast_pthread_mutex_unlock(&monlock);
1568                 ast_log(LOG_WARNING, "Cannot kill myself\n");
1569                 return -1;
1570         }
1571         if (monitor_thread) {
1572                 /* Wake up the thread */
1573                 pthread_kill(monitor_thread, SIGURG);
1574         } else {
1575                 /* Start a new monitor */
1576                 if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
1577                         ast_pthread_mutex_unlock(&monlock);
1578                         ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
1579                         return -1;
1580                 }
1581         }
1582         ast_pthread_mutex_unlock(&monlock);
1583         return 0;
1584 }
1585
1586 static struct ast_channel *mgcp_request(char *type, int format, void *data)
1587 {
1588         int oldformat;
1589         struct mgcp_endpoint *p;
1590         struct ast_channel *tmpc = NULL;
1591         char tmp[256];
1592         char *dest = data;
1593
1594         oldformat = format;
1595         format &= capability;
1596         if (!format) {
1597                 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
1598                 return NULL;
1599         }
1600         strncpy(tmp, dest, sizeof(tmp) - 1);
1601         if (!strlen(tmp)) {
1602                 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
1603                 return NULL;
1604         }
1605         p = find_endpoint(tmp, 0, NULL);
1606         if (!p) {
1607                 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
1608                 return NULL;
1609         }
1610         
1611         /* Must be busy */
1612         if (p->owner)
1613                 return NULL;
1614         tmpc = mgcp_new(p, AST_STATE_DOWN);
1615         if (!tmpc)
1616                 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
1617         restart_monitor();
1618         return tmpc;
1619 }
1620
1621 struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
1622 {
1623         struct mgcp_gateway *gw;
1624         struct mgcp_endpoint *e;
1625         char context[AST_MAX_EXTENSION] = "default";
1626         char language[80] = "";
1627         char callerid[AST_MAX_EXTENSION] = "";
1628         int inbanddtmf = 0;
1629         int nat = 0;
1630
1631         gw = malloc(sizeof(struct mgcp_gateway));
1632         if (gw) {
1633                 memset(gw, 0, sizeof(struct mgcp_gateway));
1634                 gw->expire = -1;
1635                 strncpy(gw->name, cat, sizeof(gw->name) - 1);
1636                 while(v) {
1637                         if (!strcasecmp(v->name, "host")) {
1638                                 if (!strcasecmp(v->value, "dynamic")) {
1639                                         /* They'll register with us */
1640                                         gw->dynamic = 1;
1641                                         memset(&gw->addr.sin_addr, 0, 4);
1642                                         if (gw->addr.sin_port) {
1643                                                 /* If we've already got a port, make it the default rather than absolute */
1644                                                 gw->defaddr.sin_port = gw->addr.sin_port;
1645                                                 gw->addr.sin_port = 0;
1646                                         }
1647                                 } else {
1648                                         /* Non-dynamic.  Make sure we become that way if we're not */
1649                                         if (gw->expire > -1)
1650                                                 ast_sched_del(sched, gw->expire);
1651                                         gw->expire = -1;
1652                                         gw->dynamic = 0;
1653                                         if (ast_get_ip(&gw->addr, v->value)) {
1654                                                 free(gw);
1655                                                 return NULL;
1656                                         }
1657                                 }
1658                         } else if (!strcasecmp(v->name, "defaultip")) {
1659                                 if (ast_get_ip(&gw->defaddr, v->value)) {
1660                                         free(gw);
1661                                         return NULL;
1662                                 }
1663                         } else if (!strcasecmp(v->name, "permit") ||
1664                                            !strcasecmp(v->name, "deny")) {
1665                                 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
1666                         } else if (!strcasecmp(v->name, "port")) {
1667                                 gw->addr.sin_port = htons(atoi(v->value));
1668                         } else if (!strcasecmp(v->name, "context")) {
1669                                 strncpy(context, v->value, sizeof(context) - 1);
1670                         } else if (!strcasecmp(v->name, "inbanddtmf")) {
1671                                 inbanddtmf = atoi(v->value);
1672                         } else if (!strcasecmp(v->name, "nat")) {
1673                                 nat = ast_true(v->value);
1674                         } else if (!strcasecmp(v->name, "callerid")) {
1675                                 if (!strcasecmp(v->value, "asreceived"))
1676                                         strcpy(callerid, "");
1677                                 else
1678                                         strncpy(callerid, v->value, sizeof(callerid) - 1);
1679                         } else if (!strcasecmp(v->name, "language")) {
1680                                 strncpy(language, v->value, sizeof(language)-1);
1681                         } else if (!strcasecmp(v->name, "trunk") ||
1682                                    !strcasecmp(v->name, "line")) {
1683                                 e = malloc(sizeof(struct mgcp_endpoint));
1684                                 if (e) {
1685                                         memset(e, 0, sizeof(struct mgcp_endpoint));
1686                                         /* XXX Should we really check for uniqueness?? XXX */
1687                                         snprintf(e->txident, sizeof(e->txident), "%08x", rand());
1688                                         strncpy(e->context, context, sizeof(e->context) - 1);
1689                                         strncpy(e->callerid, callerid, sizeof(e->callerid) - 1);
1690                                         strncpy(e->language, language, sizeof(e->language) - 1);
1691                                         e->capability = capability;
1692                                         e->parent = gw;
1693                                         e->dtmfinband = inbanddtmf;
1694                                         e->nat = nat;
1695                                         strncpy(e->name, v->value, sizeof(e->name) - 1);
1696                                         if (!strcasecmp(v->name, "trunk"))
1697                                                 e->type = TYPE_TRUNK;
1698                                         else
1699                                                 e->type = TYPE_LINE;
1700                                         e->next = gw->endpoints;
1701                                         gw->endpoints = e;
1702                                 }
1703                         } else
1704                                 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
1705                         v = v->next;
1706                 }
1707                 
1708         }
1709
1710         if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
1711                 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
1712                 free(gw);
1713                 return NULL;
1714         }
1715         if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 
1716                 gw->defaddr.sin_port = htons(DEFAULT_MGCP_PORT);
1717         if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
1718                 gw->addr.sin_port = htons(DEFAULT_MGCP_PORT);
1719         if (gw->addr.sin_addr.s_addr)
1720                 memcpy(&gw->ourip, myaddrfor(&gw->addr.sin_addr), sizeof(gw->ourip));
1721         return gw;
1722 }
1723
1724 static struct ast_rtp *mgcp_get_rtp_peer(struct ast_channel *chan)
1725 {
1726         struct mgcp_endpoint *p;
1727         p = chan->pvt->pvt;
1728         if (p && p->rtp)
1729                 return p->rtp;
1730         return NULL;
1731 }
1732
1733 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp)
1734 {
1735         struct mgcp_endpoint *p;
1736         p = chan->pvt->pvt;
1737         if (p) {
1738                 transmit_modify_with_sdp(p, rtp);
1739                 return 0;
1740         }
1741         return -1;
1742 }
1743
1744 static struct ast_rtp_protocol mgcp_rtp = {
1745         get_rtp_info: mgcp_get_rtp_peer,
1746         set_rtp_peer: mgcp_set_rtp_peer,
1747 };
1748
1749 static int mgcp_do_debug(int fd, int argc, char *argv[])
1750 {
1751         if (argc != 2)
1752                 return RESULT_SHOWUSAGE;
1753         mgcpdebug = 1;
1754         ast_cli(fd, "MGCP Debugging Enabled\n");
1755         return RESULT_SUCCESS;
1756 }
1757
1758 static int mgcp_no_debug(int fd, int argc, char *argv[])
1759 {
1760         if (argc != 3)
1761                 return RESULT_SHOWUSAGE;
1762         mgcpdebug = 0;
1763         ast_cli(fd, "MGCP Debugging Disabled\n");
1764         return RESULT_SUCCESS;
1765 }
1766
1767 static char debug_usage[] = 
1768 "Usage: mgcp debug\n"
1769 "       Enables dumping of MGCP packets for debugging purposes\n";
1770
1771 static char no_debug_usage[] = 
1772 "Usage: mgcp no debug\n"
1773 "       Disables dumping of MGCP packets for debugging purposes\n";
1774
1775 static struct ast_cli_entry  cli_debug =
1776         { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage };
1777 static struct ast_cli_entry  cli_no_debug =
1778         { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage };
1779
1780
1781 int load_module()
1782 {
1783         struct ast_config *cfg;
1784         struct ast_variable *v;
1785         struct mgcp_gateway *g;
1786         char *cat;
1787         struct hostent *hp;
1788         int format;
1789         
1790         if (gethostname(ourhost, sizeof(ourhost))) {
1791                 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
1792                 return 0;
1793         }
1794         cfg = ast_load(config);
1795
1796         /* We *must* have a config file otherwise stop immediately */
1797         if (!cfg) {
1798                 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
1799                 return 0;
1800         }
1801         memset(&bindaddr, 0, sizeof(bindaddr));
1802         v = ast_variable_browse(cfg, "general");
1803         while(v) {
1804                 /* Create the interface list */
1805                 if (!strcasecmp(v->name, "bindaddr")) {
1806                         if (!(hp = gethostbyname(v->value))) {
1807                                 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
1808                         } else {
1809                                 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
1810                         }
1811                 } else if (!strcasecmp(v->name, "allow")) {
1812                         format = ast_getformatbyname(v->value);
1813                         if (format < 1) 
1814                                 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
1815                         else
1816                                 capability |= format;
1817                 } else if (!strcasecmp(v->name, "disallow")) {
1818                         format = ast_getformatbyname(v->value);
1819                         if (format < 1) 
1820                                 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
1821                         else
1822                                 capability &= ~format;
1823                 } else if (!strcasecmp(v->name, "port")) {
1824                         if (sscanf(v->value, "%i", &ourport) == 1) {
1825                                 bindaddr.sin_port = htons(ourport);
1826                         } else {
1827                                 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
1828                         }
1829                 }
1830                 v = v->next;
1831         }
1832         
1833         cat = ast_category_browse(cfg, NULL);
1834         while(cat) {
1835                 if (strcasecmp(cat, "general")) {
1836                         g = build_gateway(cat, ast_variable_browse(cfg, cat));
1837                         if (g) {
1838                                 if (option_verbose > 2)
1839                                         ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
1840                                 ast_pthread_mutex_lock(&gatelock);
1841                                 g->next = gateways;
1842                                 gateways = g;
1843                                 ast_pthread_mutex_unlock(&gatelock);
1844                         }
1845                 }
1846                 cat = ast_category_browse(cfg, cat);
1847         }
1848         
1849         if (ntohl(bindaddr.sin_addr.s_addr)) {
1850                 memcpy(&__ourip, &bindaddr, sizeof(__ourip));
1851         } else {
1852                 hp = gethostbyname(ourhost);
1853                 if (!hp) {
1854                         ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
1855                         return 0;
1856                 }
1857                 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
1858         }
1859         if (!ntohs(bindaddr.sin_port))
1860                 bindaddr.sin_port = ntohs(DEFAULT_MGCP_PORT);
1861         bindaddr.sin_family = AF_INET;
1862         pthread_mutex_lock(&netlock);
1863         if (mgcpsock > -1)
1864                 close(mgcpsock);
1865         mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
1866         if (mgcpsock < 0) {
1867                 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
1868         } else {
1869                 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
1870                         ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
1871                                         inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
1872                                                 strerror(errno));
1873                         close(mgcpsock);
1874                         mgcpsock = -1;
1875                 } else if (option_verbose > 1)
1876                         ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n", 
1877                                 inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
1878         }
1879         pthread_mutex_unlock(&netlock);
1880         ast_destroy(cfg);
1881
1882         /* Make sure we can register our mgcp channel type */
1883         if (ast_channel_register(type, tdesc, capability, mgcp_request)) {
1884                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
1885                 ast_destroy(cfg);
1886                 return -1;
1887         }
1888         mgcp_rtp.type = type;
1889         ast_rtp_proto_register(&mgcp_rtp);
1890         ast_cli_register(&cli_show_endpoints);
1891         ast_cli_register(&cli_debug);
1892         ast_cli_register(&cli_no_debug);
1893         /* And start the monitor for the first time */
1894         restart_monitor();
1895         return 0;
1896 }
1897
1898 int unload_module()
1899 {
1900 #if 0
1901         struct mgcp_endpoint *p, *pl;
1902         /* First, take us out of the channel loop */
1903         ast_channel_unregister(type);
1904         if (!ast_pthread_mutex_lock(&gatelock)) {
1905                 /* Hangup all interfaces if they have an owner */
1906                 p = iflist;
1907                 while(p) {
1908                         if (p->owner)
1909                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
1910                         p = p->next;
1911                 }
1912                 iflist = NULL;
1913                 ast_pthread_mutex_unlock(&iflock);
1914         } else {
1915                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1916                 return -1;
1917         }
1918         if (!ast_pthread_mutex_lock(&monlock)) {
1919                 if (monitor_thread) {
1920                         pthread_cancel(monitor_thread);
1921                         pthread_kill(monitor_thread, SIGURG);
1922                         pthread_join(monitor_thread, NULL);
1923                 }
1924                 monitor_thread = -2;
1925                 ast_pthread_mutex_unlock(&monlock);
1926         } else {
1927                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1928                 return -1;
1929         }
1930
1931         if (!ast_pthread_mutex_lock(&iflock)) {
1932                 /* Destroy all the interfaces and free their memory */
1933                 p = iflist;
1934                 while(p) {
1935                         pl = p;
1936                         p = p->next;
1937                         /* Free associated memory */
1938                         free(pl);
1939                 }
1940                 iflist = NULL;
1941                 ast_pthread_mutex_unlock(&iflock);
1942         } else {
1943                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1944                 return -1;
1945         }
1946 #endif          
1947         return -1;
1948 }
1949
1950 int usecount()
1951 {
1952         int res;
1953         ast_pthread_mutex_lock(&usecnt_lock);
1954         res = usecnt;
1955         ast_pthread_mutex_unlock(&usecnt_lock);
1956         return res;
1957 }
1958
1959 char *key()
1960 {
1961         return ASTERISK_GPL_KEY;
1962 }
1963
1964 char *description()
1965 {
1966         return desc;
1967 }
1968