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