Merged revisions 89536 via svnmerge from
[asterisk/asterisk.git] / channels / chan_local.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \author Mark Spencer <markster@digium.com>
22  *
23  * \brief Local Proxy Channel
24  * 
25  * \ingroup channel_drivers
26  */
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include <fcntl.h>
33 #include <sys/signal.h>
34
35 #include "asterisk/lock.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/config.h"
38 #include "asterisk/module.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/sched.h"
41 #include "asterisk/io.h"
42 #include "asterisk/rtp.h"
43 #include "asterisk/acl.h"
44 #include "asterisk/callerid.h"
45 #include "asterisk/file.h"
46 #include "asterisk/cli.h"
47 #include "asterisk/app.h"
48 #include "asterisk/musiconhold.h"
49 #include "asterisk/manager.h"
50 #include "asterisk/stringfields.h"
51 #include "asterisk/devicestate.h"
52
53 static const char tdesc[] = "Local Proxy Channel Driver";
54
55 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
56
57 static struct ast_jb_conf g_jb_conf = {
58         .flags = 0,
59         .max_size = -1,
60         .resync_threshold = -1,
61         .impl = "",
62 };
63
64 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause);
65 static int local_digit_begin(struct ast_channel *ast, char digit);
66 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
67 static int local_call(struct ast_channel *ast, char *dest, int timeout);
68 static int local_hangup(struct ast_channel *ast);
69 static int local_answer(struct ast_channel *ast);
70 static struct ast_frame *local_read(struct ast_channel *ast);
71 static int local_write(struct ast_channel *ast, struct ast_frame *f);
72 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
73 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
74 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
75 static int local_sendtext(struct ast_channel *ast, const char *text);
76 static int local_devicestate(void *data);
77
78 /* PBX interface structure for channel registration */
79 static const struct ast_channel_tech local_tech = {
80         .type = "Local",
81         .description = tdesc,
82         .capabilities = -1,
83         .requester = local_request,
84         .send_digit_begin = local_digit_begin,
85         .send_digit_end = local_digit_end,
86         .call = local_call,
87         .hangup = local_hangup,
88         .answer = local_answer,
89         .read = local_read,
90         .write = local_write,
91         .write_video = local_write,
92         .exception = local_read,
93         .indicate = local_indicate,
94         .fixup = local_fixup,
95         .send_html = local_sendhtml,
96         .send_text = local_sendtext,
97         .devicestate = local_devicestate,
98 };
99
100 struct local_pvt {
101         ast_mutex_t lock;                       /* Channel private lock */
102         unsigned int flags;                     /* Private flags */
103         char context[AST_MAX_CONTEXT];          /* Context to call */
104         char exten[AST_MAX_EXTENSION];          /* Extension to call */
105         int reqformat;                          /* Requested format */
106         struct ast_jb_conf jb_conf;             /*!< jitterbuffer configuration for this local channel */
107         struct ast_channel *owner;              /* Master Channel */
108         struct ast_channel *chan;               /* Outbound channel */
109         struct ast_module_user *u_owner;        /*! reference to keep the module loaded while in use */
110         struct ast_module_user *u_chan;         /*! reference to keep the module loaded while in use */
111         AST_LIST_ENTRY(local_pvt) list;         /* Next entity */
112 };
113
114 #define LOCAL_GLARE_DETECT    (1 << 0) /*!< Detect glare on hangup */
115 #define LOCAL_CANCEL_QUEUE    (1 << 1) /*!< Cancel queue */
116 #define LOCAL_ALREADY_MASQED  (1 << 2) /*!< Already masqueraded */
117 #define LOCAL_LAUNCHED_PBX    (1 << 3) /*!< PBX was launched */
118 #define LOCAL_NO_OPTIMIZATION (1 << 4) /*!< Do not optimize using masquerading */
119
120 static AST_LIST_HEAD_STATIC(locals, local_pvt);
121
122 /*! \brief Adds devicestate to local channels */
123 static int local_devicestate(void *data)
124 {
125         char *exten = ast_strdupa(data);
126         char *context = NULL, *opts = NULL;
127         int res;
128         struct local_pvt *lp;
129
130         if (!(context = strchr(exten, '@'))) {
131                 ast_log(LOG_WARNING, "Someone used Local/%s somewhere without a @context. This is bad.\n", exten);
132                 return AST_DEVICE_INVALID;      
133         }
134
135         *context++ = '\0';
136
137         /* Strip options if they exist */
138         if ((opts = strchr(context, '/')))
139                 *opts = '\0';
140
141         ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
142
143         res = ast_exists_extension(NULL, context, exten, 1, NULL);
144         if (!res)               
145                 return AST_DEVICE_INVALID;
146         
147         res = AST_DEVICE_NOT_INUSE;
148         AST_LIST_LOCK(&locals);
149         AST_LIST_TRAVERSE(&locals, lp, list) {
150                 if (!strcmp(exten, lp->exten) && !strcmp(context, lp->context) && lp->owner) {
151                         res = AST_DEVICE_INUSE;
152                         break;
153                 }
154         }
155         AST_LIST_UNLOCK(&locals);
156
157         return res;
158 }
159
160 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us)
161 {
162         struct ast_channel *other = NULL;
163
164 retrylock:              
165
166         /* Recalculate outbound channel */
167         other = isoutbound ? p->owner : p->chan;
168
169         /* Set glare detection */
170         ast_set_flag(p, LOCAL_GLARE_DETECT);
171         if (ast_test_flag(p, LOCAL_CANCEL_QUEUE)) {
172                 /* We had a glare on the hangup.  Forget all this business,
173                 return and destroy p.  */
174                 ast_mutex_unlock(&p->lock);
175                 ast_mutex_destroy(&p->lock);
176                 ast_free(p);
177                 return -1;
178         }
179         if (!other) {
180                 ast_clear_flag(p, LOCAL_GLARE_DETECT);
181                 return 0;
182         }
183         if (ast_channel_trylock(other)) {
184                 /* Failed to lock.  Release main lock and try again */
185                 ast_mutex_unlock(&p->lock);
186                 if (us) {
187                         if (ast_channel_unlock(us)) {
188                                 ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
189                                         us->name, f->frametype, f->subclass);
190                                 us = NULL;
191                         }
192                 }
193                 /* Wait just a bit */
194                 usleep(1);
195                 /* Only we can destroy ourselves, so we can't disappear here */
196                 if (us)
197                         ast_channel_lock(us);
198                 ast_mutex_lock(&p->lock);
199                 goto retrylock;
200         }
201         ast_queue_frame(other, f);
202         ast_channel_unlock(other);
203         ast_clear_flag(p, LOCAL_GLARE_DETECT);
204         return 0;
205 }
206
207 static int local_answer(struct ast_channel *ast)
208 {
209         struct local_pvt *p = ast->tech_pvt;
210         int isoutbound;
211         int res = -1;
212
213         if (!p)
214                 return -1;
215
216         ast_mutex_lock(&p->lock);
217         isoutbound = IS_OUTBOUND(ast, p);
218         if (isoutbound) {
219                 /* Pass along answer since somebody answered us */
220                 struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
221                 res = local_queue_frame(p, isoutbound, &answer, ast);
222         } else
223                 ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
224         if (!res)
225                 ast_mutex_unlock(&p->lock);
226         return res;
227 }
228
229 static void check_bridge(struct local_pvt *p, int isoutbound)
230 {
231         if (ast_test_flag(p, LOCAL_ALREADY_MASQED) || ast_test_flag(p, LOCAL_NO_OPTIMIZATION) || !p->chan || !p->owner || (p->chan->_bridge != ast_bridged_channel(p->chan)))
232                 return;
233
234         /* only do the masquerade if we are being called on the outbound channel,
235            if it has been bridged to another channel and if there are no pending
236            frames on the owner channel (because they would be transferred to the
237            outbound channel during the masquerade)
238         */
239         if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) {
240                 /* Masquerade bridged channel into owner */
241                 /* Lock everything we need, one by one, and give up if
242                    we can't get everything.  Remember, we'll get another
243                    chance in just a little bit */
244                 if (!ast_channel_trylock(p->chan->_bridge)) {
245                         if (!ast_check_hangup(p->chan->_bridge)) {
246                                 if (!ast_channel_trylock(p->owner)) {
247                                         if (!ast_check_hangup(p->owner)) {
248                                                 ast_channel_masquerade(p->owner, p->chan->_bridge);
249                                                 ast_set_flag(p, LOCAL_ALREADY_MASQED);
250                                         }
251                                         ast_channel_unlock(p->owner);
252                                 }
253                                 ast_channel_unlock(p->chan->_bridge);
254                         }
255                 }
256         /* We only allow masquerading in one 'direction'... it's important to preserve the state
257            (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan)
258            when the local channels go away.
259         */
260 #if 0
261         } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && AST_LIST_EMPTY(&p->chan->readq)) {
262                 /* Masquerade bridged channel into chan */
263                 if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
264                         if (!ast_check_hangup(p->owner->_bridge)) {
265                                 if (!ast_mutex_trylock(&p->chan->lock)) {
266                                         if (!ast_check_hangup(p->chan)) {
267                                                 ast_channel_masquerade(p->chan, p->owner->_bridge);
268                                                 ast_set_flag(p, LOCAL_ALREADY_MASQED);
269                                         }
270                                         ast_mutex_unlock(&p->chan->lock);
271                                 }
272                         }
273                         ast_mutex_unlock(&(p->owner->_bridge)->lock);
274                 }
275 #endif
276         }
277 }
278
279 static struct ast_frame  *local_read(struct ast_channel *ast)
280 {
281         return &ast_null_frame;
282 }
283
284 static int local_write(struct ast_channel *ast, struct ast_frame *f)
285 {
286         struct local_pvt *p = ast->tech_pvt;
287         int res = -1;
288         int isoutbound;
289
290         if (!p)
291                 return -1;
292
293         /* Just queue for delivery to the other side */
294         ast_mutex_lock(&p->lock);
295         isoutbound = IS_OUTBOUND(ast, p);
296         if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO))
297                 check_bridge(p, isoutbound);
298         if (!ast_test_flag(p, LOCAL_ALREADY_MASQED))
299                 res = local_queue_frame(p, isoutbound, f, ast);
300         else {
301                 ast_debug(1, "Not posting to queue since already masked on '%s'\n", ast->name);
302                 res = 0;
303         }
304         if (!res)
305                 ast_mutex_unlock(&p->lock);
306         return res;
307 }
308
309 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
310 {
311         struct local_pvt *p = newchan->tech_pvt;
312
313         if (!p)
314                 return -1;
315
316         ast_mutex_lock(&p->lock);
317
318         if ((p->owner != oldchan) && (p->chan != oldchan)) {
319                 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
320                 ast_mutex_unlock(&p->lock);
321                 return -1;
322         }
323         if (p->owner == oldchan)
324                 p->owner = newchan;
325         else
326                 p->chan = newchan;
327         ast_mutex_unlock(&p->lock);
328         return 0;
329 }
330
331 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
332 {
333         struct local_pvt *p = ast->tech_pvt;
334         int res = 0;
335         struct ast_frame f = { AST_FRAME_CONTROL, };
336         int isoutbound;
337
338         if (!p)
339                 return -1;
340
341         /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
342         if (condition == AST_CONTROL_HOLD) {
343                 ast_moh_start(ast, data, NULL);
344         } else if (condition == AST_CONTROL_UNHOLD) {
345                 ast_moh_stop(ast);
346         } else {
347                 /* Queue up a frame representing the indication as a control frame */
348                 ast_mutex_lock(&p->lock);
349                 isoutbound = IS_OUTBOUND(ast, p);
350                 f.subclass = condition;
351                 f.data = (void*)data;
352                 f.datalen = datalen;
353                 if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
354                         ast_mutex_unlock(&p->lock);
355         }
356
357         return res;
358 }
359
360 static int local_digit_begin(struct ast_channel *ast, char digit)
361 {
362         struct local_pvt *p = ast->tech_pvt;
363         int res = -1;
364         struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
365         int isoutbound;
366
367         if (!p)
368                 return -1;
369
370         ast_mutex_lock(&p->lock);
371         isoutbound = IS_OUTBOUND(ast, p);
372         f.subclass = digit;
373         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
374                 ast_mutex_unlock(&p->lock);
375
376         return res;
377 }
378
379 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
380 {
381         struct local_pvt *p = ast->tech_pvt;
382         int res = -1;
383         struct ast_frame f = { AST_FRAME_DTMF_END, };
384         int isoutbound;
385
386         if (!p)
387                 return -1;
388
389         ast_mutex_lock(&p->lock);
390         isoutbound = IS_OUTBOUND(ast, p);
391         f.subclass = digit;
392         f.len = duration;
393         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
394                 ast_mutex_unlock(&p->lock);
395
396         return res;
397 }
398
399 static int local_sendtext(struct ast_channel *ast, const char *text)
400 {
401         struct local_pvt *p = ast->tech_pvt;
402         int res = -1;
403         struct ast_frame f = { AST_FRAME_TEXT, };
404         int isoutbound;
405
406         if (!p)
407                 return -1;
408
409         ast_mutex_lock(&p->lock);
410         isoutbound = IS_OUTBOUND(ast, p);
411         f.data = (char *) text;
412         f.datalen = strlen(text) + 1;
413         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
414                 ast_mutex_unlock(&p->lock);
415         return res;
416 }
417
418 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
419 {
420         struct local_pvt *p = ast->tech_pvt;
421         int res = -1;
422         struct ast_frame f = { AST_FRAME_HTML, };
423         int isoutbound;
424
425         if (!p)
426                 return -1;
427         
428         ast_mutex_lock(&p->lock);
429         isoutbound = IS_OUTBOUND(ast, p);
430         f.subclass = subclass;
431         f.data = (char *)data;
432         f.datalen = datalen;
433         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
434                 ast_mutex_unlock(&p->lock);
435         return res;
436 }
437
438 /*! \brief Initiate new call, part of PBX interface 
439  *      dest is the dial string */
440 static int local_call(struct ast_channel *ast, char *dest, int timeout)
441 {
442         struct local_pvt *p = ast->tech_pvt;
443         int res;
444         struct ast_var_t *varptr = NULL, *new;
445         size_t len, namelen;
446
447         if (!p)
448                 return -1;
449         
450         ast_mutex_lock(&p->lock);
451
452         /*
453          * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
454          * call, so it's done here instead.
455          */
456         p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
457         p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
458         p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
459         p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
460         p->chan->cid.cid_pres = p->owner->cid.cid_pres;
461         ast_string_field_set(p->chan, language, p->owner->language);
462         ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
463         p->chan->cdrflags = p->owner->cdrflags;
464
465         /* copy the channel variables from the incoming channel to the outgoing channel */
466         /* Note that due to certain assumptions, they MUST be in the same order */
467         AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
468                 namelen = strlen(varptr->name);
469                 len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
470                 if ((new = ast_calloc(1, len))) {
471                         memcpy(new, varptr, len);
472                         new->value = &(new->name[0]) + namelen + 1;
473                         AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
474                 }
475         }
476
477         /* Start switch on sub channel */
478         if (!(res = ast_pbx_start(p->chan)))
479                 ast_set_flag(p, LOCAL_LAUNCHED_PBX);
480
481         ast_mutex_unlock(&p->lock);
482         return res;
483 }
484
485 /*! \brief Hangup a call through the local proxy channel */
486 static int local_hangup(struct ast_channel *ast)
487 {
488         struct local_pvt *p = ast->tech_pvt;
489         int isoutbound;
490         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
491         struct ast_channel *ochan = NULL;
492         int glaredetect = 0, res = 0;
493
494         if (!p)
495                 return -1;
496
497         ast_mutex_lock(&p->lock);
498         if (p->chan && ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) 
499                 ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
500         isoutbound = IS_OUTBOUND(ast, p);
501         if (isoutbound) {
502                 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
503                 if ((status) && (p->owner))
504                         pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
505                 p->chan = NULL;
506                 ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
507                 ast_module_user_remove(p->u_chan);
508         } else {
509                 p->owner = NULL;
510                 ast_module_user_remove(p->u_owner);
511         }
512         
513         ast->tech_pvt = NULL;
514         
515         if (!p->owner && !p->chan) {
516                 /* Okay, done with the private part now, too. */
517                 glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);
518                 /* If we have a queue holding, don't actually destroy p yet, but
519                    let local_queue do it. */
520                 if (glaredetect)
521                         ast_set_flag(p, LOCAL_CANCEL_QUEUE);
522                 ast_mutex_unlock(&p->lock);
523                 /* Remove from list */
524                 AST_LIST_LOCK(&locals);
525                 AST_LIST_REMOVE(&locals, p, list);
526                 AST_LIST_UNLOCK(&locals);
527                 /* Grab / release lock just in case */
528                 ast_mutex_lock(&p->lock);
529                 ast_mutex_unlock(&p->lock);
530                 /* And destroy */
531                 if (!glaredetect) {
532                         ast_mutex_destroy(&p->lock);
533                         ast_free(p);
534                 }
535                 return 0;
536         }
537         if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))
538                 /* Need to actually hangup since there is no PBX */
539                 ochan = p->chan;
540         else
541                 res = local_queue_frame(p, isoutbound, &f, NULL);
542         if (!res)
543                 ast_mutex_unlock(&p->lock);
544         if (ochan)
545                 ast_hangup(ochan);
546         return 0;
547 }
548
549 /*! \brief Create a call structure */
550 static struct local_pvt *local_alloc(const char *data, int format)
551 {
552         struct local_pvt *tmp = NULL;
553         char *c = NULL, *opts = NULL;
554
555         if (!(tmp = ast_calloc(1, sizeof(*tmp))))
556                 return NULL;
557
558         /* Initialize private structure information */
559         ast_mutex_init(&tmp->lock);
560         ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
561
562         memcpy(&tmp->jb_conf, &g_jb_conf, sizeof(tmp->jb_conf));
563
564         /* Look for options */
565         if ((opts = strchr(tmp->exten, '/'))) {
566                 *opts++ = '\0';
567                 if (strchr(opts, 'n'))
568                         ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
569                 if (strchr(opts, 'j')) {
570                         if (ast_test_flag(tmp, LOCAL_NO_OPTIMIZATION))
571                                 ast_set_flag(&tmp->jb_conf, AST_JB_ENABLED);
572                         else {
573                                 ast_log(LOG_ERROR, "You must use the 'n' option for chan_local "
574                                         "to use the 'j' option to enable the jitterbuffer\n");
575                         }
576                 }
577         }
578
579         /* Look for a context */
580         if ((c = strchr(tmp->exten, '@')))
581                 *c++ = '\0';
582
583         ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
584
585         tmp->reqformat = format;
586
587         if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
588                 ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
589                 ast_mutex_destroy(&tmp->lock);
590                 ast_free(tmp);
591                 tmp = NULL;
592         } else {
593                 /* Add to list */
594                 AST_LIST_LOCK(&locals);
595                 AST_LIST_INSERT_HEAD(&locals, tmp, list);
596                 AST_LIST_UNLOCK(&locals);
597         }
598         
599         return tmp;
600 }
601
602 /*! \brief Start new local channel */
603 static struct ast_channel *local_new(struct local_pvt *p, int state)
604 {
605         struct ast_channel *tmp = NULL, *tmp2 = NULL;
606         int randnum = ast_random() & 0xffff, fmt = 0;
607         const char *t;
608         int ama;
609
610         /* Allocate two new Asterisk channels */
611         /* safe accountcode */
612         if (p->owner && p->owner->accountcode)
613                 t = p->owner->accountcode;
614         else
615                 t = "";
616
617         if (p->owner)
618                 ama = p->owner->amaflags;
619         else
620                 ama = 0;
621         if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;1", p->exten, p->context, randnum)) 
622                         || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;2", p->exten, p->context, randnum))) {
623                 if (tmp)
624                         ast_channel_free(tmp);
625                 if (tmp2)
626                         ast_channel_free(tmp2);
627                 ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
628                 return NULL;
629         } 
630
631         tmp2->tech = tmp->tech = &local_tech;
632
633         tmp->nativeformats = p->reqformat;
634         tmp2->nativeformats = p->reqformat;
635
636         /* Determine our read/write format and set it on each channel */
637         fmt = ast_best_codec(p->reqformat);
638         tmp->writeformat = fmt;
639         tmp2->writeformat = fmt;
640         tmp->rawwriteformat = fmt;
641         tmp2->rawwriteformat = fmt;
642         tmp->readformat = fmt;
643         tmp2->readformat = fmt;
644         tmp->rawreadformat = fmt;
645         tmp2->rawreadformat = fmt;
646
647         tmp->tech_pvt = p;
648         tmp2->tech_pvt = p;
649
650         p->owner = tmp;
651         p->chan = tmp2;
652         p->u_owner = ast_module_user_add(p->owner);
653         p->u_chan = ast_module_user_add(p->chan);
654
655         ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
656         ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
657         ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
658         tmp->priority = 1;
659         tmp2->priority = 1;
660
661         ast_jb_configure(tmp, &p->jb_conf);
662
663         return tmp;
664 }
665
666
667 /*! \brief Part of PBX interface */
668 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
669 {
670         struct local_pvt *p = NULL;
671         struct ast_channel *chan = NULL;
672
673         /* Allocate a new private structure and then Asterisk channel */
674         if ((p = local_alloc(data, format)))
675                 chan = local_new(p, AST_STATE_DOWN);
676
677         return chan;
678 }
679
680 /*! \brief CLI command "local show channels" */
681 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
682 {
683         struct local_pvt *p = NULL;
684
685         switch (cmd) {
686         case CLI_INIT:
687                 e->command = "local show channels";
688                 e->usage =
689                         "Usage: local show channels\n"
690                         "       Provides summary information on active local proxy channels.\n";
691                 return NULL;
692         case CLI_GENERATE:
693                 return NULL;
694         }
695
696         if (a->argc != 3)
697                 return CLI_SHOWUSAGE;
698
699         AST_LIST_LOCK(&locals);
700         if (!AST_LIST_EMPTY(&locals)) {
701                 AST_LIST_TRAVERSE(&locals, p, list) {
702                         ast_mutex_lock(&p->lock);
703                         ast_cli(a->fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
704                         ast_mutex_unlock(&p->lock);
705                 }
706         } else
707                 ast_cli(a->fd, "No local channels in use\n");
708         AST_LIST_UNLOCK(&locals);
709
710         return CLI_SUCCESS;
711 }
712
713 static struct ast_cli_entry cli_local[] = {
714         AST_CLI_DEFINE(locals_show, "List status of local channels"),
715 };
716
717 /*! \brief Load module into PBX, register channel */
718 static int load_module(void)
719 {
720         /* Make sure we can register our channel type */
721         if (ast_channel_register(&local_tech)) {
722                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
723                 return AST_MODULE_LOAD_FAILURE;
724         }
725         ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
726         return AST_MODULE_LOAD_SUCCESS;
727 }
728
729 /*! \brief Unload the local proxy channel from Asterisk */
730 static int unload_module(void)
731 {
732         struct local_pvt *p = NULL;
733
734         /* First, take us out of the channel loop */
735         ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
736         ast_channel_unregister(&local_tech);
737         if (!AST_LIST_LOCK(&locals)) {
738                 /* Hangup all interfaces if they have an owner */
739                 AST_LIST_TRAVERSE(&locals, p, list) {
740                         if (p->owner)
741                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
742                 }
743                 AST_LIST_UNLOCK(&locals);
744                 AST_LIST_HEAD_DESTROY(&locals);
745         } else {
746                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
747                 return -1;
748         }               
749         return 0;
750 }
751
752 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel");