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