Merged revisions 55954 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 <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
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         if (option_debug > 2)
145                 ast_log(LOG_DEBUG, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
146         res = ast_exists_extension(NULL, context, exten, 1, NULL);
147         if (!res)               
148                 return AST_DEVICE_INVALID;
149         else
150                 return AST_DEVICE_UNKNOWN;
151 }
152
153 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us)
154 {
155         struct ast_channel *other = NULL;
156
157 retrylock:              
158
159         /* Recalculate outbound channel */
160         other = isoutbound ? p->owner : p->chan;
161
162         /* Set glare detection */
163         ast_set_flag(p, LOCAL_GLARE_DETECT);
164         if (ast_test_flag(p, LOCAL_CANCEL_QUEUE)) {
165                 /* We had a glare on the hangup.  Forget all this business,
166                 return and destroy p.  */
167                 ast_mutex_unlock(&p->lock);
168                 ast_mutex_destroy(&p->lock);
169                 free(p);
170                 return -1;
171         }
172         if (!other) {
173                 ast_clear_flag(p, LOCAL_GLARE_DETECT);
174                 return 0;
175         }
176         if (ast_mutex_trylock(&other->lock)) {
177                 /* Failed to lock.  Release main lock and try again */
178                 ast_mutex_unlock(&p->lock);
179                 if (us) {
180                         if (ast_mutex_unlock(&us->lock)) {
181                                 ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
182                                         us->name, f->frametype, f->subclass);
183                                 us = NULL;
184                         }
185                 }
186                 /* Wait just a bit */
187                 usleep(1);
188                 /* Only we can destroy ourselves, so we can't disappear here */
189                 if (us)
190                         ast_mutex_lock(&us->lock);
191                 ast_mutex_lock(&p->lock);
192                 goto retrylock;
193         }
194         ast_queue_frame(other, f);
195         ast_mutex_unlock(&other->lock);
196         ast_clear_flag(p, LOCAL_GLARE_DETECT);
197         return 0;
198 }
199
200 static int local_answer(struct ast_channel *ast)
201 {
202         struct local_pvt *p = ast->tech_pvt;
203         int isoutbound;
204         int res = -1;
205
206         if (!p)
207                 return -1;
208
209         ast_mutex_lock(&p->lock);
210         isoutbound = IS_OUTBOUND(ast, p);
211         if (isoutbound) {
212                 /* Pass along answer since somebody answered us */
213                 struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
214                 res = local_queue_frame(p, isoutbound, &answer, ast);
215         } else
216                 ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
217         ast_mutex_unlock(&p->lock);
218         return res;
219 }
220
221 static void check_bridge(struct local_pvt *p, int isoutbound)
222 {
223         if (ast_test_flag(p, LOCAL_ALREADY_MASQED) || ast_test_flag(p, LOCAL_NO_OPTIMIZATION) || !p->chan || !p->owner)
224                 return;
225
226         /* only do the masquerade if we are being called on the outbound channel,
227            if it has been bridged to another channel and if there are no pending
228            frames on the owner channel (because they would be transferred to the
229            outbound channel during the masquerade)
230         */
231         if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) {
232                 /* Masquerade bridged channel into owner */
233                 /* Lock everything we need, one by one, and give up if
234                    we can't get everything.  Remember, we'll get another
235                    chance in just a little bit */
236                 if (!ast_mutex_trylock(&(p->chan->_bridge)->lock)) {
237                         if (!p->chan->_bridge->_softhangup) {
238                                 if (!ast_mutex_trylock(&p->owner->lock)) {
239                                         if (!p->owner->_softhangup) {
240                                                 ast_channel_masquerade(p->owner, p->chan->_bridge);
241                                                 ast_set_flag(p, LOCAL_ALREADY_MASQED);
242                                         }
243                                         ast_mutex_unlock(&p->owner->lock);
244                                 }
245                                 ast_mutex_unlock(&(p->chan->_bridge)->lock);
246                         }
247                 }
248         /* We only allow masquerading in one 'direction'... it's important to preserve the state
249            (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan)
250            when the local channels go away.
251         */
252 #if 0
253         } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && AST_LIST_EMPTY(&p->chan->readq)) {
254                 /* Masquerade bridged channel into chan */
255                 if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
256                         if (!p->owner->_bridge->_softhangup) {
257                                 if (!ast_mutex_trylock(&p->chan->lock)) {
258                                         if (!p->chan->_softhangup) {
259                                                 ast_channel_masquerade(p->chan, p->owner->_bridge);
260                                                 ast_set_flag(p, LOCAL_ALREADY_MASQED);
261                                         }
262                                         ast_mutex_unlock(&p->chan->lock);
263                                 }
264                         }
265                         ast_mutex_unlock(&(p->owner->_bridge)->lock);
266                 }
267 #endif
268         }
269 }
270
271 static struct ast_frame  *local_read(struct ast_channel *ast)
272 {
273         return &ast_null_frame;
274 }
275
276 static int local_write(struct ast_channel *ast, struct ast_frame *f)
277 {
278         struct local_pvt *p = ast->tech_pvt;
279         int res = -1;
280         int isoutbound;
281
282         if (!p)
283                 return -1;
284
285         /* Just queue for delivery to the other side */
286         ast_mutex_lock(&p->lock);
287         isoutbound = IS_OUTBOUND(ast, p);
288         if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO))
289                 check_bridge(p, isoutbound);
290         if (!ast_test_flag(p, LOCAL_ALREADY_MASQED))
291                 res = local_queue_frame(p, isoutbound, f, ast);
292         else {
293                 if (option_debug)
294                         ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name);
295                 res = 0;
296         }
297         ast_mutex_unlock(&p->lock);
298         return res;
299 }
300
301 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
302 {
303         struct local_pvt *p = newchan->tech_pvt;
304
305         if (!p)
306                 return -1;
307
308         ast_mutex_lock(&p->lock);
309
310         if ((p->owner != oldchan) && (p->chan != oldchan)) {
311                 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
312                 ast_mutex_unlock(&p->lock);
313                 return -1;
314         }
315         if (p->owner == oldchan)
316                 p->owner = newchan;
317         else
318                 p->chan = newchan;
319         ast_mutex_unlock(&p->lock);
320         return 0;
321 }
322
323 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
324 {
325         struct local_pvt *p = ast->tech_pvt;
326         int res = 0;
327         struct ast_frame f = { AST_FRAME_CONTROL, };
328         int isoutbound;
329
330         if (!p)
331                 return -1;
332
333         /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
334         if (condition == AST_CONTROL_HOLD) {
335                 ast_moh_start(ast, data, NULL);
336         } else if (condition == AST_CONTROL_UNHOLD) {
337                 ast_moh_stop(ast);
338         } else {
339                 /* Queue up a frame representing the indication as a control frame */
340                 ast_mutex_lock(&p->lock);
341                 isoutbound = IS_OUTBOUND(ast, p);
342                 f.subclass = condition;
343                 f.data = (void*)data;
344                 f.datalen = datalen;
345                 res = local_queue_frame(p, isoutbound, &f, ast);
346                 ast_mutex_unlock(&p->lock);
347         }
348
349         return res;
350 }
351
352 static int local_digit_begin(struct ast_channel *ast, char digit)
353 {
354         struct local_pvt *p = ast->tech_pvt;
355         int res = -1;
356         struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
357         int isoutbound;
358
359         if (!p)
360                 return -1;
361
362         ast_mutex_lock(&p->lock);
363         isoutbound = IS_OUTBOUND(ast, p);
364         f.subclass = digit;
365         res = local_queue_frame(p, isoutbound, &f, ast);
366         ast_mutex_unlock(&p->lock);
367
368         return res;
369 }
370
371 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
372 {
373         struct local_pvt *p = ast->tech_pvt;
374         int res = -1;
375         struct ast_frame f = { AST_FRAME_DTMF_END, };
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         f.len = duration;
385         res = local_queue_frame(p, isoutbound, &f, ast);
386         ast_mutex_unlock(&p->lock);
387         
388         return res;
389 }
390
391 static int local_sendtext(struct ast_channel *ast, const char *text)
392 {
393         struct local_pvt *p = ast->tech_pvt;
394         int res = -1;
395         struct ast_frame f = { AST_FRAME_TEXT, };
396         int isoutbound;
397
398         if (!p)
399                 return -1;
400
401         ast_mutex_lock(&p->lock);
402         isoutbound = IS_OUTBOUND(ast, p);
403         f.data = (char *) text;
404         f.datalen = strlen(text) + 1;
405         res = local_queue_frame(p, isoutbound, &f, ast);
406         ast_mutex_unlock(&p->lock);
407         return res;
408 }
409
410 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
411 {
412         struct local_pvt *p = ast->tech_pvt;
413         int res = -1;
414         struct ast_frame f = { AST_FRAME_HTML, };
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.subclass = subclass;
423         f.data = (char *)data;
424         f.datalen = datalen;
425         res = local_queue_frame(p, isoutbound, &f, ast);
426         ast_mutex_unlock(&p->lock);
427         return res;
428 }
429
430 /*! \brief Initiate new call, part of PBX interface 
431  *      dest is the dial string */
432 static int local_call(struct ast_channel *ast, char *dest, int timeout)
433 {
434         struct local_pvt *p = ast->tech_pvt;
435         int res;
436         struct ast_var_t *varptr = NULL, *new;
437         size_t len, namelen;
438
439         if (!p)
440                 return -1;
441         
442         ast_mutex_lock(&p->lock);
443
444         p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
445         p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
446         p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
447         p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
448         p->chan->cid.cid_pres = p->owner->cid.cid_pres;
449         ast_string_field_set(p->chan, language, p->owner->language);
450         ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
451         p->chan->cdrflags = p->owner->cdrflags;
452
453         /* copy the channel variables from the incoming channel to the outgoing channel */
454         /* Note that due to certain assumptions, they MUST be in the same order */
455         AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
456                 namelen = strlen(varptr->name);
457                 len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
458                 if ((new = ast_calloc(1, len))) {
459                         memcpy(new, varptr, len);
460                         new->value = &(new->name[0]) + namelen + 1;
461                         AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
462                 }
463         }
464
465         ast_set_flag(p, LOCAL_LAUNCHED_PBX);
466
467         /* Start switch on sub channel */
468         res = ast_pbx_start(p->chan);
469         ast_mutex_unlock(&p->lock);
470         return res;
471 }
472
473 /*! \brief Hangup a call through the local proxy channel */
474 static int local_hangup(struct ast_channel *ast)
475 {
476         struct local_pvt *p = ast->tech_pvt;
477         int isoutbound;
478         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
479         struct ast_channel *ochan = NULL;
480         int glaredetect = 0;
481
482         if (!p)
483                 return -1;
484
485         ast_mutex_lock(&p->lock);
486         isoutbound = IS_OUTBOUND(ast, p);
487         if (isoutbound) {
488                 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
489                 if ((status) && (p->owner))
490                         pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
491                 p->chan = NULL;
492                 ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
493                 ast_module_user_remove(p->u_chan);
494         } else {
495                 p->owner = NULL;
496                 ast_module_user_remove(p->u_owner);
497         }
498         
499         ast->tech_pvt = NULL;
500         
501         if (!p->owner && !p->chan) {
502                 /* Okay, done with the private part now, too. */
503                 glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);
504                 /* If we have a queue holding, don't actually destroy p yet, but
505                    let local_queue do it. */
506                 if (glaredetect)
507                         ast_set_flag(p, LOCAL_CANCEL_QUEUE);
508                 ast_mutex_unlock(&p->lock);
509                 /* Remove from list */
510                 AST_LIST_LOCK(&locals);
511                 AST_LIST_REMOVE(&locals, p, list);
512                 AST_LIST_UNLOCK(&locals);
513                 /* Grab / release lock just in case */
514                 ast_mutex_lock(&p->lock);
515                 ast_mutex_unlock(&p->lock);
516                 /* And destroy */
517                 if (!glaredetect) {
518                         ast_mutex_destroy(&p->lock);
519                         free(p);
520                 }
521                 return 0;
522         }
523         if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))
524                 /* Need to actually hangup since there is no PBX */
525                 ochan = p->chan;
526         else
527                 local_queue_frame(p, isoutbound, &f, NULL);
528         ast_mutex_unlock(&p->lock);
529         if (ochan)
530                 ast_hangup(ochan);
531         return 0;
532 }
533
534 /*! \brief Create a call structure */
535 static struct local_pvt *local_alloc(const char *data, int format)
536 {
537         struct local_pvt *tmp = NULL;
538         char *c = NULL, *opts = NULL;
539
540         if (!(tmp = ast_calloc(1, sizeof(*tmp))))
541                 return NULL;
542
543         /* Initialize private structure information */
544         ast_mutex_init(&tmp->lock);
545         ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
546
547         /* Look for options */
548         if ((opts = strchr(tmp->exten, '/'))) {
549                 *opts++ = '\0';
550                 if (strchr(opts, 'n'))
551                         ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
552         }
553
554         /* Look for a context */
555         if ((c = strchr(tmp->exten, '@')))
556                 *c++ = '\0';
557
558         ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
559
560         tmp->reqformat = format;
561
562         if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
563                 ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
564                 ast_mutex_destroy(&tmp->lock);
565                 free(tmp);
566                 tmp = NULL;
567         } else {
568                 /* Add to list */
569                 AST_LIST_LOCK(&locals);
570                 AST_LIST_INSERT_HEAD(&locals, tmp, list);
571                 AST_LIST_UNLOCK(&locals);
572         }
573         
574         return tmp;
575 }
576
577 /*! \brief Start new local channel */
578 static struct ast_channel *local_new(struct local_pvt *p, int state)
579 {
580         struct ast_channel *tmp = NULL, *tmp2 = NULL;
581         int randnum = ast_random() & 0xffff, fmt = 0;
582
583         /* Allocate two new Asterisk channels */
584         if (!(tmp = ast_channel_alloc(1, state, 0, 0, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 
585                         || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {
586                 if (tmp)
587                         ast_channel_free(tmp);
588                 if (tmp2)
589                         ast_channel_free(tmp2);
590                 ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
591                 return NULL;
592         } 
593
594         tmp2->tech = tmp->tech = &local_tech;
595
596         tmp->nativeformats = p->reqformat;
597         tmp2->nativeformats = p->reqformat;
598
599         /* Determine our read/write format and set it on each channel */
600         fmt = ast_best_codec(p->reqformat);
601         tmp->writeformat = fmt;
602         tmp2->writeformat = fmt;
603         tmp->rawwriteformat = fmt;
604         tmp2->rawwriteformat = fmt;
605         tmp->readformat = fmt;
606         tmp2->readformat = fmt;
607         tmp->rawreadformat = fmt;
608         tmp2->rawreadformat = fmt;
609
610         tmp->tech_pvt = p;
611         tmp2->tech_pvt = p;
612
613         p->owner = tmp;
614         p->chan = tmp2;
615         p->u_owner = ast_module_user_add(p->owner);
616         p->u_chan = ast_module_user_add(p->chan);
617
618         ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
619         ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
620         ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
621         tmp->priority = 1;
622         tmp2->priority = 1;
623
624         return tmp;
625 }
626
627
628 /*! \brief Part of PBX interface */
629 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
630 {
631         struct local_pvt *p = NULL;
632         struct ast_channel *chan = NULL;
633
634         /* Allocate a new private structure and then Asterisk channel */
635         if ((p = local_alloc(data, format)))
636                 chan = local_new(p, AST_STATE_DOWN);
637
638         return chan;
639 }
640
641 /*! \brief CLI command "local show channels" */
642 static int locals_show(int fd, int argc, char **argv)
643 {
644         struct local_pvt *p = NULL;
645
646         if (argc != 3)
647                 return RESULT_SHOWUSAGE;
648
649         AST_LIST_LOCK(&locals);
650         if (!AST_LIST_EMPTY(&locals)) {
651                 AST_LIST_TRAVERSE(&locals, p, list) {
652                         ast_mutex_lock(&p->lock);
653                         ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
654                         ast_mutex_unlock(&p->lock);
655                 }
656         } else
657                 ast_cli(fd, "No local channels in use\n");
658         AST_LIST_UNLOCK(&locals);
659
660         return RESULT_SUCCESS;
661 }
662
663 static const char show_locals_usage[] = 
664 "Usage: local show channels\n"
665 "       Provides summary information on active local proxy channels.\n";
666
667 static struct ast_cli_entry cli_local[] = {
668         { { "local", "show", "channels", NULL },
669         locals_show, "List status of local channels",
670         show_locals_usage },
671 };
672
673 /*! \brief Load module into PBX, register channel */
674 static int load_module(void)
675 {
676         /* Make sure we can register our channel type */
677         if (ast_channel_register(&local_tech)) {
678                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
679                 return -1;
680         }
681         ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
682         return 0;
683 }
684
685 /*! \brief Unload the local proxy channel from Asterisk */
686 static int unload_module(void)
687 {
688         struct local_pvt *p = NULL;
689
690         /* First, take us out of the channel loop */
691         ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
692         ast_channel_unregister(&local_tech);
693         if (!AST_LIST_LOCK(&locals)) {
694                 /* Hangup all interfaces if they have an owner */
695                 AST_LIST_TRAVERSE(&locals, p, list) {
696                         if (p->owner)
697                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
698                 }
699                 AST_LIST_UNLOCK(&locals);
700                 AST_LIST_HEAD_DESTROY(&locals);
701         } else {
702                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
703                 return -1;
704         }               
705         return 0;
706 }
707
708 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel");