Merged revisions 99594 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         struct ast_channel_monitor *tmp;
232         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)))
233                 return;
234
235         /* only do the masquerade if we are being called on the outbound channel,
236            if it has been bridged to another channel and if there are no pending
237            frames on the owner channel (because they would be transferred to the
238            outbound channel during the masquerade)
239         */
240         if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) {
241                 /* Masquerade bridged channel into owner */
242                 /* Lock everything we need, one by one, and give up if
243                    we can't get everything.  Remember, we'll get another
244                    chance in just a little bit */
245                 if (!ast_channel_trylock(p->chan->_bridge)) {
246                         if (!ast_check_hangup(p->chan->_bridge)) {
247                                 if (!ast_channel_trylock(p->owner)) {
248                                         if (!ast_check_hangup(p->owner)) {
249                                                 if(p->owner->monitor && !p->chan->_bridge->monitor) {
250                                                         /* If a local channel is being monitored, we don't want a masquerade
251                                                          * to cause the monitor to go away. Since the masquerade swaps the monitors,
252                                                          * pre-swapping the monitors before the masquerade will ensure that the monitor
253                                                          * ends up where it is expected.
254                                                          */
255                                                         tmp = p->owner->monitor;
256                                                         p->owner->monitor = p->chan->_bridge->monitor;
257                                                         p->chan->_bridge->monitor = tmp;
258                                                 }
259                                                 ast_channel_masquerade(p->owner, p->chan->_bridge);
260                                                 ast_set_flag(p, LOCAL_ALREADY_MASQED);
261                                         }
262                                         ast_channel_unlock(p->owner);
263                                 }
264                                 ast_channel_unlock(p->chan->_bridge);
265                         }
266                 }
267         /* We only allow masquerading in one 'direction'... it's important to preserve the state
268            (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan)
269            when the local channels go away.
270         */
271 #if 0
272         } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && AST_LIST_EMPTY(&p->chan->readq)) {
273                 /* Masquerade bridged channel into chan */
274                 if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
275                         if (!ast_check_hangup(p->owner->_bridge)) {
276                                 if (!ast_mutex_trylock(&p->chan->lock)) {
277                                         if (!ast_check_hangup(p->chan)) {
278                                                 ast_channel_masquerade(p->chan, p->owner->_bridge);
279                                                 ast_set_flag(p, LOCAL_ALREADY_MASQED);
280                                         }
281                                         ast_mutex_unlock(&p->chan->lock);
282                                 }
283                         }
284                         ast_mutex_unlock(&(p->owner->_bridge)->lock);
285                 }
286 #endif
287         }
288 }
289
290 static struct ast_frame  *local_read(struct ast_channel *ast)
291 {
292         return &ast_null_frame;
293 }
294
295 static int local_write(struct ast_channel *ast, struct ast_frame *f)
296 {
297         struct local_pvt *p = ast->tech_pvt;
298         int res = -1;
299         int isoutbound;
300
301         if (!p)
302                 return -1;
303
304         /* Just queue for delivery to the other side */
305         ast_mutex_lock(&p->lock);
306         isoutbound = IS_OUTBOUND(ast, p);
307         if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO))
308                 check_bridge(p, isoutbound);
309         if (!ast_test_flag(p, LOCAL_ALREADY_MASQED))
310                 res = local_queue_frame(p, isoutbound, f, ast);
311         else {
312                 ast_debug(1, "Not posting to queue since already masked on '%s'\n", ast->name);
313                 res = 0;
314         }
315         if (!res)
316                 ast_mutex_unlock(&p->lock);
317         return res;
318 }
319
320 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
321 {
322         struct local_pvt *p = newchan->tech_pvt;
323
324         if (!p)
325                 return -1;
326
327         ast_mutex_lock(&p->lock);
328
329         if ((p->owner != oldchan) && (p->chan != oldchan)) {
330                 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
331                 ast_mutex_unlock(&p->lock);
332                 return -1;
333         }
334         if (p->owner == oldchan)
335                 p->owner = newchan;
336         else
337                 p->chan = newchan;
338         ast_mutex_unlock(&p->lock);
339         return 0;
340 }
341
342 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
343 {
344         struct local_pvt *p = ast->tech_pvt;
345         int res = 0;
346         struct ast_frame f = { AST_FRAME_CONTROL, };
347         int isoutbound;
348
349         if (!p)
350                 return -1;
351
352         /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
353         if (condition == AST_CONTROL_HOLD) {
354                 ast_moh_start(ast, data, NULL);
355         } else if (condition == AST_CONTROL_UNHOLD) {
356                 ast_moh_stop(ast);
357         } else {
358                 /* Queue up a frame representing the indication as a control frame */
359                 ast_mutex_lock(&p->lock);
360                 isoutbound = IS_OUTBOUND(ast, p);
361                 f.subclass = condition;
362                 f.data = (void*)data;
363                 f.datalen = datalen;
364                 if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
365                         ast_mutex_unlock(&p->lock);
366         }
367
368         return res;
369 }
370
371 static int local_digit_begin(struct ast_channel *ast, char digit)
372 {
373         struct local_pvt *p = ast->tech_pvt;
374         int res = -1;
375         struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
376         int isoutbound;
377
378         if (!p)
379                 return -1;
380
381         ast_mutex_lock(&p->lock);
382         isoutbound = IS_OUTBOUND(ast, p);
383         f.subclass = digit;
384         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
385                 ast_mutex_unlock(&p->lock);
386
387         return res;
388 }
389
390 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
391 {
392         struct local_pvt *p = ast->tech_pvt;
393         int res = -1;
394         struct ast_frame f = { AST_FRAME_DTMF_END, };
395         int isoutbound;
396
397         if (!p)
398                 return -1;
399
400         ast_mutex_lock(&p->lock);
401         isoutbound = IS_OUTBOUND(ast, p);
402         f.subclass = digit;
403         f.len = duration;
404         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
405                 ast_mutex_unlock(&p->lock);
406
407         return res;
408 }
409
410 static int local_sendtext(struct ast_channel *ast, const char *text)
411 {
412         struct local_pvt *p = ast->tech_pvt;
413         int res = -1;
414         struct ast_frame f = { AST_FRAME_TEXT, };
415         int isoutbound;
416
417         if (!p)
418                 return -1;
419
420         ast_mutex_lock(&p->lock);
421         isoutbound = IS_OUTBOUND(ast, p);
422         f.data = (char *) text;
423         f.datalen = strlen(text) + 1;
424         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
425                 ast_mutex_unlock(&p->lock);
426         return res;
427 }
428
429 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
430 {
431         struct local_pvt *p = ast->tech_pvt;
432         int res = -1;
433         struct ast_frame f = { AST_FRAME_HTML, };
434         int isoutbound;
435
436         if (!p)
437                 return -1;
438         
439         ast_mutex_lock(&p->lock);
440         isoutbound = IS_OUTBOUND(ast, p);
441         f.subclass = subclass;
442         f.data = (char *)data;
443         f.datalen = datalen;
444         if (!(res = local_queue_frame(p, isoutbound, &f, ast)))
445                 ast_mutex_unlock(&p->lock);
446         return res;
447 }
448
449 /*! \brief Initiate new call, part of PBX interface 
450  *      dest is the dial string */
451 static int local_call(struct ast_channel *ast, char *dest, int timeout)
452 {
453         struct local_pvt *p = ast->tech_pvt;
454         int res;
455         struct ast_var_t *varptr = NULL, *new;
456         size_t len, namelen;
457
458         if (!p)
459                 return -1;
460         
461         ast_mutex_lock(&p->lock);
462
463         /*
464          * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
465          * call, so it's done here instead.
466          */
467         p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
468         p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
469         p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
470         p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
471         p->chan->cid.cid_pres = p->owner->cid.cid_pres;
472         ast_string_field_set(p->chan, language, p->owner->language);
473         ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
474         p->chan->cdrflags = p->owner->cdrflags;
475
476         /* copy the channel variables from the incoming channel to the outgoing channel */
477         /* Note that due to certain assumptions, they MUST be in the same order */
478         AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
479                 namelen = strlen(varptr->name);
480                 len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
481                 if ((new = ast_calloc(1, len))) {
482                         memcpy(new, varptr, len);
483                         new->value = &(new->name[0]) + namelen + 1;
484                         AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
485                 }
486         }
487         ast_channel_datastore_inherit(p->owner, p->chan);
488
489         /* Start switch on sub channel */
490         if (!(res = ast_pbx_start(p->chan)))
491                 ast_set_flag(p, LOCAL_LAUNCHED_PBX);
492
493         ast_mutex_unlock(&p->lock);
494         return res;
495 }
496
497 /*! \brief Hangup a call through the local proxy channel */
498 static int local_hangup(struct ast_channel *ast)
499 {
500         struct local_pvt *p = ast->tech_pvt;
501         int isoutbound;
502         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
503         struct ast_channel *ochan = NULL;
504         int glaredetect = 0, res = 0;
505
506         if (!p)
507                 return -1;
508
509         ast_mutex_lock(&p->lock);
510         if (p->chan && ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) 
511                 ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
512         isoutbound = IS_OUTBOUND(ast, p);
513         if (isoutbound) {
514                 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
515                 if ((status) && (p->owner)) {
516                         /* Deadlock avoidance */
517                         while (ast_channel_trylock(p->owner)) {
518                                 ast_mutex_unlock(&p->lock);
519                                 usleep(1);
520                                 ast_mutex_lock(&p->lock);
521                         }
522                         pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
523                         ast_channel_unlock(p->owner);
524                 }
525                 p->chan = NULL;
526                 ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
527                 ast_module_user_remove(p->u_chan);
528         } else {
529                 p->owner = NULL;
530                 ast_module_user_remove(p->u_owner);
531         }
532         
533         ast->tech_pvt = NULL;
534         
535         if (!p->owner && !p->chan) {
536                 /* Okay, done with the private part now, too. */
537                 glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);
538                 /* If we have a queue holding, don't actually destroy p yet, but
539                    let local_queue do it. */
540                 if (glaredetect)
541                         ast_set_flag(p, LOCAL_CANCEL_QUEUE);
542                 ast_mutex_unlock(&p->lock);
543                 /* Remove from list */
544                 AST_LIST_LOCK(&locals);
545                 AST_LIST_REMOVE(&locals, p, list);
546                 AST_LIST_UNLOCK(&locals);
547                 /* Grab / release lock just in case */
548                 ast_mutex_lock(&p->lock);
549                 ast_mutex_unlock(&p->lock);
550                 /* And destroy */
551                 if (!glaredetect) {
552                         ast_mutex_destroy(&p->lock);
553                         ast_free(p);
554                 }
555                 return 0;
556         }
557         if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))
558                 /* Need to actually hangup since there is no PBX */
559                 ochan = p->chan;
560         else
561                 res = local_queue_frame(p, isoutbound, &f, NULL);
562         if (!res)
563                 ast_mutex_unlock(&p->lock);
564         if (ochan)
565                 ast_hangup(ochan);
566         return 0;
567 }
568
569 /*! \brief Create a call structure */
570 static struct local_pvt *local_alloc(const char *data, int format)
571 {
572         struct local_pvt *tmp = NULL;
573         char *c = NULL, *opts = NULL;
574
575         if (!(tmp = ast_calloc(1, sizeof(*tmp))))
576                 return NULL;
577
578         /* Initialize private structure information */
579         ast_mutex_init(&tmp->lock);
580         ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
581
582         memcpy(&tmp->jb_conf, &g_jb_conf, sizeof(tmp->jb_conf));
583
584         /* Look for options */
585         if ((opts = strchr(tmp->exten, '/'))) {
586                 *opts++ = '\0';
587                 if (strchr(opts, 'n'))
588                         ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
589                 if (strchr(opts, 'j')) {
590                         if (ast_test_flag(tmp, LOCAL_NO_OPTIMIZATION))
591                                 ast_set_flag(&tmp->jb_conf, AST_JB_ENABLED);
592                         else {
593                                 ast_log(LOG_ERROR, "You must use the 'n' option for chan_local "
594                                         "to use the 'j' option to enable the jitterbuffer\n");
595                         }
596                 }
597         }
598
599         /* Look for a context */
600         if ((c = strchr(tmp->exten, '@')))
601                 *c++ = '\0';
602
603         ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
604
605         tmp->reqformat = format;
606
607         if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
608                 ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
609                 ast_mutex_destroy(&tmp->lock);
610                 ast_free(tmp);
611                 tmp = NULL;
612         } else {
613                 /* Add to list */
614                 AST_LIST_LOCK(&locals);
615                 AST_LIST_INSERT_HEAD(&locals, tmp, list);
616                 AST_LIST_UNLOCK(&locals);
617         }
618         
619         return tmp;
620 }
621
622 /*! \brief Start new local channel */
623 static struct ast_channel *local_new(struct local_pvt *p, int state)
624 {
625         struct ast_channel *tmp = NULL, *tmp2 = NULL;
626         int randnum = ast_random() & 0xffff, fmt = 0;
627         const char *t;
628         int ama;
629
630         /* Allocate two new Asterisk channels */
631         /* safe accountcode */
632         if (p->owner && p->owner->accountcode)
633                 t = p->owner->accountcode;
634         else
635                 t = "";
636
637         if (p->owner)
638                 ama = p->owner->amaflags;
639         else
640                 ama = 0;
641         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)) 
642                         || !(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))) {
643                 if (tmp)
644                         ast_channel_free(tmp);
645                 if (tmp2)
646                         ast_channel_free(tmp2);
647                 ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
648                 return NULL;
649         } 
650
651         tmp2->tech = tmp->tech = &local_tech;
652
653         tmp->nativeformats = p->reqformat;
654         tmp2->nativeformats = p->reqformat;
655
656         /* Determine our read/write format and set it on each channel */
657         fmt = ast_best_codec(p->reqformat);
658         tmp->writeformat = fmt;
659         tmp2->writeformat = fmt;
660         tmp->rawwriteformat = fmt;
661         tmp2->rawwriteformat = fmt;
662         tmp->readformat = fmt;
663         tmp2->readformat = fmt;
664         tmp->rawreadformat = fmt;
665         tmp2->rawreadformat = fmt;
666
667         tmp->tech_pvt = p;
668         tmp2->tech_pvt = p;
669
670         p->owner = tmp;
671         p->chan = tmp2;
672         p->u_owner = ast_module_user_add(p->owner);
673         p->u_chan = ast_module_user_add(p->chan);
674
675         ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
676         ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
677         ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
678         tmp->priority = 1;
679         tmp2->priority = 1;
680
681         ast_jb_configure(tmp, &p->jb_conf);
682
683         return tmp;
684 }
685
686
687 /*! \brief Part of PBX interface */
688 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
689 {
690         struct local_pvt *p = NULL;
691         struct ast_channel *chan = NULL;
692
693         /* Allocate a new private structure and then Asterisk channel */
694         if ((p = local_alloc(data, format)))
695                 chan = local_new(p, AST_STATE_DOWN);
696
697         return chan;
698 }
699
700 /*! \brief CLI command "local show channels" */
701 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
702 {
703         struct local_pvt *p = NULL;
704
705         switch (cmd) {
706         case CLI_INIT:
707                 e->command = "local show channels";
708                 e->usage =
709                         "Usage: local show channels\n"
710                         "       Provides summary information on active local proxy channels.\n";
711                 return NULL;
712         case CLI_GENERATE:
713                 return NULL;
714         }
715
716         if (a->argc != 3)
717                 return CLI_SHOWUSAGE;
718
719         AST_LIST_LOCK(&locals);
720         if (!AST_LIST_EMPTY(&locals)) {
721                 AST_LIST_TRAVERSE(&locals, p, list) {
722                         ast_mutex_lock(&p->lock);
723                         ast_cli(a->fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
724                         ast_mutex_unlock(&p->lock);
725                 }
726         } else
727                 ast_cli(a->fd, "No local channels in use\n");
728         AST_LIST_UNLOCK(&locals);
729
730         return CLI_SUCCESS;
731 }
732
733 static struct ast_cli_entry cli_local[] = {
734         AST_CLI_DEFINE(locals_show, "List status of local channels"),
735 };
736
737 /*! \brief Load module into PBX, register channel */
738 static int load_module(void)
739 {
740         /* Make sure we can register our channel type */
741         if (ast_channel_register(&local_tech)) {
742                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
743                 return AST_MODULE_LOAD_FAILURE;
744         }
745         ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
746         return AST_MODULE_LOAD_SUCCESS;
747 }
748
749 /*! \brief Unload the local proxy channel from Asterisk */
750 static int unload_module(void)
751 {
752         struct local_pvt *p = NULL;
753
754         /* First, take us out of the channel loop */
755         ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
756         ast_channel_unregister(&local_tech);
757         if (!AST_LIST_LOCK(&locals)) {
758                 /* Hangup all interfaces if they have an owner */
759                 AST_LIST_TRAVERSE(&locals, p, list) {
760                         if (p->owner)
761                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
762                 }
763                 AST_LIST_UNLOCK(&locals);
764                 AST_LIST_HEAD_DESTROY(&locals);
765         } else {
766                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
767                 return -1;
768         }               
769         return 0;
770 }
771
772 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel (Note: used internally by other modules)");