2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \author Mark Spencer <markster@digium.com>
23 * \brief Local Proxy Channel
25 * \ingroup channel_drivers
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33 #include <sys/signal.h>
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/acl.h"
43 #include "asterisk/callerid.h"
44 #include "asterisk/file.h"
45 #include "asterisk/cli.h"
46 #include "asterisk/app.h"
47 #include "asterisk/musiconhold.h"
48 #include "asterisk/manager.h"
49 #include "asterisk/stringfields.h"
50 #include "asterisk/devicestate.h"
52 static const char tdesc[] = "Local Proxy Channel Driver";
54 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
56 static struct ast_jb_conf g_jb_conf = {
59 .resync_threshold = -1,
63 static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
64 static int local_digit_begin(struct ast_channel *ast, char digit);
65 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
66 static int local_call(struct ast_channel *ast, char *dest, int timeout);
67 static int local_hangup(struct ast_channel *ast);
68 static int local_answer(struct ast_channel *ast);
69 static struct ast_frame *local_read(struct ast_channel *ast);
70 static int local_write(struct ast_channel *ast, struct ast_frame *f);
71 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
72 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
73 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
74 static int local_sendtext(struct ast_channel *ast, const char *text);
75 static int local_devicestate(void *data);
76 static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
78 /* PBX interface structure for channel registration */
79 static const struct ast_channel_tech local_tech = {
83 .requester = local_request,
84 .send_digit_begin = local_digit_begin,
85 .send_digit_end = local_digit_end,
87 .hangup = local_hangup,
88 .answer = local_answer,
91 .write_video = local_write,
92 .exception = local_read,
93 .indicate = local_indicate,
95 .send_html = local_sendhtml,
96 .send_text = local_sendtext,
97 .devicestate = local_devicestate,
98 .bridged_channel = local_bridgedchannel,
101 /*! \brief the local pvt structure for all channels
103 The local channel pvt has two ast_chan objects - the "owner" and the "next channel", the outbound channel
105 ast_chan owner -> local_pvt -> ast_chan chan -> yet-another-pvt-depending-on-channel-type
109 ast_mutex_t lock; /*!< Channel private lock */
110 unsigned int flags; /*!< Private flags */
111 char context[AST_MAX_CONTEXT]; /*!< Context to call */
112 char exten[AST_MAX_EXTENSION]; /*!< Extension to call */
113 int reqformat; /*!< Requested format */
114 struct ast_jb_conf jb_conf; /*!< jitterbuffer configuration for this local channel */
115 struct ast_channel *owner; /*!< Master Channel - Bridging happens here */
116 struct ast_channel *chan; /*!< Outbound channel - PBX is run here */
117 struct ast_module_user *u_owner; /*!< reference to keep the module loaded while in use */
118 struct ast_module_user *u_chan; /*!< reference to keep the module loaded while in use */
119 AST_LIST_ENTRY(local_pvt) list; /*!< Next entity */
122 #define LOCAL_GLARE_DETECT (1 << 0) /*!< Detect glare on hangup */
123 #define LOCAL_CANCEL_QUEUE (1 << 1) /*!< Cancel queue */
124 #define LOCAL_ALREADY_MASQED (1 << 2) /*!< Already masqueraded */
125 #define LOCAL_LAUNCHED_PBX (1 << 3) /*!< PBX was launched */
126 #define LOCAL_NO_OPTIMIZATION (1 << 4) /*!< Do not optimize using masquerading */
127 #define LOCAL_BRIDGE (1 << 5) /*!< Report back the "true" channel as being bridged to */
128 #define LOCAL_MOH_PASSTHRU (1 << 6) /*!< Pass through music on hold start/stop frames */
130 static AST_LIST_HEAD_STATIC(locals, local_pvt);
132 /*! \brief Adds devicestate to local channels */
133 static int local_devicestate(void *data)
135 char *exten = ast_strdupa(data);
136 char *context = NULL, *opts = NULL;
138 struct local_pvt *lp;
140 if (!(context = strchr(exten, '@'))) {
141 ast_log(LOG_WARNING, "Someone used Local/%s somewhere without a @context. This is bad.\n", exten);
142 return AST_DEVICE_INVALID;
147 /* Strip options if they exist */
148 if ((opts = strchr(context, '/')))
151 ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
153 res = ast_exists_extension(NULL, context, exten, 1, NULL);
155 return AST_DEVICE_INVALID;
157 res = AST_DEVICE_NOT_INUSE;
158 AST_LIST_LOCK(&locals);
159 AST_LIST_TRAVERSE(&locals, lp, list) {
160 if (!strcmp(exten, lp->exten) && !strcmp(context, lp->context) && lp->owner) {
161 res = AST_DEVICE_INUSE;
165 AST_LIST_UNLOCK(&locals);
171 * \note Assumes the pvt is no longer in the pvts list
173 static struct local_pvt *local_pvt_destroy(struct local_pvt *pvt)
175 ast_mutex_destroy(&pvt->lock);
180 /*! \brief Return the bridged channel of a Local channel */
181 static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
183 struct local_pvt *p = bridge->tech_pvt;
184 struct ast_channel *bridged = bridge;
187 ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning <none>\n",
188 chan->name, bridge->name);
192 ast_mutex_lock(&p->lock);
194 if (ast_test_flag(p, LOCAL_BRIDGE)) {
195 /* Find the opposite channel */
196 bridged = (bridge == p->owner ? p->chan : p->owner);
198 /* Now see if the opposite channel is bridged to anything */
201 } else if (bridged->_bridge) {
202 bridged = bridged->_bridge;
206 ast_mutex_unlock(&p->lock);
211 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f,
212 struct ast_channel *us, int us_locked)
214 struct ast_channel *other = NULL;
216 /* Recalculate outbound channel */
217 other = isoutbound ? p->owner : p->chan;
223 /* do not queue frame if generator is on both local channels */
224 if (us && us->generator && other->generator) {
228 /* Set glare detection */
229 ast_set_flag(p, LOCAL_GLARE_DETECT);
231 /* Ensure that we have both channels locked */
232 while (other && ast_channel_trylock(other)) {
233 ast_mutex_unlock(&p->lock);
234 if (us && us_locked) {
236 CHANNEL_DEADLOCK_AVOIDANCE(us);
237 } while (ast_mutex_trylock(&p->lock));
240 ast_mutex_lock(&p->lock);
242 other = isoutbound ? p->owner : p->chan;
245 /* Since glare detection only occurs within this function, and because
246 * a pvt flag cannot be set without having the pvt lock, this is the only
247 * location where we could detect a cancelling of the queue. */
248 if (ast_test_flag(p, LOCAL_CANCEL_QUEUE)) {
249 /* We had a glare on the hangup. Forget all this business,
250 return and destroy p. */
251 ast_mutex_unlock(&p->lock);
252 p = local_pvt_destroy(p);
254 ast_channel_unlock(other);
260 if (other->pbx || other->_bridge || !ast_strlen_zero(other->appl)) {
261 ast_queue_frame(other, f);
262 } /* else the frame won't go anywhere */
263 ast_channel_unlock(other);
266 ast_clear_flag(p, LOCAL_GLARE_DETECT);
271 static int local_answer(struct ast_channel *ast)
273 struct local_pvt *p = ast->tech_pvt;
280 ast_mutex_lock(&p->lock);
281 isoutbound = IS_OUTBOUND(ast, p);
283 /* Pass along answer since somebody answered us */
284 struct ast_frame answer = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
285 res = local_queue_frame(p, isoutbound, &answer, ast, 1);
287 ast_log(LOG_WARNING, "Huh? Local is being asked to answer?\n");
289 ast_mutex_unlock(&p->lock);
293 static void check_bridge(struct local_pvt *p, int isoutbound)
295 struct ast_channel_monitor *tmp;
296 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)))
299 /* only do the masquerade if we are being called on the outbound channel,
300 if it has been bridged to another channel and if there are no pending
301 frames on the owner channel (because they would be transferred to the
302 outbound channel during the masquerade)
304 if (isoutbound && p->chan->_bridge /* Not ast_bridged_channel! Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) {
305 /* Masquerade bridged channel into owner */
306 /* Lock everything we need, one by one, and give up if
307 we can't get everything. Remember, we'll get another
308 chance in just a little bit */
309 if (!ast_channel_trylock(p->chan->_bridge)) {
310 if (!ast_check_hangup(p->chan->_bridge)) {
311 if (!ast_channel_trylock(p->owner)) {
312 if (!ast_check_hangup(p->owner)) {
313 if (p->owner->monitor && !p->chan->_bridge->monitor) {
314 /* If a local channel is being monitored, we don't want a masquerade
315 * to cause the monitor to go away. Since the masquerade swaps the monitors,
316 * pre-swapping the monitors before the masquerade will ensure that the monitor
317 * ends up where it is expected.
319 tmp = p->owner->monitor;
320 p->owner->monitor = p->chan->_bridge->monitor;
321 p->chan->_bridge->monitor = tmp;
323 if (p->chan->audiohooks) {
324 struct ast_audiohook_list *audiohooks_swapper;
325 audiohooks_swapper = p->chan->audiohooks;
326 p->chan->audiohooks = p->owner->audiohooks;
327 p->owner->audiohooks = audiohooks_swapper;
329 ast_app_group_update(p->chan, p->owner);
330 ast_channel_masquerade(p->owner, p->chan->_bridge);
331 ast_set_flag(p, LOCAL_ALREADY_MASQED);
333 ast_channel_unlock(p->owner);
335 ast_channel_unlock(p->chan->_bridge);
338 /* We only allow masquerading in one 'direction'... it's important to preserve the state
339 (group variables, etc.) that live on p->chan->_bridge (and were put there by the dialplan)
340 when the local channels go away.
343 } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && AST_LIST_EMPTY(&p->chan->readq)) {
344 /* Masquerade bridged channel into chan */
345 if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
346 if (!ast_check_hangup(p->owner->_bridge)) {
347 if (!ast_mutex_trylock(&p->chan->lock)) {
348 if (!ast_check_hangup(p->chan)) {
349 ast_channel_masquerade(p->chan, p->owner->_bridge);
350 ast_set_flag(p, LOCAL_ALREADY_MASQED);
352 ast_mutex_unlock(&p->chan->lock);
355 ast_mutex_unlock(&(p->owner->_bridge)->lock);
361 static struct ast_frame *local_read(struct ast_channel *ast)
363 return &ast_null_frame;
366 static int local_write(struct ast_channel *ast, struct ast_frame *f)
368 struct local_pvt *p = ast->tech_pvt;
375 /* Just queue for delivery to the other side */
376 ast_mutex_lock(&p->lock);
377 isoutbound = IS_OUTBOUND(ast, p);
378 if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO))
379 check_bridge(p, isoutbound);
380 if (!ast_test_flag(p, LOCAL_ALREADY_MASQED))
381 res = local_queue_frame(p, isoutbound, f, ast, 1);
383 ast_debug(1, "Not posting to queue since already masked on '%s'\n", ast->name);
387 ast_mutex_unlock(&p->lock);
391 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
393 struct local_pvt *p = newchan->tech_pvt;
398 ast_mutex_lock(&p->lock);
400 if ((p->owner != oldchan) && (p->chan != oldchan)) {
401 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
402 ast_mutex_unlock(&p->lock);
405 if (p->owner == oldchan)
409 ast_mutex_unlock(&p->lock);
413 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
415 struct local_pvt *p = ast->tech_pvt;
417 struct ast_frame f = { AST_FRAME_CONTROL, };
423 /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
424 if (!ast_test_flag(p, LOCAL_MOH_PASSTHRU) && condition == AST_CONTROL_HOLD) {
425 ast_moh_start(ast, data, NULL);
426 } else if (!ast_test_flag(p, LOCAL_MOH_PASSTHRU) && condition == AST_CONTROL_UNHOLD) {
428 } else if (condition == AST_CONTROL_CONNECTED_LINE || condition == AST_CONTROL_REDIRECTING) {
429 struct ast_channel *this_channel;
430 struct ast_channel *the_other_channel;
431 /* A connected line update frame may only contain a partial amount of data, such
432 * as just a source, or just a ton, and not the full amount of information. However,
433 * the collected information is all stored in the outgoing channel's connectedline
434 * structure, so when receiving a connected line update on an outgoing local channel,
435 * we need to transmit the collected connected line information instead of whatever
436 * happens to be in this control frame. The same applies for redirecting information, which
437 * is why it is handled here as well.*/
438 ast_mutex_lock(&p->lock);
439 isoutbound = IS_OUTBOUND(ast, p);
441 this_channel = p->chan;
442 the_other_channel = p->owner;
444 this_channel = p->owner;
445 the_other_channel = p->chan;
447 if (the_other_channel) {
448 unsigned char frame_data[1024];
449 if (condition == AST_CONTROL_CONNECTED_LINE) {
450 f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected);
452 f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting);
454 f.subclass.integer = condition;
455 f.data.ptr = frame_data;
456 if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1))) {
457 ast_mutex_unlock(&p->lock);
460 ast_mutex_unlock(&p->lock);
463 /* Queue up a frame representing the indication as a control frame */
464 ast_mutex_lock(&p->lock);
465 isoutbound = IS_OUTBOUND(ast, p);
466 f.subclass.integer = condition;
467 f.data.ptr = (void*)data;
469 if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1)))
470 ast_mutex_unlock(&p->lock);
476 static int local_digit_begin(struct ast_channel *ast, char digit)
478 struct local_pvt *p = ast->tech_pvt;
480 struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
486 ast_mutex_lock(&p->lock);
487 isoutbound = IS_OUTBOUND(ast, p);
488 f.subclass.integer = digit;
489 if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))
490 ast_mutex_unlock(&p->lock);
495 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
497 struct local_pvt *p = ast->tech_pvt;
499 struct ast_frame f = { AST_FRAME_DTMF_END, };
505 ast_mutex_lock(&p->lock);
506 isoutbound = IS_OUTBOUND(ast, p);
507 f.subclass.integer = digit;
509 if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))
510 ast_mutex_unlock(&p->lock);
515 static int local_sendtext(struct ast_channel *ast, const char *text)
517 struct local_pvt *p = ast->tech_pvt;
519 struct ast_frame f = { AST_FRAME_TEXT, };
525 ast_mutex_lock(&p->lock);
526 isoutbound = IS_OUTBOUND(ast, p);
527 f.data.ptr = (char *) text;
528 f.datalen = strlen(text) + 1;
529 if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))
530 ast_mutex_unlock(&p->lock);
534 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
536 struct local_pvt *p = ast->tech_pvt;
538 struct ast_frame f = { AST_FRAME_HTML, };
544 ast_mutex_lock(&p->lock);
545 isoutbound = IS_OUTBOUND(ast, p);
546 f.subclass.integer = subclass;
547 f.data.ptr = (char *)data;
549 if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0)))
550 ast_mutex_unlock(&p->lock);
554 /*! \brief Initiate new call, part of PBX interface
555 * dest is the dial string */
556 static int local_call(struct ast_channel *ast, char *dest, int timeout)
558 struct local_pvt *p = ast->tech_pvt;
560 struct ast_var_t *varptr = NULL, *new;
566 /* If you value your sanity, please don't look at this code */
568 while (ast_channel_trylock(p->chan)) {
569 ast_channel_unlock(p->owner);
571 ast_channel_lock(p->owner);
574 /* p->owner and p->chan are locked now. Let's get p locked */
575 if (ast_mutex_trylock(&p->lock)) {
577 ast_channel_unlock(p->chan);
578 ast_channel_unlock(p->owner);
580 ast_channel_lock(p->owner);
585 * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
586 * call, so it's done here instead.
588 * All these failure points just return -1. The individual strings will
589 * be cleared when we destroy the channel.
591 if (p->owner->cid.cid_rdnis) {
592 if (!(p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis))) {
593 ast_mutex_unlock(&p->lock);
594 ast_channel_unlock(p->chan);
598 ast_party_redirecting_copy(&p->chan->redirecting, &p->owner->redirecting);
600 if (p->owner->cid.cid_dnid) {
601 if (!(p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid))) {
602 ast_mutex_unlock(&p->lock);
603 ast_channel_unlock(p->chan);
607 p->chan->cid.cid_tns = p->owner->cid.cid_tns;
609 ast_connected_line_copy_to_caller(&p->chan->cid, &p->owner->connected);
610 ast_connected_line_copy_from_caller(&p->chan->connected, &p->owner->cid);
612 ast_string_field_set(p->chan, language, p->owner->language);
613 ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
614 ast_string_field_set(p->chan, musicclass, p->owner->musicclass);
615 ast_cdr_update(p->chan);
616 p->chan->cdrflags = p->owner->cdrflags;
618 if (!ast_exists_extension(NULL, p->chan->context, p->chan->exten, 1, p->owner->cid.cid_num)) {
619 ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n", p->chan->exten, p->chan->context);
620 ast_mutex_unlock(&p->lock);
621 ast_channel_unlock(p->chan);
625 /* Make sure we inherit the ANSWERED_ELSEWHERE flag if it's set on the queue/dial call request in the dialplan */
626 if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
627 ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
630 /* copy the channel variables from the incoming channel to the outgoing channel */
631 /* Note that due to certain assumptions, they MUST be in the same order */
632 AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
633 namelen = strlen(varptr->name);
634 len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
635 if ((new = ast_calloc(1, len))) {
636 memcpy(new, varptr, len);
637 new->value = &(new->name[0]) + namelen + 1;
638 AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
641 ast_channel_datastore_inherit(p->owner, p->chan);
643 /* Start switch on sub channel */
644 if (!(res = ast_pbx_start(p->chan)))
645 ast_set_flag(p, LOCAL_LAUNCHED_PBX);
647 ast_mutex_unlock(&p->lock);
648 ast_channel_unlock(p->chan);
652 /*! \brief Hangup a call through the local proxy channel */
653 static int local_hangup(struct ast_channel *ast)
655 struct local_pvt *p = ast->tech_pvt;
657 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_HANGUP }, .data.uint32 = ast->hangupcause };
658 struct ast_channel *ochan = NULL;
659 int glaredetect = 0, res = 0;
664 ast_mutex_lock(&p->lock);
666 isoutbound = IS_OUTBOUND(ast, p);
668 if (p->chan && ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
669 ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
670 ast_debug(2, "This local call has the ANSWERED_ELSEWHERE flag set.\n");
674 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
675 if ((status) && (p->owner)) {
676 /* Deadlock avoidance */
677 while (p->owner && ast_channel_trylock(p->owner)) {
678 ast_mutex_unlock(&p->lock);
680 ast_channel_unlock(ast);
684 ast_channel_lock(ast);
686 ast_mutex_lock(&p->lock);
689 pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
690 ast_channel_unlock(p->owner);
694 ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
695 ast_module_user_remove(p->u_chan);
697 ast_module_user_remove(p->u_owner);
698 while (p->chan && ast_channel_trylock(p->chan)) {
699 DEADLOCK_AVOIDANCE(&p->lock);
703 ast_queue_hangup(p->chan);
704 ast_channel_unlock(p->chan);
708 ast->tech_pvt = NULL;
710 if (!p->owner && !p->chan) {
711 /* Okay, done with the private part now, too. */
712 glaredetect = ast_test_flag(p, LOCAL_GLARE_DETECT);
713 /* If we have a queue holding, don't actually destroy p yet, but
714 let local_queue do it. */
716 ast_set_flag(p, LOCAL_CANCEL_QUEUE);
717 /* Remove from list */
718 AST_LIST_LOCK(&locals);
719 AST_LIST_REMOVE(&locals, p, list);
720 AST_LIST_UNLOCK(&locals);
721 ast_mutex_unlock(&p->lock);
724 p = local_pvt_destroy(p);
728 if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX))
729 /* Need to actually hangup since there is no PBX */
732 res = local_queue_frame(p, isoutbound, &f, NULL, 1);
734 ast_mutex_unlock(&p->lock);
740 /*! \brief Create a call structure */
741 static struct local_pvt *local_alloc(const char *data, int format)
743 struct local_pvt *tmp = NULL;
744 char *c = NULL, *opts = NULL;
746 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
749 /* Initialize private structure information */
750 ast_mutex_init(&tmp->lock);
751 ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
753 memcpy(&tmp->jb_conf, &g_jb_conf, sizeof(tmp->jb_conf));
755 /* Look for options */
756 if ((opts = strchr(tmp->exten, '/'))) {
758 if (strchr(opts, 'n'))
759 ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
760 if (strchr(opts, 'j')) {
761 if (ast_test_flag(tmp, LOCAL_NO_OPTIMIZATION))
762 ast_set_flag(&tmp->jb_conf, AST_JB_ENABLED);
764 ast_log(LOG_ERROR, "You must use the 'n' option for chan_local "
765 "to use the 'j' option to enable the jitterbuffer\n");
768 if (strchr(opts, 'b')) {
769 ast_set_flag(tmp, LOCAL_BRIDGE);
771 if (strchr(opts, 'm')) {
772 ast_set_flag(tmp, LOCAL_MOH_PASSTHRU);
776 /* Look for a context */
777 if ((c = strchr(tmp->exten, '@')))
780 ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
782 tmp->reqformat = format;
785 /* We can't do this check here, because we don't know the CallerID yet, and
786 * the CallerID could potentially affect what step is actually taken (or
787 * even if that step exists). */
788 if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
789 ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
790 tmp = local_pvt_destroy(tmp);
794 AST_LIST_LOCK(&locals);
795 AST_LIST_INSERT_HEAD(&locals, tmp, list);
796 AST_LIST_UNLOCK(&locals);
804 /*! \brief Start new local channel */
805 static struct ast_channel *local_new(struct local_pvt *p, int state, const char *linkedid)
807 struct ast_channel *tmp = NULL, *tmp2 = NULL;
808 int randnum = ast_random() & 0xffff, fmt = 0;
812 /* Allocate two new Asterisk channels */
813 /* safe accountcode */
814 if (p->owner && p->owner->accountcode)
815 t = p->owner->accountcode;
820 ama = p->owner->amaflags;
823 if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, linkedid, ama, "Local/%s@%s-%04x;1", p->exten, p->context, randnum))
824 || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, linkedid, ama, "Local/%s@%s-%04x;2", p->exten, p->context, randnum))) {
826 tmp = ast_channel_release(tmp);
828 ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
832 tmp2->tech = tmp->tech = &local_tech;
834 tmp->nativeformats = p->reqformat;
835 tmp2->nativeformats = p->reqformat;
837 /* Determine our read/write format and set it on each channel */
838 fmt = ast_best_codec(p->reqformat);
839 tmp->writeformat = fmt;
840 tmp2->writeformat = fmt;
841 tmp->rawwriteformat = fmt;
842 tmp2->rawwriteformat = fmt;
843 tmp->readformat = fmt;
844 tmp2->readformat = fmt;
845 tmp->rawreadformat = fmt;
846 tmp2->rawreadformat = fmt;
853 p->u_owner = ast_module_user_add(p->owner);
854 p->u_chan = ast_module_user_add(p->chan);
856 ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
857 ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
858 ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
862 ast_jb_configure(tmp, &p->jb_conf);
867 /*! \brief Part of PBX interface */
868 static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
870 struct local_pvt *p = NULL;
871 struct ast_channel *chan = NULL;
873 /* Allocate a new private structure and then Asterisk channel */
874 if ((p = local_alloc(data, format))) {
875 if (!(chan = local_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL))) {
876 AST_LIST_LOCK(&locals);
877 AST_LIST_REMOVE(&locals, p, list);
878 AST_LIST_UNLOCK(&locals);
879 p = local_pvt_destroy(p);
886 /*! \brief CLI command "local show channels" */
887 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
889 struct local_pvt *p = NULL;
893 e->command = "local show channels";
895 "Usage: local show channels\n"
896 " Provides summary information on active local proxy channels.\n";
903 return CLI_SHOWUSAGE;
905 AST_LIST_LOCK(&locals);
906 if (!AST_LIST_EMPTY(&locals)) {
907 AST_LIST_TRAVERSE(&locals, p, list) {
908 ast_mutex_lock(&p->lock);
909 ast_cli(a->fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
910 ast_mutex_unlock(&p->lock);
913 ast_cli(a->fd, "No local channels in use\n");
914 AST_LIST_UNLOCK(&locals);
919 static struct ast_cli_entry cli_local[] = {
920 AST_CLI_DEFINE(locals_show, "List status of local channels"),
923 /*! \brief Load module into PBX, register channel */
924 static int load_module(void)
926 /* Make sure we can register our channel type */
927 if (ast_channel_register(&local_tech)) {
928 ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
929 return AST_MODULE_LOAD_FAILURE;
931 ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
932 return AST_MODULE_LOAD_SUCCESS;
935 /*! \brief Unload the local proxy channel from Asterisk */
936 static int unload_module(void)
938 struct local_pvt *p = NULL;
940 /* First, take us out of the channel loop */
941 ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
942 ast_channel_unregister(&local_tech);
943 if (!AST_LIST_LOCK(&locals)) {
944 /* Hangup all interfaces if they have an owner */
945 AST_LIST_TRAVERSE(&locals, p, list) {
947 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
949 AST_LIST_UNLOCK(&locals);
951 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
957 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel (Note: used internally by other modules)");