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
31 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <sys/signal.h>
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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"
63 static const char desc[] = "Local Proxy Channel";
64 static const char type[] = "Local";
65 static const char tdesc[] = "Local Proxy Channel Driver";
68 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
70 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
72 /* Protect the interface list (of sip_pvt's) */
73 AST_MUTEX_DEFINE_STATIC(locallock);
75 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause);
76 static int local_digit(struct ast_channel *ast, char digit);
77 static int local_call(struct ast_channel *ast, char *dest, int timeout);
78 static int local_hangup(struct ast_channel *ast);
79 static int local_answer(struct ast_channel *ast);
80 static struct ast_frame *local_read(struct ast_channel *ast);
81 static int local_write(struct ast_channel *ast, struct ast_frame *f);
82 static int local_indicate(struct ast_channel *ast, int condition);
83 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
84 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
86 /* PBX interface structure for channel registration */
87 static const struct ast_channel_tech local_tech = {
91 .requester = local_request,
92 .send_digit = local_digit,
94 .hangup = local_hangup,
95 .answer = local_answer,
98 .exception = local_read,
99 .indicate = local_indicate,
100 .fixup = local_fixup,
101 .send_html = local_sendhtml,
104 static struct local_pvt {
105 ast_mutex_t lock; /* Channel private lock */
106 char context[AST_MAX_CONTEXT]; /* Context to call */
107 char exten[AST_MAX_EXTENSION]; /* Extension to call */
108 int reqformat; /* Requested format */
109 int glaredetect; /* Detect glare on hangup */
110 int cancelqueue; /* Cancel queue */
111 int alreadymasqed; /* Already masqueraded */
112 int launchedpbx; /* Did we launch the PBX */
113 int nooptimization; /* Don't leave masq state */
114 struct ast_channel *owner; /* Master Channel */
115 struct ast_channel *chan; /* Outbound channel */
116 struct local_pvt *next; /* Next entity */
119 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us)
121 struct ast_channel *other;
123 /* Recalculate outbound channel */
129 /* Set glare detection */
131 if (p->cancelqueue) {
132 /* We had a glare on the hangup. Forget all this business,
133 return and destroy p. */
134 ast_mutex_unlock(&p->lock);
135 ast_mutex_destroy(&p->lock);
143 if (ast_mutex_trylock(&other->lock)) {
144 /* Failed to lock. Release main lock and try again */
145 ast_mutex_unlock(&p->lock);
147 if (ast_mutex_unlock(&us->lock)) {
148 ast_log(LOG_WARNING, "%s wasn't locked while sending %d/%d\n",
149 us->name, f->frametype, f->subclass);
153 /* Wait just a bit */
155 /* Only we can destroy ourselves, so we can't disappear here */
157 ast_mutex_lock(&us->lock);
158 ast_mutex_lock(&p->lock);
161 ast_queue_frame(other, f);
162 ast_mutex_unlock(&other->lock);
167 static int local_answer(struct ast_channel *ast)
169 struct local_pvt *p = ast->tech_pvt;
173 ast_mutex_lock(&p->lock);
174 isoutbound = IS_OUTBOUND(ast, p);
176 /* Pass along answer since somebody answered us */
177 struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
178 res = local_queue_frame(p, isoutbound, &answer, ast);
180 ast_log(LOG_WARNING, "Huh? Local is being asked to answer?\n");
181 ast_mutex_unlock(&p->lock);
185 static void check_bridge(struct local_pvt *p, int isoutbound)
187 if (p->alreadymasqed || p->nooptimization)
189 if (!p->chan || !p->owner)
191 if (isoutbound&& p->chan->_bridge /* Not ast_bridged_channel! Only go one step! */ && !p->owner->readq) {
192 /* Masquerade bridged channel into owner */
193 /* Lock everything we need, one by one, and give up if
194 we can't get everything. Remember, we'll get another
195 chance in just a little bit */
196 if (!ast_mutex_trylock(&(p->chan->_bridge)->lock)) {
197 if (!p->chan->_bridge->_softhangup) {
198 if (!ast_mutex_trylock(&p->owner->lock)) {
199 if (!p->owner->_softhangup) {
200 ast_channel_masquerade(p->owner, p->chan->_bridge);
201 p->alreadymasqed = 1;
203 ast_mutex_unlock(&p->owner->lock);
205 ast_mutex_unlock(&(p->chan->_bridge)->lock);
208 } else if (!isoutbound && p->owner && p->owner->_bridge && p->chan && !p->chan->readq) {
209 /* Masquerade bridged channel into chan */
210 if (!ast_mutex_trylock(&(p->owner->_bridge)->lock)) {
211 if (!p->owner->_bridge->_softhangup) {
212 if (!ast_mutex_trylock(&p->chan->lock)) {
213 if (!p->chan->_softhangup) {
214 ast_channel_masquerade(p->chan, p->owner->_bridge);
215 p->alreadymasqed = 1;
217 ast_mutex_unlock(&p->chan->lock);
220 ast_mutex_unlock(&(p->owner->_bridge)->lock);
225 static struct ast_frame *local_read(struct ast_channel *ast)
227 return &ast_null_frame;
230 static int local_write(struct ast_channel *ast, struct ast_frame *f)
232 struct local_pvt *p = ast->tech_pvt;
236 /* Just queue for delivery to the other side */
237 ast_mutex_lock(&p->lock);
238 isoutbound = IS_OUTBOUND(ast, p);
239 if (f && (f->frametype == AST_FRAME_VOICE))
240 check_bridge(p, isoutbound);
241 if (!p->alreadymasqed)
242 res = local_queue_frame(p, isoutbound, f, ast);
244 ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name);
247 ast_mutex_unlock(&p->lock);
251 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
253 struct local_pvt *p = newchan->tech_pvt;
254 ast_mutex_lock(&p->lock);
256 if ((p->owner != oldchan) && (p->chan != oldchan)) {
257 ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
258 ast_mutex_unlock(&p->lock);
261 if (p->owner == oldchan)
265 ast_mutex_unlock(&p->lock);
269 static int local_indicate(struct ast_channel *ast, int condition)
271 struct local_pvt *p = ast->tech_pvt;
273 struct ast_frame f = { AST_FRAME_CONTROL, };
276 /* Queue up a frame representing the indication as a control frame */
277 ast_mutex_lock(&p->lock);
278 isoutbound = IS_OUTBOUND(ast, p);
279 f.subclass = condition;
280 res = local_queue_frame(p, isoutbound, &f, ast);
281 ast_mutex_unlock(&p->lock);
285 static int local_digit(struct ast_channel *ast, char digit)
287 struct local_pvt *p = ast->tech_pvt;
289 struct ast_frame f = { AST_FRAME_DTMF, };
292 ast_mutex_lock(&p->lock);
293 isoutbound = IS_OUTBOUND(ast, p);
295 res = local_queue_frame(p, isoutbound, &f, ast);
296 ast_mutex_unlock(&p->lock);
300 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
302 struct local_pvt *p = ast->tech_pvt;
304 struct ast_frame f = { AST_FRAME_HTML, };
307 ast_mutex_lock(&p->lock);
308 isoutbound = IS_OUTBOUND(ast, p);
309 f.subclass = subclass;
310 f.data = (char *)data;
312 res = local_queue_frame(p, isoutbound, &f, ast);
313 ast_mutex_unlock(&p->lock);
317 /*! \brief Initiate new call, part of PBX interface
318 * dest is the dial string */
319 static int local_call(struct ast_channel *ast, char *dest, int timeout)
321 struct local_pvt *p = ast->tech_pvt;
323 struct ast_var_t *varptr = NULL, *new;
326 ast_mutex_lock(&p->lock);
328 p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
329 p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
330 p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
331 p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
333 strncpy(p->chan->language, p->owner->language, sizeof(p->chan->language) - 1);
334 strncpy(p->chan->accountcode, p->owner->accountcode, sizeof(p->chan->accountcode) - 1);
335 p->chan->cdrflags = p->owner->cdrflags;
337 /* copy the channel variables from the incoming channel to the outgoing channel */
338 /* Note that due to certain assumptions, they MUST be in the same order */
339 AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
340 namelen = strlen(varptr->name);
341 len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
342 if ((new = ast_calloc(1, len))) {
343 memcpy(new, varptr, len);
344 new->value = &(new->name[0]) + namelen + 1;
345 AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
351 /* Start switch on sub channel */
352 res = ast_pbx_start(p->chan);
353 ast_mutex_unlock(&p->lock);
358 static void local_destroy(struct local_pvt *p)
360 struct local_pvt *cur, *prev = NULL;
361 ast_mutex_lock(&locallock);
366 prev->next = cur->next;
369 ast_mutex_destroy(cur);
376 ast_mutex_unlock(&locallock);
378 ast_log(LOG_WARNING, "Unable ot find local '%s@%s' in local list\n", p->exten, p->context);
382 /*! \brief Hangup a call through the local proxy channel */
383 static int local_hangup(struct ast_channel *ast)
385 struct local_pvt *p = ast->tech_pvt;
387 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
388 struct local_pvt *cur, *prev=NULL;
389 struct ast_channel *ochan = NULL;
393 ast_mutex_lock(&p->lock);
394 isoutbound = IS_OUTBOUND(ast, p);
396 status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
398 pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
403 ast->tech_pvt = NULL;
405 ast_mutex_lock(&usecnt_lock);
407 ast_mutex_unlock(&usecnt_lock);
409 if (!p->owner && !p->chan) {
410 /* Okay, done with the private part now, too. */
411 glaredetect = p->glaredetect;
412 /* If we have a queue holding, don't actually destroy p yet, but
413 let local_queue do it. */
416 ast_mutex_unlock(&p->lock);
417 /* Remove from list */
418 ast_mutex_lock(&locallock);
423 prev->next = cur->next;
431 ast_mutex_unlock(&locallock);
432 /* Grab / release lock just in case */
433 ast_mutex_lock(&p->lock);
434 ast_mutex_unlock(&p->lock);
437 ast_mutex_destroy(&p->lock);
442 if (p->chan && !p->launchedpbx)
443 /* Need to actually hangup since there is no PBX */
446 local_queue_frame(p, isoutbound, &f, NULL);
447 ast_mutex_unlock(&p->lock);
453 /*! \brief Create a call structure */
454 static struct local_pvt *local_alloc(char *data, int format)
456 struct local_pvt *tmp;
460 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
463 ast_mutex_init(&tmp->lock);
464 strncpy(tmp->exten, data, sizeof(tmp->exten) - 1);
465 opts = strchr(tmp->exten, '/');
469 if (strchr(opts, 'n'))
470 tmp->nooptimization = 1;
472 c = strchr(tmp->exten, '@');
476 strncpy(tmp->context, c, sizeof(tmp->context) - 1);
478 strncpy(tmp->context, "default", sizeof(tmp->context) - 1);
479 tmp->reqformat = format;
480 if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
481 ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
482 ast_mutex_destroy(&tmp->lock);
487 ast_mutex_lock(&locallock);
490 ast_mutex_unlock(&locallock);
496 /*! \brief Start new local channel */
497 static struct ast_channel *local_new(struct local_pvt *p, int state)
499 struct ast_channel *tmp, *tmp2;
500 int randnum = rand() & 0xffff;
502 tmp = ast_channel_alloc(1);
503 tmp2 = ast_channel_alloc(1);
506 ast_channel_free(tmp);
508 ast_channel_free(tmp2);
509 ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
513 tmp2->tech = tmp->tech = &local_tech;
514 tmp->nativeformats = p->reqformat;
515 tmp2->nativeformats = p->reqformat;
516 snprintf(tmp->name, sizeof(tmp->name), "Local/%s@%s-%04x,1", p->exten, p->context, randnum);
517 snprintf(tmp2->name, sizeof(tmp2->name), "Local/%s@%s-%04x,2", p->exten, p->context, randnum);
520 ast_setstate(tmp, state);
521 ast_setstate(tmp2, AST_STATE_RING);
522 tmp->writeformat = p->reqformat;
523 tmp2->writeformat = p->reqformat;
524 tmp->rawwriteformat = p->reqformat;
525 tmp2->rawwriteformat = p->reqformat;
526 tmp->readformat = p->reqformat;
527 tmp2->readformat = p->reqformat;
528 tmp->rawreadformat = p->reqformat;
529 tmp2->rawreadformat = p->reqformat;
534 ast_mutex_lock(&usecnt_lock);
537 ast_mutex_unlock(&usecnt_lock);
538 ast_update_use_count();
539 ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
540 ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
541 ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
549 /*! \brief Part of PBX interface */
550 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
553 struct ast_channel *chan = NULL;
555 p = local_alloc(data, format);
557 chan = local_new(p, AST_STATE_DOWN);
561 /*! \brief CLI command "local show channels" */
562 static int locals_show(int fd, int argc, char **argv)
567 return RESULT_SHOWUSAGE;
568 ast_mutex_lock(&locallock);
571 ast_mutex_lock(&p->lock);
572 ast_cli(fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
573 ast_mutex_unlock(&p->lock);
577 ast_cli(fd, "No local channels in use\n");
578 ast_mutex_unlock(&locallock);
579 return RESULT_SUCCESS;
582 static char show_locals_usage[] =
583 "Usage: local show channels\n"
584 " Provides summary information on active local proxy channels.\n";
586 static struct ast_cli_entry cli_show_locals = {
587 { "local", "show", "channels", NULL }, locals_show,
588 "Show status of local channels", show_locals_usage, NULL };
590 /*! \brief Load module into PBX, register channel */
593 /* Make sure we can register our channel type */
594 if (ast_channel_register(&local_tech)) {
595 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
598 ast_cli_register(&cli_show_locals);
602 /*! \brief Reload module */
608 /*! \brief Unload the local proxy channel from Asterisk */
613 /* First, take us out of the channel loop */
614 ast_cli_unregister(&cli_show_locals);
615 ast_channel_unregister(&local_tech);
616 if (!ast_mutex_lock(&locallock)) {
617 /* Hangup all interfaces if they have an owner */
621 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
625 ast_mutex_unlock(&locallock);
627 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
640 return ASTERISK_GPL_KEY;
645 return (char *) desc;