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