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