Merged revisions 49568 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);
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)
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         res = local_queue_frame(p, isoutbound, &f, ast);
385         ast_mutex_unlock(&p->lock);
386         
387         return res;
388 }
389
390 static int local_sendtext(struct ast_channel *ast, const char *text)
391 {
392         struct local_pvt *p = ast->tech_pvt;
393         int res = -1;
394         struct ast_frame f = { AST_FRAME_TEXT, };
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.data = (char *) text;
403         f.datalen = strlen(text) + 1;
404         res = local_queue_frame(p, isoutbound, &f, ast);
405         ast_mutex_unlock(&p->lock);
406         return res;
407 }
408
409 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
410 {
411         struct local_pvt *p = ast->tech_pvt;
412         int res = -1;
413         struct ast_frame f = { AST_FRAME_HTML, };
414         int isoutbound;
415
416         if (!p)
417                 return -1;
418         
419         ast_mutex_lock(&p->lock);
420         isoutbound = IS_OUTBOUND(ast, p);
421         f.subclass = subclass;
422         f.data = (char *)data;
423         f.datalen = datalen;
424         res = local_queue_frame(p, isoutbound, &f, ast);
425         ast_mutex_unlock(&p->lock);
426         return res;
427 }
428
429 /*! \brief Initiate new call, part of PBX interface 
430  *      dest is the dial string */
431 static int local_call(struct ast_channel *ast, char *dest, int timeout)
432 {
433         struct local_pvt *p = ast->tech_pvt;
434         int res;
435         struct ast_var_t *varptr = NULL, *new;
436         size_t len, namelen;
437
438         if (!p)
439                 return -1;
440         
441         ast_mutex_lock(&p->lock);
442
443         p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
444         p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
445         p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
446         p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
447         p->chan->cid.cid_pres = p->owner->cid.cid_pres;
448         ast_string_field_set(p->chan, language, p->owner->language);
449         ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
450         p->chan->cdrflags = p->owner->cdrflags;
451
452         /* copy the channel variables from the incoming channel to the outgoing channel */
453         /* Note that due to certain assumptions, they MUST be in the same order */
454         AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
455                 namelen = strlen(varptr->name);
456                 len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
457                 if ((new = ast_calloc(1, len))) {
458                         memcpy(new, varptr, len);
459                         new->value = &(new->name[0]) + namelen + 1;
460                         AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
461                 }
462         }
463
464         ast_set_flag(p, LOCAL_LAUNCHED_PBX);
465
466         /* Start switch on sub channel */
467         res = ast_pbx_start(p->chan);
468         ast_mutex_unlock(&p->lock);
469         return res;
470 }
471
472 /*! \brief Hangup a call through the local proxy channel */
473 static int local_hangup(struct ast_channel *ast)
474 {
475         struct local_pvt *p = ast->tech_pvt;
476         int isoutbound;
477         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
478         struct ast_channel *ochan = NULL;
479         int glaredetect = 0;
480
481         if (!p)
482                 return -1;
483
484         ast_mutex_lock(&p->lock);
485         isoutbound = IS_OUTBOUND(ast, p);
486         if (isoutbound) {
487                 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
488                 if ((status) && (p->owner))
489                         pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
490                 p->chan = NULL;
491                 ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
492                 ast_module_user_remove(p->u_chan);
493         } else {
494                 p->owner = NULL;
495                 ast_module_user_remove(p->u_owner);
496         }
497         
498         ast->tech_pvt = NULL;
499         
500         if (!p->owner && !p->chan) {
501                 /* Okay, done with the private part now, too. */
502                 glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);
503                 /* If we have a queue holding, don't actually destroy p yet, but
504                    let local_queue do it. */
505                 if (glaredetect)
506                         ast_set_flag(p, LOCAL_CANCEL_QUEUE);
507                 ast_mutex_unlock(&p->lock);
508                 /* Remove from list */
509                 AST_LIST_LOCK(&locals);
510                 AST_LIST_REMOVE(&locals, p, list);
511                 AST_LIST_UNLOCK(&locals);
512                 /* Grab / release lock just in case */
513                 ast_mutex_lock(&p->lock);
514                 ast_mutex_unlock(&p->lock);
515                 /* And destroy */
516                 if (!glaredetect) {
517                         ast_mutex_destroy(&p->lock);
518                         free(p);
519                 }
520                 return 0;
521         }
522         if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))
523                 /* Need to actually hangup since there is no PBX */
524                 ochan = p->chan;
525         else
526                 local_queue_frame(p, isoutbound, &f, NULL);
527         ast_mutex_unlock(&p->lock);
528         if (ochan)
529                 ast_hangup(ochan);
530         return 0;
531 }
532
533 /*! \brief Create a call structure */
534 static struct local_pvt *local_alloc(const char *data, int format)
535 {
536         struct local_pvt *tmp = NULL;
537         char *c = NULL, *opts = NULL;
538
539         if (!(tmp = ast_calloc(1, sizeof(*tmp))))
540                 return NULL;
541
542         /* Initialize private structure information */
543         ast_mutex_init(&tmp->lock);
544         ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
545
546         /* Look for options */
547         if ((opts = strchr(tmp->exten, '/'))) {
548                 *opts++ = '\0';
549                 if (strchr(opts, 'n'))
550                         ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
551         }
552
553         /* Look for a context */
554         if ((c = strchr(tmp->exten, '@')))
555                 *c++ = '\0';
556
557         ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
558
559         tmp->reqformat = format;
560
561         if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
562                 ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
563                 ast_mutex_destroy(&tmp->lock);
564                 free(tmp);
565                 tmp = NULL;
566         } else {
567                 /* Add to list */
568                 AST_LIST_LOCK(&locals);
569                 AST_LIST_INSERT_HEAD(&locals, tmp, list);
570                 AST_LIST_UNLOCK(&locals);
571         }
572         
573         return tmp;
574 }
575
576 /*! \brief Start new local channel */
577 static struct ast_channel *local_new(struct local_pvt *p, int state)
578 {
579         struct ast_channel *tmp = NULL, *tmp2 = NULL;
580         int randnum = ast_random() & 0xffff, fmt = 0;
581
582         /* Allocate two new Asterisk channels */
583         if (!(tmp = ast_channel_alloc(1, state, 0, 0, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 
584                         || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {
585                 if (tmp)
586                         ast_channel_free(tmp);
587                 if (tmp2)
588                         ast_channel_free(tmp2);
589                 ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
590                 return NULL;
591         } 
592
593         tmp2->tech = tmp->tech = &local_tech;
594
595         tmp->nativeformats = p->reqformat;
596         tmp2->nativeformats = p->reqformat;
597
598         /* Determine our read/write format and set it on each channel */
599         fmt = ast_best_codec(p->reqformat);
600         tmp->writeformat = fmt;
601         tmp2->writeformat = fmt;
602         tmp->rawwriteformat = fmt;
603         tmp2->rawwriteformat = fmt;
604         tmp->readformat = fmt;
605         tmp2->readformat = fmt;
606         tmp->rawreadformat = fmt;
607         tmp2->rawreadformat = fmt;
608
609         tmp->tech_pvt = p;
610         tmp2->tech_pvt = p;
611
612         p->owner = tmp;
613         p->chan = tmp2;
614         p->u_owner = ast_module_user_add(p->owner);
615         p->u_chan = ast_module_user_add(p->chan);
616
617         ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
618         ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
619         ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
620         tmp->priority = 1;
621         tmp2->priority = 1;
622
623         return tmp;
624 }
625
626
627 /*! \brief Part of PBX interface */
628 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
629 {
630         struct local_pvt *p = NULL;
631         struct ast_channel *chan = NULL;
632
633         /* Allocate a new private structure and then Asterisk channel */
634         if ((p = local_alloc(data, format)))
635                 chan = local_new(p, AST_STATE_DOWN);
636
637         return chan;
638 }
639
640 /*! \brief CLI command "local show channels" */
641 static int locals_show(int fd, int argc, char **argv)
642 {
643         struct local_pvt *p = NULL;
644
645         if (argc != 3)
646                 return RESULT_SHOWUSAGE;
647
648         AST_LIST_LOCK(&locals);
649         if (!AST_LIST_EMPTY(&locals)) {
650                 AST_LIST_TRAVERSE(&locals, p, list) {
651                         ast_mutex_lock(&p->lock);
652                         ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
653                         ast_mutex_unlock(&p->lock);
654                 }
655         } else
656                 ast_cli(fd, "No local channels in use\n");
657         AST_LIST_UNLOCK(&locals);
658
659         return RESULT_SUCCESS;
660 }
661
662 static const char show_locals_usage[] = 
663 "Usage: local show channels\n"
664 "       Provides summary information on active local proxy channels.\n";
665
666 static struct ast_cli_entry cli_local[] = {
667         { { "local", "show", "channels", NULL },
668         locals_show, "List status of local channels",
669         show_locals_usage },
670 };
671
672 /*! \brief Load module into PBX, register channel */
673 static int load_module(void)
674 {
675         /* Make sure we can register our channel type */
676         if (ast_channel_register(&local_tech)) {
677                 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
678                 return -1;
679         }
680         ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
681         return 0;
682 }
683
684 /*! \brief Unload the local proxy channel from Asterisk */
685 static int unload_module(void)
686 {
687         struct local_pvt *p = NULL;
688
689         /* First, take us out of the channel loop */
690         ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
691         ast_channel_unregister(&local_tech);
692         if (!AST_LIST_LOCK(&locals)) {
693                 /* Hangup all interfaces if they have an owner */
694                 AST_LIST_TRAVERSE(&locals, p, list) {
695                         if (p->owner)
696                                 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
697                 }
698                 AST_LIST_UNLOCK(&locals);
699                 AST_LIST_HEAD_DESTROY(&locals);
700         } else {
701                 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
702                 return -1;
703         }               
704         return 0;
705 }
706
707 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel");