define an AST_MAX_CONTEXT for use instead of AST_MAX_EXTENSION
[asterisk/asterisk.git] / channels / chan_local.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Local Proxy Channel
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 <string.h>
16 #include <unistd.h>
17 #include <sys/socket.h>
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <fcntl.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <sys/signal.h>
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/lock.h"
31 #include "asterisk/channel.h"
32 #include "asterisk/config.h"
33 #include "asterisk/logger.h"
34 #include "asterisk/module.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/options.h"
37 #include "asterisk/lock.h"
38 #include "asterisk/sched.h"
39 #include "asterisk/io.h"
40 #include "asterisk/rtp.h"
41 #include "asterisk/acl.h"
42 #include "asterisk/callerid.h"
43 #include "asterisk/file.h"
44 #include "asterisk/cli.h"
45 #include "asterisk/app.h"
46 #include "asterisk/musiconhold.h"
47 #include "asterisk/manager.h"
48
49 static const char desc[] = "Local Proxy Channel";
50 static const char type[] = "Local";
51 static const char tdesc[] = "Local Proxy Channel Driver";
52
53 static int usecnt =0;
54 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
55
56 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
57
58 /* Protect the interface list (of sip_pvt's) */
59 AST_MUTEX_DEFINE_STATIC(locallock);
60
61 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause);
62 static int local_digit(struct ast_channel *ast, char digit);
63 static int local_call(struct ast_channel *ast, char *dest, int timeout);
64 static int local_hangup(struct ast_channel *ast);
65 static int local_answer(struct ast_channel *ast);
66 static struct ast_frame *local_read(struct ast_channel *ast);
67 static int local_write(struct ast_channel *ast, struct ast_frame *f);
68 static int local_indicate(struct ast_channel *ast, int condition);
69 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
70 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
71
72 static const struct ast_channel_tech local_tech = {
73         .type = type,
74         .description = tdesc,
75         .capabilities = -1,
76         .requester = local_request,
77         .send_digit = local_digit,
78         .call = local_call,
79         .hangup = local_hangup,
80         .answer = local_answer,
81         .read = local_read,
82         .write = local_write,
83         .exception = local_read,
84         .indicate = local_indicate,
85         .fixup = local_fixup,
86         .send_html = local_sendhtml,
87 };
88
89 static struct local_pvt {
90         ast_mutex_t lock;                       /* Channel private lock */
91         char context[AST_MAX_CONTEXT];          /* Context to call */
92         char exten[AST_MAX_EXTENSION];          /* Extension to call */
93         int reqformat;                          /* Requested format */
94         int glaredetect;                        /* Detect glare on hangup */
95         int cancelqueue;                        /* Cancel queue */
96         int alreadymasqed;                      /* Already masqueraded */
97         int launchedpbx;                        /* Did we launch the PBX */
98         int nooptimization;
99         struct ast_channel *owner;              /* Master Channel */
100         struct ast_channel *chan;               /* Outbound channel */
101         struct local_pvt *next;                 /* Next entity */
102 } *locals = NULL;
103
104 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us)
105 {
106         struct ast_channel *other;
107 retrylock:              
108         /* Recalculate outbound channel */
109         if (isoutbound) {
110                 other = p->owner;
111         } else {
112                 other = p->chan;
113         }
114         /* Set glare detection */
115         p->glaredetect = 1;
116         if (p->cancelqueue) {
117                 /* We had a glare on the hangup.  Forget all this business,
118                 return and destroy p.  */
119                 ast_mutex_unlock(&p->lock);
120                 ast_mutex_destroy(&p->lock);
121                 free(p);
122                 return -1;
123         }
124         if (!other) {
125                 p->glaredetect = 0;
126                 return 0;
127         }
128         if (ast_mutex_trylock(&other->lock)) {
129                 /* Failed to lock.  Release main lock and try again */
130                 ast_mutex_unlock(&p->lock);
131                 if (us) {
132                         if (ast_mutex_unlock(&us->lock)) {
133                                 ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
134                                         us->name, f->frametype, f->subclass);
135                                 us = NULL;
136                         }
137                 }
138                 /* Wait just a bit */
139                 usleep(1);
140                 /* Only we can destroy ourselves, so we can't disappear here */
141                 if (us)
142                         ast_mutex_lock(&us->lock);
143                 ast_mutex_lock(&p->lock);
144                 goto retrylock;
145         }
146         ast_queue_frame(other, f);
147         ast_mutex_unlock(&other->lock);
148         p->glaredetect = 0;
149         return 0;
150 }
151
152 static int local_answer(struct ast_channel *ast)
153 {
154         struct local_pvt *p = ast->tech_pvt;
155         int isoutbound;
156         int res = -1;
157         ast_mutex_lock(&p->lock);
158         isoutbound = IS_OUTBOUND(ast, p);
159         if (isoutbound) {
160                 /* Pass along answer since somebody answered us */
161                 struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
162                 res = local_queue_frame(p, isoutbound, &answer, ast);
163         } else
164                 ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
165         ast_mutex_unlock(&p->lock);
166         return res;
167 }
168
169 static void check_bridge(struct local_pvt *p, int isoutbound)
170 {
171         if (p->alreadymasqed || p->nooptimization)
172                 return;
173         if (isoutbound && p->chan && p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && p->owner && !p->owner->readq) {
174                 /* Masquerade bridged channel into owner */
175                 /* Lock everything we need, one by one, and give up if
176                    we can't get everything.  Remember, we'll get another
177                    chance in just a little bit */
178                 if (!ast_mutex_trylock(&(p->chan->_bridge)->lock)) {
179                         if (!ast_mutex_trylock(&p->owner->lock)) {
180                                 ast_channel_masquerade(p->owner, p->chan->_bridge);
181                                 p->alreadymasqed = 1;
182                                 ast_mutex_unlock(&p->owner->lock);
183                         }
184                         ast_mutex_unlock(&(p->chan->_bridge)->lock);
185                 }
186         } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && !p->chan->readq) {
187                 /* Masquerade bridged channel into chan */
188                 if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
189                         if (!ast_mutex_trylock(&p->chan->lock)) {
190                                 ast_channel_masquerade(p->chan, p->owner->_bridge);
191                                 p->alreadymasqed = 1;
192                                 ast_mutex_unlock(&p->chan->lock);
193                         }
194                         ast_mutex_unlock(&(p->owner->_bridge)->lock);
195                 }
196         }
197 }
198
199 static struct ast_frame  *local_read(struct ast_channel *ast)
200 {
201         static struct ast_frame null = { AST_FRAME_NULL, };
202         return &null;
203 }
204
205 static int local_write(struct ast_channel *ast, struct ast_frame *f)
206 {
207         struct local_pvt *p = ast->tech_pvt;
208         int res = -1;
209         int isoutbound;
210
211
212         /* Just queue for delivery to the other side */
213         ast_mutex_lock(&p->lock);
214         isoutbound = IS_OUTBOUND(ast, p);
215         if (f && (f->frametype == AST_FRAME_VOICE)) 
216                 check_bridge(p, isoutbound);
217         if (!p->alreadymasqed)
218                 res = local_queue_frame(p, isoutbound, f, ast);
219         else {
220                 ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name);
221                 res = 0;
222         }
223         ast_mutex_unlock(&p->lock);
224         return res;
225 }
226
227 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
228 {
229         struct local_pvt *p = newchan->tech_pvt;
230         ast_mutex_lock(&p->lock);
231         if ((p->owner != oldchan) && (p->chan != oldchan)) {
232                 ast_log(LOG_WARNING, "old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
233                 ast_mutex_unlock(&p->lock);
234                 return -1;
235         }
236         if (p->owner == oldchan)
237                 p->owner = newchan;
238         else
239                 p->chan = newchan;      
240         ast_mutex_unlock(&p->lock);
241         return 0;
242 }
243
244 static int local_indicate(struct ast_channel *ast, int condition)
245 {
246         struct local_pvt *p = ast->tech_pvt;
247         int res = -1;
248         struct ast_frame f = { AST_FRAME_CONTROL, };
249         int isoutbound;
250         /* Queue up a frame representing the indication as a control frame */
251         ast_mutex_lock(&p->lock);
252         isoutbound = IS_OUTBOUND(ast, p);
253         f.subclass = condition;
254         res = local_queue_frame(p, isoutbound, &f, ast);
255         ast_mutex_unlock(&p->lock);
256         return res;
257 }
258
259 static int local_digit(struct ast_channel *ast, char digit)
260 {
261         struct local_pvt *p = ast->tech_pvt;
262         int res = -1;
263         struct ast_frame f = { AST_FRAME_DTMF, };
264         int isoutbound;
265         ast_mutex_lock(&p->lock);
266         isoutbound = IS_OUTBOUND(ast, p);
267         f.subclass = digit;
268         res = local_queue_frame(p, isoutbound, &f, ast);
269         ast_mutex_unlock(&p->lock);
270         return res;
271 }
272
273 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
274 {
275         struct local_pvt *p = ast->tech_pvt;
276         int res = -1;
277         struct ast_frame f = { AST_FRAME_HTML, };
278         int isoutbound;
279         ast_mutex_lock(&p->lock);
280         isoutbound = IS_OUTBOUND(ast, p);
281         f.subclass = subclass;
282         f.data = (char *)data;
283         f.datalen = datalen;
284         res = local_queue_frame(p, isoutbound, &f, ast);
285         ast_mutex_unlock(&p->lock);
286         return res;
287 }
288
289 static int local_call(struct ast_channel *ast, char *dest, int timeout)
290 {
291         struct local_pvt *p = ast->tech_pvt;
292         int res;
293         
294         ast_mutex_lock(&p->lock);
295         if (p->owner->cid.cid_num)
296                 p->chan->cid.cid_num = strdup(p->owner->cid.cid_num);
297         else 
298                 p->chan->cid.cid_num = NULL;
299
300         if (p->owner->cid.cid_name)
301                 p->chan->cid.cid_name = strdup(p->owner->cid.cid_name);
302         else 
303                 p->chan->cid.cid_name = NULL;
304
305         if (p->owner->cid.cid_rdnis)
306                 p->chan->cid.cid_rdnis = strdup(p->owner->cid.cid_rdnis);
307         else
308                 p->chan->cid.cid_rdnis = NULL;
309
310         if (p->owner->cid.cid_ani)
311                 p->chan->cid.cid_ani = strdup(p->owner->cid.cid_ani);
312         else
313                 p->chan->cid.cid_ani = NULL;
314
315         strncpy(p->chan->language, p->owner->language, sizeof(p->chan->language) - 1);
316         strncpy(p->chan->accountcode, p->owner->accountcode, sizeof(p->chan->accountcode) - 1);
317         p->chan->cdrflags = p->owner->cdrflags;
318         ast_channel_inherit_variables(p->owner, p->chan);
319         p->launchedpbx = 1;
320         /* Start switch on sub channel */
321         res = ast_pbx_start(p->chan);
322         ast_mutex_unlock(&p->lock);
323         return res;
324 }
325
326 /*
327 static void local_destroy(struct local_pvt *p)
328 {
329         struct local_pvt *cur, *prev = NULL;
330         ast_mutex_lock(&locallock);
331         cur = locals;
332         while(cur) {
333                 if (cur == p) {
334                         if (prev)
335                                 prev->next = cur->next;
336                         else
337                                 locals = cur->next;
338                         ast_mutex_destroy(cur);
339                         free(cur);
340                         break;
341                 }
342                 prev = cur;
343                 cur = cur->next;
344         }
345         ast_mutex_unlock(&locallock);
346         if (!cur)
347                 ast_log(LOG_WARNING, "Unable ot find local '%s@%s' in local list\n", p->exten, p->context);
348 }
349 */
350
351 static int local_hangup(struct ast_channel *ast)
352 {
353         struct local_pvt *p = ast->tech_pvt;
354         int isoutbound;
355         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
356         struct local_pvt *cur, *prev=NULL;
357         struct ast_channel *ochan = NULL;
358         int glaredetect;
359         ast_mutex_lock(&p->lock);
360         isoutbound = IS_OUTBOUND(ast, p);
361         if (isoutbound) {
362                 p->chan = NULL;
363                 p->launchedpbx = 0;
364         } else
365                 p->owner = NULL;
366         ast->tech_pvt = NULL;
367         
368         ast_mutex_lock(&usecnt_lock);
369         usecnt--;
370         ast_mutex_unlock(&usecnt_lock);
371         
372         if (!p->owner && !p->chan) {
373                 /* Okay, done with the private part now, too. */
374                 glaredetect = p->glaredetect;
375                 /* If we have a queue holding, don't actually destroy p yet, but
376                    let local_queue do it. */
377                 if (p->glaredetect)
378                         p->cancelqueue = 1;
379                 ast_mutex_unlock(&p->lock);
380                 /* Remove from list */
381                 ast_mutex_lock(&locallock);
382                 cur = locals;
383                 while(cur) {
384                         if (cur == p) {
385                                 if (prev)
386                                         prev->next = cur->next;
387                                 else
388                                         locals = cur->next;
389                                 break;
390                         }
391                         prev = cur;
392                         cur = cur->next;
393                 }
394                 ast_mutex_unlock(&locallock);
395                 /* Grab / release lock just in case */
396                 ast_mutex_lock(&p->lock);
397                 ast_mutex_unlock(&p->lock);
398                 /* And destroy */
399                 if (!glaredetect) {
400                         ast_mutex_destroy(&p->lock);
401                         free(p);
402                 }
403                 return 0;
404         }
405         if (p->chan && !p->launchedpbx)
406                 /* Need to actually hangup since there is no PBX */
407                 ochan = p->chan;
408         else
409                 local_queue_frame(p, isoutbound, &f, NULL);
410         ast_mutex_unlock(&p->lock);
411         if (ochan)
412                 ast_hangup(ochan);
413         return 0;
414 }
415
416 static struct local_pvt *local_alloc(char *data, int format)
417 {
418         struct local_pvt *tmp;
419         char *c;
420         char *opts;
421         tmp = malloc(sizeof(struct local_pvt));
422         if (tmp) {
423                 memset(tmp, 0, sizeof(struct local_pvt));
424                 ast_mutex_init(&tmp->lock);
425                 strncpy(tmp->exten, data, sizeof(tmp->exten) - 1);
426                 opts = strchr(tmp->exten, '/');
427                 if (opts) {
428                         *opts='\0';
429                         opts++;
430                         if (strchr(opts, 'n'))
431                                 tmp->nooptimization = 1;
432                 }
433                 c = strchr(tmp->exten, '@');
434                 if (c) {
435                         *c = '\0';
436                         c++;
437                         strncpy(tmp->context, c, sizeof(tmp->context) - 1);
438                 } else
439                         strncpy(tmp->context, "default", sizeof(tmp->context) - 1);
440                 tmp->reqformat = format;
441                 if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
442                         ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
443                         ast_mutex_destroy(&tmp->lock);
444                         free(tmp);
445                         tmp = NULL;
446                 } else {
447                         /* Add to list */
448                         ast_mutex_lock(&locallock);
449                         tmp->next = locals;
450                         locals = tmp;
451                         ast_mutex_unlock(&locallock);
452                 }
453                 
454         }
455         return tmp;
456 }
457
458 static struct ast_channel *local_new(struct local_pvt *p, int state)
459 {
460         struct ast_channel *tmp, *tmp2;
461         int randnum = rand() & 0xffff;
462         tmp = ast_channel_alloc(1);
463         tmp2 = ast_channel_alloc(1);
464         if (!tmp || !tmp2) {
465                 if (tmp)
466                         ast_channel_free(tmp);
467                 if (tmp2)
468                         ast_channel_free(tmp2);
469                 tmp = NULL;
470         }
471         if (tmp) {
472                 tmp2->tech = tmp->tech = &local_tech;
473                 tmp->nativeformats = p->reqformat;
474                 tmp2->nativeformats = p->reqformat;
475                 snprintf(tmp->name, sizeof(tmp->name), "Local/%s@%s-%04x,1", p->exten, p->context, randnum);
476                 snprintf(tmp2->name, sizeof(tmp2->name), "Local/%s@%s-%04x,2", p->exten, p->context, randnum);
477                 tmp->type = type;
478                 tmp2->type = type;
479                 ast_setstate(tmp, state);
480                 ast_setstate(tmp2, AST_STATE_RING);
481                 tmp->writeformat = p->reqformat;;
482                 tmp2->writeformat = p->reqformat;
483                 tmp->rawwriteformat = p->reqformat;
484                 tmp2->rawwriteformat = p->reqformat;
485                 tmp->readformat = p->reqformat;
486                 tmp2->readformat = p->reqformat;
487                 tmp->rawreadformat = p->reqformat;
488                 tmp2->rawreadformat = p->reqformat;
489                 tmp->tech_pvt = p;
490                 tmp2->tech_pvt = p;
491                 p->owner = tmp;
492                 p->chan = tmp2;
493                 ast_mutex_lock(&usecnt_lock);
494                 usecnt++;
495                 usecnt++;
496                 ast_mutex_unlock(&usecnt_lock);
497                 ast_update_use_count();
498                 strncpy(tmp->context, p->context, sizeof(tmp->context)-1);
499                 strncpy(tmp2->context, p->context, sizeof(tmp2->context)-1);
500                 strncpy(tmp2->exten, p->exten, sizeof(tmp->exten)-1);
501                 tmp->priority = 1;
502                 tmp2->priority = 1;
503         } else
504                 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
505         return tmp;
506 }
507
508
509 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
510 {
511         struct local_pvt *p;
512         struct ast_channel *chan = NULL;
513         p = local_alloc(data, format);
514         if (p)
515                 chan = local_new(p, AST_STATE_DOWN);
516         return chan;
517 }
518
519 static int locals_show(int fd, int argc, char **argv)
520 {
521         struct local_pvt *p;
522
523         if (argc != 3)
524                 return RESULT_SHOWUSAGE;
525         ast_mutex_lock(&locallock);
526         p = locals;
527         while(p) {
528                 ast_mutex_lock(&p->lock);
529                 ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
530                 ast_mutex_unlock(&p->lock);
531                 p = p->next;
532         }
533         if (!locals)
534                 ast_cli(fd, "No local channels in use\n");
535         ast_mutex_unlock(&locallock);
536         return RESULT_SUCCESS;
537 }
538
539 static char show_locals_usage[] = 
540 "Usage: local show channels\n"
541 "       Provides summary information on local channels.\n";
542
543 static struct ast_cli_entry cli_show_locals = {
544         { "local", "show", "channels", NULL }, locals_show, 
545         "Show status of local channels", show_locals_usage, NULL };
546
547 int load_module()
548 {
549         /* Make sure we can register our channel type */
550         if (ast_channel_register(&local_tech)) {
551                 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
552                 return -1;
553         }
554         ast_cli_register(&cli_show_locals);
555         return 0;
556 }
557
558 int reload()
559 {
560         return 0;
561 }
562
563 int unload_module()
564 {
565         struct local_pvt *p;
566         /* First, take us out of the channel loop */
567         ast_cli_unregister(&cli_show_locals);
568         ast_channel_unregister(&local_tech);
569         if (!ast_mutex_lock(&locallock)) {
570                 /* Hangup all interfaces if they have an owner */
571                 p = locals;
572                 while(p) {
573                         if (p->owner)
574                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
575                         p = p->next;
576                 }
577                 locals = NULL;
578                 ast_mutex_unlock(&locallock);
579         } else {
580                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
581                 return -1;
582         }               
583         return 0;
584 }
585
586 int usecount()
587 {
588         return usecnt;
589 }
590
591 char *key()
592 {
593         return ASTERISK_GPL_KEY;
594 }
595
596 char *description()
597 {
598         return (char *) desc;
599 }
600