Wed Mar 12 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         rtp_pt_init(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                 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           int subtypeLen, i;
887           if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
888           // Note: should really look at the 'freq' and '#chans' params too
889           subtypeLen = strlen(mimeSubtype);
890           // Convert the MIME subtype to upper case, for ease of searching:
891           for (i = 0; i < subtypeLen; ++i) {
892             mimeSubtype[i] = toupper(mimeSubtype[i]);
893           }
894           rtp_set_rtpmap_type(p->rtp, codec, "audio", mimeSubtype);
895           free(mimeSubtype);
896         }
897
898         // Now gather all of the codecs that were asked for:
899         rtp_get_current_formats(p->rtp,
900                                 &peercapability, &peerNonCodecCapability);
901         p->capability = capability & peercapability;
902         if (mgcpdebug) {
903                 ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
904                 capability, peercapability, p->capability);
905                 ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
906                             nonCodecCapability, peerNonCodecCapability,
907                             p->nonCodecCapability);
908         }
909         if (!p->capability) {
910                 ast_log(LOG_WARNING, "No compatible codecs!\n");
911                 return -1;
912         }
913         return 0;
914         
915 }
916
917 static int add_header(struct mgcp_request *req, char *var, char *value)
918 {
919         if (req->len >= sizeof(req->data) - 4) {
920                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
921                 return -1;
922         }
923         if (req->lines) {
924                 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
925                 return -1;
926         }
927         req->header[req->headers] = req->data + req->len;
928         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
929         req->len += strlen(req->header[req->headers]);
930         if (req->headers < MGCP_MAX_HEADERS)
931                 req->headers++;
932         else {
933                 ast_log(LOG_WARNING, "Out of header space\n");
934                 return -1;
935         }
936         return 0;       
937 }
938
939 static int add_line(struct mgcp_request *req, char *line)
940 {
941         if (req->len >= sizeof(req->data) - 4) {
942                 ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
943                 return -1;
944         }
945         if (!req->lines) {
946                 /* Add extra empty return */
947                 snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
948                 req->len += strlen(req->data + req->len);
949         }
950         req->line[req->lines] = req->data + req->len;
951         snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
952         req->len += strlen(req->line[req->lines]);
953         if (req->lines < MGCP_MAX_LINES)
954                 req->lines++;
955         else {
956                 ast_log(LOG_WARNING, "Out of line space\n");
957                 return -1;
958         }
959         return 0;       
960 }
961
962 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
963 {
964         /* Initialize a response */
965         if (req->headers || req->len) {
966                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
967                 return -1;
968         }
969         req->header[req->headers] = req->data + req->len;
970         snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
971         req->len += strlen(req->header[req->headers]);
972         if (req->headers < MGCP_MAX_HEADERS)
973                 req->headers++;
974         else
975                 ast_log(LOG_WARNING, "Out of header space\n");
976         return 0;
977 }
978
979 static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *verb)
980 {
981         /* Initialize a response */
982         if (req->headers || req->len) {
983                 ast_log(LOG_WARNING, "Request already initialized?!?\n");
984                 return -1;
985         }
986         req->header[req->headers] = req->data + req->len;
987         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);
988         req->len += strlen(req->header[req->headers]);
989         if (req->headers < MGCP_MAX_HEADERS)
990                 req->headers++;
991         else
992                 ast_log(LOG_WARNING, "Out of header space\n");
993         return 0;
994 }
995
996
997 static int respprep(struct mgcp_request *resp, struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
998 {
999         memset(resp, 0, sizeof(*resp));
1000         init_resp(resp, msg, req, msgrest);
1001         return 0;
1002 }
1003
1004 static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb)
1005 {
1006         memset(req, 0, sizeof(struct mgcp_request));
1007         oseq++;
1008         init_req(p, req, verb);
1009         return 0;
1010 }
1011
1012 static int transmit_response(struct mgcp_endpoint *p, char *msg, struct mgcp_request *req, char *msgrest)
1013 {
1014         struct mgcp_request resp;
1015         respprep(&resp, p, msg, req, msgrest);
1016         return send_response(p, &resp);
1017 }
1018
1019
1020 static int add_sdp(struct mgcp_request *resp, struct mgcp_endpoint *p, struct ast_rtp *rtp)
1021 {
1022         int len;
1023         int codec;
1024         char costr[80];
1025         struct sockaddr_in sin;
1026         char v[256];
1027         char s[256];
1028         char o[256];
1029         char c[256];
1030         char t[256];
1031         char m[256];
1032         char a[1024] = "";
1033         int x;
1034         struct sockaddr_in dest;
1035         /* XXX We break with the "recommendation" and send our IP, in order that our
1036                peer doesn't have to gethostbyname() us XXX */
1037         len = 0;
1038         if (!p->rtp) {
1039                 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
1040                 return -1;
1041         }
1042         ast_rtp_get_us(p->rtp, &sin);
1043         if (rtp) {
1044                 ast_rtp_get_peer(rtp, &dest);
1045         } else {
1046                 if (p->tmpdest.sin_addr.s_addr) {
1047                         dest.sin_addr = p->tmpdest.sin_addr;
1048                         dest.sin_port = p->tmpdest.sin_port;
1049                         /* Reset temporary destination */
1050                         memset(&p->tmpdest, 0, sizeof(p->tmpdest));
1051                 } else {
1052                         dest.sin_addr = p->parent->ourip;
1053                         dest.sin_port = sin.sin_port;
1054                 }
1055         }
1056         if (mgcpdebug)
1057                 ast_verbose("We're at %s port %d\n", inet_ntoa(p->parent->ourip), ntohs(sin.sin_port)); 
1058         snprintf(v, sizeof(v), "v=0\r\n");
1059         snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
1060         snprintf(s, sizeof(s), "s=session\r\n");
1061         snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", inet_ntoa(dest.sin_addr));
1062         snprintf(t, sizeof(t), "t=0 0\r\n");
1063         snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
1064         for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1065                 if (p->capability & x) {
1066                         if (mgcpdebug)
1067                                 ast_verbose("Answering with capability %d\n", x);
1068                         codec = rtp_lookup_code(p->rtp, 1, x);
1069                         if (codec > -1) {
1070                                 snprintf(costr, sizeof(costr), " %d", codec);
1071                                 strcat(m, costr);
1072                                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, rtp_lookup_mime_subtype(1, x));
1073                                 strcat(a, costr);
1074                         }
1075                 }
1076         }
1077         for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
1078                 if (p->nonCodecCapability & x) {
1079                         if (mgcpdebug)
1080                                 ast_verbose("Answering with non-codec capability %d\n", x);
1081                         codec = rtp_lookup_code(p->rtp, 0, x);
1082                         if (codec > -1) {
1083                                 snprintf(costr, sizeof(costr), " %d", codec);
1084                                 strcat(m, costr);
1085                                 snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, rtp_lookup_mime_subtype(0, x));
1086                                 strcat(a, costr);
1087                                 if (x == AST_RTP_DTMF) {
1088                                   /* Indicate we support DTMF...  Not sure about 16, but MSN supports it so dang it, we will too... */
1089                                   snprintf(costr, sizeof costr, "a=fmtp:%d 0-16\r\n",
1090                                            codec);
1091                                   strcat(a, costr);
1092                                 }
1093                         }
1094                 }
1095         }
1096         strcat(m, "\r\n");
1097         len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
1098         snprintf(costr, sizeof(costr), "%d", len);
1099         add_line(resp, v);
1100         add_line(resp, o);
1101         add_line(resp, s);
1102         add_line(resp, c);
1103         add_line(resp, t);
1104         add_line(resp, m);
1105         add_line(resp, a);
1106         return 0;
1107 }
1108
1109 static int transmit_modify_with_sdp(struct mgcp_endpoint *p, struct ast_rtp *rtp)
1110 {
1111         struct mgcp_request resp;
1112         char local[256];
1113         char tmp[80];
1114         int x;
1115         if (!strlen(p->cxident) && rtp) {
1116                 /* We don't have a CXident yet, store the destination and
1117                    wait a bit */
1118                 ast_rtp_get_peer(rtp, &p->tmpdest);
1119                 return 0;
1120         }
1121         snprintf(local, sizeof(local), "p:20");
1122         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1123                 if (p->capability & x) {
1124                         snprintf(tmp, sizeof(tmp), ", a:%s", rtp_lookup_mime_subtype(1, x));
1125                         strcat(local, tmp);
1126                 }
1127         }
1128         reqprep(&resp, p, "MDCX");
1129         add_header(&resp, "C", p->callid);
1130         add_header(&resp, "L", local);
1131         add_header(&resp, "M", "sendrecv");
1132         add_header(&resp, "X", p->txident);
1133         add_header(&resp, "I", p->cxident);
1134         add_header(&resp, "S", "");
1135         add_sdp(&resp, p, rtp);
1136         p->lastout = oseq;
1137         return send_request(p, &resp);
1138 }
1139
1140 static int transmit_connect_with_sdp(struct mgcp_endpoint *p, struct ast_rtp *rtp)
1141 {
1142         struct mgcp_request resp;
1143         char local[256];
1144         char tmp[80];
1145         int x;
1146         snprintf(local, sizeof(local), "p:20");
1147         for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
1148                 if (p->capability & x) {
1149                         snprintf(tmp, sizeof(tmp), ", a:%s", rtp_lookup_mime_subtype(1, x));
1150                         strcat(local, tmp);
1151                 }
1152         }
1153         reqprep(&resp, p, "CRCX");
1154         add_header(&resp, "C", p->callid);
1155         add_header(&resp, "L", local);
1156         add_header(&resp, "M", "sendrecv");
1157         add_header(&resp, "X", p->txident);
1158         add_header(&resp, "S", "");
1159         add_sdp(&resp, p, rtp);
1160         p->lastout = oseq;
1161         return send_request(p, &resp);
1162 }
1163
1164 static int transmit_notify_request(struct mgcp_endpoint *p, char *tone, int offhook)
1165 {
1166         struct mgcp_request resp;
1167         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1168         reqprep(&resp, p, "RQNT");
1169         add_header(&resp, "X", p->txident);
1170         if (offhook)
1171                 add_header(&resp, "R", "hu(N), hf(N), D/[0-9#*](N)");
1172         else
1173                 add_header(&resp, "R", "hd(N)");
1174         add_header(&resp, "S", tone);
1175         return send_request(p, &resp);
1176 }
1177
1178 static int transmit_notify_request_with_callerid(struct mgcp_endpoint *p, char *tone, int offhook, char *callerid)
1179 {
1180         struct mgcp_request resp;
1181         char cid[256];
1182         char tone2[256];
1183         char *l, *n;
1184         time_t t;
1185         struct tm *tm;
1186         
1187         time(&t);
1188         tm = localtime(&t);
1189         if (callerid)
1190                 strncpy(cid, callerid, sizeof(cid) - 1);
1191         else
1192                 strcpy(cid, "");
1193         ast_callerid_parse(cid, &n, &l);
1194         if (l) {
1195                 ast_shrink_phone_number(l);
1196                 if (!ast_isphonenumber(l)) {
1197                         n = l;
1198                         l = "";
1199                 }
1200         } 
1201         if (!n)
1202                 n = "O";
1203         if (!l)
1204                 l = "";
1205         snprintf(tone2, sizeof(tone2), "%s, ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
1206                         tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, l, n);
1207         strncpy(p->curtone, tone, sizeof(p->curtone) - 1);
1208         reqprep(&resp, p, "RQNT");
1209         add_header(&resp, "X", p->txident);
1210         if (offhook)
1211                 add_header(&resp, "R", "hu(N), hf(N), D/[0-9#*](N)");
1212         else
1213                 add_header(&resp, "R", "hd(N)");
1214         add_header(&resp, "S", tone2);
1215         return send_request(p, &resp);
1216 }
1217 static int transmit_connection_del(struct mgcp_endpoint *p)
1218 {
1219         struct mgcp_request resp;
1220         reqprep(&resp, p, "DLCX");
1221         add_header(&resp, "C", p->callid);
1222         add_header(&resp, "I", p->cxident);
1223         return send_request(p, &resp);
1224 }
1225
1226 static void handle_response(struct mgcp_endpoint *p, int result, int ident)
1227 {
1228         if ((result >= 400) && (result <= 499)) {
1229                 ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s\n", result, p->name, p->parent->name);
1230                 if (p->owner)
1231                         ast_softhangup(p->owner, AST_SOFTHANGUP_DEV);
1232         }
1233 }
1234
1235 static void start_rtp(struct mgcp_endpoint *p)
1236 {
1237                 ast_pthread_mutex_lock(&p->lock);
1238                 /* Allocate the RTP now */
1239                 p->rtp = ast_rtp_new(NULL, NULL);
1240                 if (p->rtp && p->owner)
1241                         p->owner->fds[0] = ast_rtp_fd(p->rtp);
1242                 if (p->rtp)
1243                         ast_rtp_setnat(p->rtp, p->nat);
1244 #if 0
1245                 ast_rtp_set_callback(p->rtp, rtpready);
1246                 ast_rtp_set_data(p->rtp, p);
1247 #endif          
1248                 /* Make a call*ID */
1249                 snprintf(p->callid, sizeof(p->callid), "%08x%s", rand(), p->txident);
1250                 /* Transmit the connection create */
1251                 transmit_connect_with_sdp(p, NULL);
1252                 ast_pthread_mutex_unlock(&p->lock);
1253 }
1254
1255 static void *mgcp_ss(void *data)
1256 {
1257         struct ast_channel *chan = data;
1258         struct mgcp_endpoint *p = chan->pvt->pvt;
1259         char exten[AST_MAX_EXTENSION] = "";
1260         int pos = 0;
1261         int to = 16000;
1262         int res;
1263         for (;;) {
1264                 res = ast_waitfordigit(chan, to);
1265                 if (!res) {
1266                         ast_log(LOG_DEBUG, "Timeout...\n");
1267                         break;
1268                 }
1269                 if (res < 0) {
1270                         ast_log(LOG_DEBUG, "Got hangup...\n");
1271                         break;
1272                 }
1273                 exten[pos++] = res;
1274                 if (!ast_ignore_pattern(chan->context, exten))
1275                         ast_indicate(chan, -1);
1276                 if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
1277                         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
1278                                 to = 3000;
1279                         else
1280                                 to = 8000;
1281                 } else
1282                         break;
1283         }
1284         if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) {
1285                 strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
1286                 start_rtp(p);
1287                 ast_setstate(chan, AST_STATE_RING);
1288                 chan->rings = 1;
1289                 if (ast_pbx_run(chan)) {
1290                         ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
1291                 } else
1292                         return NULL;
1293         }
1294         ast_hangup(chan);
1295         return NULL;
1296 }
1297
1298 static int handle_request(struct mgcp_endpoint *p, struct mgcp_request *req, struct sockaddr_in *sin)
1299 {
1300         char *ev, *s;
1301         struct ast_channel *c;
1302         pthread_t t;
1303         struct ast_frame f = { 0, };
1304         if (mgcpdebug)
1305                 ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
1306         /* Clear out potential response */
1307         if (!strcasecmp(req->verb, "RSIP")) {
1308                 if (option_verbose > 2)
1309                         ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
1310                 if (p->owner)
1311                         ast_softhangup(p->owner, AST_SOFTHANGUP_DEV);
1312                 transmit_response(p, "200", req, "OK");
1313         } else if (!strcasecmp(req->verb, "NTFY")) {
1314                 /* Acknowledge and be sure we keep looking for the same things */
1315                 transmit_response(p, "200", req, "OK");
1316                 /* Notified of an event */
1317                 ev = get_header(req, "O");
1318                 s = strchr(ev, '/');
1319                 if (s) ev = s + 1;
1320                 ast_log(LOG_DEBUG, "Endpoint '%s@%s' observed '%s'\n", p->name, p->parent->name, ev);
1321                 /* Keep looking for events unless this was a hangup */
1322                 if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd"))
1323                         transmit_notify_request(p, p->curtone, 1);
1324                 if (!strcasecmp(ev, "hd")) {
1325                         /* Off hook / answer */
1326                         if (p->outgoing) {
1327                                 /* Answered */
1328                                 if (p->owner) {
1329                                         start_rtp(p);
1330                                         ast_queue_control(p->owner, AST_CONTROL_ANSWER, 1);
1331                                 }
1332                         } else {
1333                                 /* Start switch */
1334                                 if (!p->owner) {
1335                                         transmit_notify_request(p, "dl", 1);
1336                                         c = mgcp_new(p, AST_STATE_DOWN);
1337                                         if (c) {
1338                                                 if (pthread_create(&t, NULL, mgcp_ss, c)) {
1339                                                         ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
1340                                                         ast_hangup(c);
1341                                                 }
1342                                         } else
1343                                                 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", p->name, p->parent->name);
1344                                 } else {
1345                                         ast_log(LOG_WARNING, "Off hook, but alreaedy have owner on %s@%s\n", p->name, p->parent->name);
1346                                 }
1347                         }
1348                 } else if (!strcasecmp(ev, "hu")) {
1349                         ast_log(LOG_DEBUG, "Went on hook\n");
1350                         if (p->owner) {
1351                                 p->alreadygone = 1;
1352                                 ast_queue_hangup(p->owner, 1);
1353                         }
1354                 } else if ((strlen(ev) == 1) && 
1355                                         (((ev[0] >= '0') && (ev[0] <= '9')) ||
1356                                          ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
1357                                          (ev[0] == '*') || (ev[0] == '#'))) {
1358                         f.frametype = AST_FRAME_DTMF;
1359                         f.subclass = ev[0];
1360                         f.src = "mgcp";
1361                         if (p->owner)
1362                                 ast_queue_frame(p->owner, &f, 1);
1363                 } else if (!strcasecmp(ev, "T")) {
1364                         /* Digit timeout -- unimportant */
1365                 } else {
1366                         ast_log(LOG_NOTICE, "Received unknown event '%s' from %s@%s\n", ev, p->name, p->parent->name);
1367                 }
1368         } else {
1369                 ast_log(LOG_WARNING, "Unknown verb '%s' received from %s\n", req->verb, inet_ntoa(sin->sin_addr));
1370                 transmit_response(p, "510", req, "Unknown verb");
1371         }
1372         return 0;
1373 }
1374
1375 static int mgcpsock_read(int *id, int fd, short events, void *ignore)
1376 {
1377         struct mgcp_request req;
1378         struct sockaddr_in sin;
1379         struct mgcp_endpoint *p;
1380         char *c;
1381         int res;
1382         int len;
1383         int result;
1384         int ident;
1385         len = sizeof(sin);
1386         memset(&req, 0, sizeof(req));
1387         res = recvfrom(mgcpsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
1388         if (res < 0) {
1389                 if (errno != ECONNREFUSED)
1390                         ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno));
1391                 return 1;
1392         }
1393         req.data[res] = '\0';
1394         req.len = res;
1395         if (mgcpdebug)
1396                 ast_verbose("MGCP read: \n%s\nfrom %s:%d", req.data, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1397         parse(&req);
1398         if (req.headers < 1) {
1399                 /* Must have at least one header */
1400                 return 1;
1401         }
1402         if (!req.identifier || !strlen(req.identifier)) {
1403                 ast_log(LOG_NOTICE, "Message from %s missing identifier\n", inet_ntoa(sin.sin_addr));
1404                 return 1;
1405         }
1406
1407         if (sscanf(req.verb, "%d", &result) &&
1408                 sscanf(req.identifier, "%d", &ident)) {
1409                 /* Try to find who this message is for, if it's important */
1410                 p = find_endpoint(NULL, ident, &sin);
1411                 if (p) {
1412                         handle_response(p, result, ident);
1413                         if ((c = get_header(&req, "I"))) {
1414                                 if (strlen(c)) {
1415                                         strncpy(p->cxident, c, sizeof(p->cxident) - 1);
1416                                         if (p->tmpdest.sin_addr.s_addr) {
1417                                                 transmit_modify_with_sdp(p, NULL);
1418                                         }
1419                                 }
1420                         }
1421                         if (req.lines)
1422                                 process_sdp(p, &req);
1423                 }
1424         } else {
1425                 if (!req.endpoint || !strlen(req.endpoint) || 
1426                     !req.version || !strlen(req.version) || 
1427                         !req.verb || !strlen(req.verb)) {
1428                         ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
1429                         return 1;
1430                 }
1431                 /* Process request, with iflock held */
1432                 p = find_endpoint(req.endpoint, 0, &sin);
1433                 if (p) {
1434                         handle_request(p, &req, &sin);
1435                 }
1436         }
1437         return 1;
1438 }
1439
1440 static void *do_monitor(void *data)
1441 {
1442         int res;
1443         struct mgcp_pkt *p;
1444         sched = sched_context_create();
1445         if (!sched) {
1446                 ast_log(LOG_WARNING, "Unable to create schedule context\n");
1447                 return NULL;
1448         }
1449         io = io_context_create();
1450         if (!io) {
1451                 ast_log(LOG_WARNING, "Unable to create I/O context\n");
1452                 return NULL;
1453         }
1454         
1455         /* Add an I/O event to our UDP socket */
1456         if (mgcpsock > -1) 
1457                 ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
1458         
1459         /* This thread monitors all the frame relay interfaces which are not yet in use
1460            (and thus do not have a separate thread) indefinitely */
1461         /* From here on out, we die whenever asked */
1462         for(;;) {
1463                 /* Check for interfaces needing to be killed */
1464                 /* Don't let anybody kill us right away.  Nobody should lock the interface list
1465                    and wait for the monitor list, but the other way around is okay. */
1466                 ast_pthread_mutex_lock(&monlock);
1467                 /* Lock the network interface */
1468                 ast_pthread_mutex_lock(&netlock);
1469                 p = packets;
1470                 while(p) {
1471                         /* Handle any retransmissions */
1472                         p = p->next;
1473                 }
1474                 /* Okay, now that we know what to do, release the network lock */
1475                 ast_pthread_mutex_unlock(&netlock);
1476                 /* And from now on, we're okay to be killed, so release the monitor lock as well */
1477                 ast_pthread_mutex_unlock(&monlock);
1478                 pthread_testcancel();
1479                 /* Wait for sched or io */
1480                 res = ast_sched_wait(sched);
1481                 res = ast_io_wait(io, res);
1482                 ast_pthread_mutex_lock(&monlock);
1483                 if (res >= 0) 
1484                         ast_sched_runq(sched);
1485                 ast_pthread_mutex_unlock(&monlock);
1486         }
1487         /* Never reached */
1488         return NULL;
1489         
1490 }
1491
1492 static int restart_monitor(void)
1493 {
1494         /* If we're supposed to be stopped -- stay stopped */
1495         if (monitor_thread == -2)
1496                 return 0;
1497         if (ast_pthread_mutex_lock(&monlock)) {
1498                 ast_log(LOG_WARNING, "Unable to lock monitor\n");
1499                 return -1;
1500         }
1501         if (monitor_thread == pthread_self()) {
1502                 ast_pthread_mutex_unlock(&monlock);
1503                 ast_log(LOG_WARNING, "Cannot kill myself\n");
1504                 return -1;
1505         }
1506         if (monitor_thread) {
1507                 /* Wake up the thread */
1508                 pthread_kill(monitor_thread, SIGURG);
1509         } else {
1510                 /* Start a new monitor */
1511                 if (pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
1512                         ast_pthread_mutex_unlock(&monlock);
1513                         ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
1514                         return -1;
1515                 }
1516         }
1517         ast_pthread_mutex_unlock(&monlock);
1518         return 0;
1519 }
1520
1521 static struct ast_channel *mgcp_request(char *type, int format, void *data)
1522 {
1523         int oldformat;
1524         struct mgcp_endpoint *p;
1525         struct ast_channel *tmpc = NULL;
1526         char tmp[256];
1527         char *dest = data;
1528
1529         oldformat = format;
1530         format &= capability;
1531         if (!format) {
1532                 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
1533                 return NULL;
1534         }
1535         strncpy(tmp, dest, sizeof(tmp) - 1);
1536         if (!strlen(tmp)) {
1537                 ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
1538                 return NULL;
1539         }
1540         p = find_endpoint(tmp, 0, NULL);
1541         if (!p) {
1542                 ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
1543                 return NULL;
1544         }
1545         
1546         /* Must be busy */
1547         if (p->owner)
1548                 return NULL;
1549         tmpc = mgcp_new(p, AST_STATE_DOWN);
1550         if (!tmpc)
1551                 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
1552         restart_monitor();
1553         return tmpc;
1554 }
1555
1556 struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
1557 {
1558         struct mgcp_gateway *gw;
1559         struct mgcp_endpoint *e;
1560         char context[AST_MAX_EXTENSION] = "default";
1561         char language[80] = "";
1562         char callerid[AST_MAX_EXTENSION] = "";
1563         int inbanddtmf = 0;
1564         int nat = 0;
1565
1566         gw = malloc(sizeof(struct mgcp_gateway));
1567         if (gw) {
1568                 memset(gw, 0, sizeof(struct mgcp_gateway));
1569                 gw->expire = -1;
1570                 strncpy(gw->name, cat, sizeof(gw->name) - 1);
1571                 while(v) {
1572                         if (!strcasecmp(v->name, "host")) {
1573                                 if (!strcasecmp(v->value, "dynamic")) {
1574                                         /* They'll register with us */
1575                                         gw->dynamic = 1;
1576                                         memset(&gw->addr.sin_addr, 0, 4);
1577                                         if (gw->addr.sin_port) {
1578                                                 /* If we've already got a port, make it the default rather than absolute */
1579                                                 gw->defaddr.sin_port = gw->addr.sin_port;
1580                                                 gw->addr.sin_port = 0;
1581                                         }
1582                                 } else {
1583                                         /* Non-dynamic.  Make sure we become that way if we're not */
1584                                         if (gw->expire > -1)
1585                                                 ast_sched_del(sched, gw->expire);
1586                                         gw->expire = -1;
1587                                         gw->dynamic = 0;
1588                                         if (ast_get_ip(&gw->addr, v->value)) {
1589                                                 free(gw);
1590                                                 return NULL;
1591                                         }
1592                                 }
1593                         } else if (!strcasecmp(v->name, "defaultip")) {
1594                                 if (ast_get_ip(&gw->defaddr, v->value)) {
1595                                         free(gw);
1596                                         return NULL;
1597                                 }
1598                         } else if (!strcasecmp(v->name, "permit") ||
1599                                            !strcasecmp(v->name, "deny")) {
1600                                 gw->ha = ast_append_ha(v->name, v->value, gw->ha);
1601                         } else if (!strcasecmp(v->name, "port")) {
1602                                 gw->addr.sin_port = htons(atoi(v->value));
1603                         } else if (!strcasecmp(v->name, "context")) {
1604                                 strncpy(context, v->value, sizeof(context) - 1);
1605                         } else if (!strcasecmp(v->name, "inbanddtmf")) {
1606                                 inbanddtmf = atoi(v->value);
1607                         } else if (!strcasecmp(v->name, "nat")) {
1608                                 nat = ast_true(v->value);
1609                         } else if (!strcasecmp(v->name, "callerid")) {
1610                                 if (!strcasecmp(v->value, "asreceived"))
1611                                         strcpy(callerid, "");
1612                                 else
1613                                         strncpy(callerid, v->value, sizeof(callerid) - 1);
1614                         } else if (!strcasecmp(v->name, "language")) {
1615                                 strncpy(language, v->value, sizeof(language)-1);
1616                         } else if (!strcasecmp(v->name, "trunk") ||
1617                                    !strcasecmp(v->name, "line")) {
1618                                 e = malloc(sizeof(struct mgcp_endpoint));
1619                                 if (e) {
1620                                         memset(e, 0, sizeof(struct mgcp_endpoint));
1621                                         /* XXX Should we really check for uniqueness?? XXX */
1622                                         snprintf(e->txident, sizeof(e->txident), "%08x", rand());
1623                                         strncpy(e->context, context, sizeof(e->context) - 1);
1624                                         strncpy(e->callerid, callerid, sizeof(e->callerid) - 1);
1625                                         strncpy(e->language, language, sizeof(e->language) - 1);
1626                                         e->capability = capability;
1627                                         e->parent = gw;
1628                                         e->dtmfinband = inbanddtmf;
1629                                         e->nat = nat;
1630                                         strncpy(e->name, v->value, sizeof(e->name) - 1);
1631                                         if (!strcasecmp(v->name, "trunk"))
1632                                                 e->type = TYPE_TRUNK;
1633                                         else
1634                                                 e->type = TYPE_LINE;
1635                                         e->next = gw->endpoints;
1636                                         gw->endpoints = e;
1637                                 }
1638                         } else
1639                                 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
1640                         v = v->next;
1641                 }
1642                 
1643         }
1644
1645         if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
1646                 ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
1647                 free(gw);
1648                 return NULL;
1649         }
1650         if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 
1651                 gw->defaddr.sin_port = htons(DEFAULT_MGCP_PORT);
1652         if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
1653                 gw->addr.sin_port = htons(DEFAULT_MGCP_PORT);
1654         if (gw->addr.sin_addr.s_addr)
1655                 memcpy(&gw->ourip, myaddrfor(&gw->addr.sin_addr), sizeof(gw->ourip));
1656         return gw;
1657 }
1658
1659 static struct ast_rtp *mgcp_get_rtp_peer(struct ast_channel *chan)
1660 {
1661         struct mgcp_endpoint *p;
1662         p = chan->pvt->pvt;
1663         if (p && p->rtp)
1664                 return p->rtp;
1665         return NULL;
1666 }
1667
1668 static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp)
1669 {
1670         struct mgcp_endpoint *p;
1671         p = chan->pvt->pvt;
1672         if (p) {
1673                 transmit_modify_with_sdp(p, rtp);
1674                 return 0;
1675         }
1676         return -1;
1677 }
1678
1679 static struct ast_rtp_protocol mgcp_rtp = {
1680         get_rtp_info: mgcp_get_rtp_peer,
1681         set_rtp_peer: mgcp_set_rtp_peer,
1682 };
1683
1684 static int mgcp_do_debug(int fd, int argc, char *argv[])
1685 {
1686         if (argc != 2)
1687                 return RESULT_SHOWUSAGE;
1688         mgcpdebug = 1;
1689         ast_cli(fd, "MGCP Debugging Enabled\n");
1690         return RESULT_SUCCESS;
1691 }
1692
1693 static int mgcp_no_debug(int fd, int argc, char *argv[])
1694 {
1695         if (argc != 3)
1696                 return RESULT_SHOWUSAGE;
1697         mgcpdebug = 0;
1698         ast_cli(fd, "MGCP Debugging Disabled\n");
1699         return RESULT_SUCCESS;
1700 }
1701
1702 static char debug_usage[] = 
1703 "Usage: mgcp debug\n"
1704 "       Enables dumping of MGCP packets for debugging purposes\n";
1705
1706 static char no_debug_usage[] = 
1707 "Usage: mgcp no debug\n"
1708 "       Disables dumping of MGCP packets for debugging purposes\n";
1709
1710 static struct ast_cli_entry  cli_debug =
1711         { { "mgcp", "debug", NULL }, mgcp_do_debug, "Enable MGCP debugging", debug_usage };
1712 static struct ast_cli_entry  cli_no_debug =
1713         { { "mgcp", "no", "debug", NULL }, mgcp_no_debug, "Disable MGCP debugging", no_debug_usage };
1714
1715
1716 int load_module()
1717 {
1718         struct ast_config *cfg;
1719         struct ast_variable *v;
1720         struct mgcp_gateway *g;
1721         char *cat;
1722         struct hostent *hp;
1723         int format;
1724         
1725         if (gethostname(ourhost, sizeof(ourhost))) {
1726                 ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
1727                 return 0;
1728         }
1729         cfg = ast_load(config);
1730
1731         /* We *must* have a config file otherwise stop immediately */
1732         if (!cfg) {
1733                 ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
1734                 return 0;
1735         }
1736         memset(&bindaddr, 0, sizeof(bindaddr));
1737         v = ast_variable_browse(cfg, "general");
1738         while(v) {
1739                 /* Create the interface list */
1740                 if (!strcasecmp(v->name, "bindaddr")) {
1741                         if (!(hp = gethostbyname(v->value))) {
1742                                 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
1743                         } else {
1744                                 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
1745                         }
1746                 } else if (!strcasecmp(v->name, "allow")) {
1747                         format = ast_getformatbyname(v->value);
1748                         if (format < 1) 
1749                                 ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
1750                         else
1751                                 capability |= format;
1752                 } else if (!strcasecmp(v->name, "disallow")) {
1753                         format = ast_getformatbyname(v->value);
1754                         if (format < 1) 
1755                                 ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
1756                         else
1757                                 capability &= ~format;
1758                 } else if (!strcasecmp(v->name, "port")) {
1759                         if (sscanf(v->value, "%i", &ourport) == 1) {
1760                                 bindaddr.sin_port = htons(ourport);
1761                         } else {
1762                                 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
1763                         }
1764                 }
1765                 v = v->next;
1766         }
1767         
1768         cat = ast_category_browse(cfg, NULL);
1769         while(cat) {
1770                 if (strcasecmp(cat, "general")) {
1771                         g = build_gateway(cat, ast_variable_browse(cfg, cat));
1772                         if (g) {
1773                                 if (option_verbose > 2)
1774                                         ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
1775                                 ast_pthread_mutex_lock(&gatelock);
1776                                 g->next = gateways;
1777                                 gateways = g;
1778                                 ast_pthread_mutex_unlock(&gatelock);
1779                         }
1780                 }
1781                 cat = ast_category_browse(cfg, cat);
1782         }
1783         
1784         if (ntohl(bindaddr.sin_addr.s_addr)) {
1785                 memcpy(&__ourip, &bindaddr, sizeof(__ourip));
1786         } else {
1787                 hp = gethostbyname(ourhost);
1788                 if (!hp) {
1789                         ast_log(LOG_WARNING, "Unable to get our IP address, MGCP disabled\n");
1790                         return 0;
1791                 }
1792                 memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
1793         }
1794         if (!ntohs(bindaddr.sin_port))
1795                 bindaddr.sin_port = ntohs(DEFAULT_MGCP_PORT);
1796         bindaddr.sin_family = AF_INET;
1797         pthread_mutex_lock(&netlock);
1798         if (mgcpsock > -1)
1799                 close(mgcpsock);
1800         mgcpsock = socket(AF_INET, SOCK_DGRAM, 0);
1801         if (mgcpsock < 0) {
1802                 ast_log(LOG_WARNING, "Unable to create MGCP socket: %s\n", strerror(errno));
1803         } else {
1804                 if (bind(mgcpsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
1805                         ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
1806                                         inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
1807                                                 strerror(errno));
1808                         close(mgcpsock);
1809                         mgcpsock = -1;
1810                 } else if (option_verbose > 1)
1811                         ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n", 
1812                                 inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
1813         }
1814         pthread_mutex_unlock(&netlock);
1815         ast_destroy(cfg);
1816
1817         /* Make sure we can register our mgcp channel type */
1818         if (ast_channel_register(type, tdesc, capability, mgcp_request)) {
1819                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
1820                 ast_destroy(cfg);
1821                 return -1;
1822         }
1823         mgcp_rtp.type = type;
1824         ast_rtp_proto_register(&mgcp_rtp);
1825         ast_cli_register(&cli_show_endpoints);
1826         ast_cli_register(&cli_debug);
1827         ast_cli_register(&cli_no_debug);
1828         /* And start the monitor for the first time */
1829         restart_monitor();
1830         return 0;
1831 }
1832
1833 int unload_module()
1834 {
1835         struct mgcp_endpoint *p, *pl;
1836 #if 0
1837         /* First, take us out of the channel loop */
1838         ast_channel_unregister(type);
1839         if (!ast_pthread_mutex_lock(&gatelock)) {
1840                 /* Hangup all interfaces if they have an owner */
1841                 p = iflist;
1842                 while(p) {
1843                         if (p->owner)
1844                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
1845                         p = p->next;
1846                 }
1847                 iflist = NULL;
1848                 ast_pthread_mutex_unlock(&iflock);
1849         } else {
1850                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1851                 return -1;
1852         }
1853         if (!ast_pthread_mutex_lock(&monlock)) {
1854                 if (monitor_thread) {
1855                         pthread_cancel(monitor_thread);
1856                         pthread_kill(monitor_thread, SIGURG);
1857                         pthread_join(monitor_thread, NULL);
1858                 }
1859                 monitor_thread = -2;
1860                 ast_pthread_mutex_unlock(&monlock);
1861         } else {
1862                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1863                 return -1;
1864         }
1865
1866         if (!ast_pthread_mutex_lock(&iflock)) {
1867                 /* Destroy all the interfaces and free their memory */
1868                 p = iflist;
1869                 while(p) {
1870                         pl = p;
1871                         p = p->next;
1872                         /* Free associated memory */
1873                         free(pl);
1874                 }
1875                 iflist = NULL;
1876                 ast_pthread_mutex_unlock(&iflock);
1877         } else {
1878                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
1879                 return -1;
1880         }
1881 #endif          
1882         return -1;
1883 }
1884
1885 int usecount()
1886 {
1887         int res;
1888         ast_pthread_mutex_lock(&usecnt_lock);
1889         res = usecnt;
1890         ast_pthread_mutex_unlock(&usecnt_lock);
1891         return res;
1892 }
1893
1894 char *key()
1895 {
1896         return ASTERISK_GPL_KEY;
1897 }
1898
1899 char *description()
1900 {
1901         return desc;
1902 }
1903