Thu Apr 28 2011 17:13:31

Asterisk developer's documentation


chan_local.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \author Mark Spencer <markster@digium.com>
00022  *
00023  * \brief Local Proxy Channel
00024  * 
00025  * \ingroup channel_drivers
00026  */
00027 
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 306126 $")
00031 
00032 #include <fcntl.h>
00033 #include <sys/signal.h>
00034 
00035 #include "asterisk/lock.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/config.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/pbx.h"
00040 #include "asterisk/sched.h"
00041 #include "asterisk/io.h"
00042 #include "asterisk/rtp.h"
00043 #include "asterisk/acl.h"
00044 #include "asterisk/callerid.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/cli.h"
00047 #include "asterisk/app.h"
00048 #include "asterisk/musiconhold.h"
00049 #include "asterisk/manager.h"
00050 #include "asterisk/stringfields.h"
00051 #include "asterisk/devicestate.h"
00052 #include "asterisk/astobj2.h"
00053 
00054 static const char tdesc[] = "Local Proxy Channel Driver";
00055 
00056 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
00057 /* right now we are treating the locals astobj2 container as a
00058  * list.  If there is ever a reason to make this more efficient
00059  * increasing the bucket size would help. */
00060 static const int BUCKET_SIZE = 1;
00061 
00062 static struct ao2_container *locals;
00063 
00064 static struct ast_jb_conf g_jb_conf = {
00065    .flags = 0,
00066    .max_size = -1,
00067    .resync_threshold = -1,
00068    .impl = "",
00069    .target_extra = -1,
00070 };
00071 
00072 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause);
00073 static int local_digit_begin(struct ast_channel *ast, char digit);
00074 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00075 static int local_call(struct ast_channel *ast, char *dest, int timeout);
00076 static int local_hangup(struct ast_channel *ast);
00077 static int local_answer(struct ast_channel *ast);
00078 static struct ast_frame *local_read(struct ast_channel *ast);
00079 static int local_write(struct ast_channel *ast, struct ast_frame *f);
00080 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
00081 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00082 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
00083 static int local_sendtext(struct ast_channel *ast, const char *text);
00084 static int local_devicestate(void *data);
00085 static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
00086 static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen);
00087 static int local_setoption(struct ast_channel *chan, int option, void *data, int datalen);
00088 
00089 /* PBX interface structure for channel registration */
00090 static const struct ast_channel_tech local_tech = {
00091    .type = "Local",
00092    .description = tdesc,
00093    .capabilities = -1,
00094    .requester = local_request,
00095    .send_digit_begin = local_digit_begin,
00096    .send_digit_end = local_digit_end,
00097    .call = local_call,
00098    .hangup = local_hangup,
00099    .answer = local_answer,
00100    .read = local_read,
00101    .write = local_write,
00102    .write_video = local_write,
00103    .exception = local_read,
00104    .indicate = local_indicate,
00105    .fixup = local_fixup,
00106    .send_html = local_sendhtml,
00107    .send_text = local_sendtext,
00108    .devicestate = local_devicestate,
00109    .bridged_channel = local_bridgedchannel,
00110    .queryoption = local_queryoption,
00111    .setoption = local_setoption,
00112 };
00113 
00114 struct local_pvt {
00115    unsigned int flags;                     /* Private flags */
00116    char context[AST_MAX_CONTEXT];      /* Context to call */
00117    char exten[AST_MAX_EXTENSION];      /* Extension to call */
00118    int reqformat;          /* Requested format */
00119    struct ast_jb_conf jb_conf;      /*!< jitterbuffer configuration for this local channel */
00120    struct ast_channel *owner;    /* Master Channel - Bridging happens here */
00121    struct ast_channel *chan;     /* Outbound channel - PBX is run here */
00122    struct ast_module_user *u_owner; /*! reference to keep the module loaded while in use */
00123    struct ast_module_user *u_chan;     /*! reference to keep the module loaded while in use */
00124    AST_LIST_ENTRY(local_pvt) list;     /* Next entity */
00125 };
00126 
00127 #define LOCAL_ALREADY_MASQED  (1 << 0) /*!< Already masqueraded */
00128 #define LOCAL_LAUNCHED_PBX    (1 << 1) /*!< PBX was launched */
00129 #define LOCAL_NO_OPTIMIZATION (1 << 2) /*!< Do not optimize using masquerading */
00130 #define LOCAL_BRIDGE          (1 << 3) /*!< Report back the "true" channel as being bridged to */
00131 #define LOCAL_MOH_PASSTHRU    (1 << 4) /*!< Pass through music on hold start/stop frames */
00132 
00133 static int local_setoption(struct ast_channel *chan, int option, void * data, int datalen)
00134 {
00135    int res;
00136    struct local_pvt *p;
00137    struct ast_channel *otherchan;
00138    ast_chan_write_info_t *write_info;
00139 
00140    if (option != AST_OPTION_CHANNEL_WRITE) {
00141       return -1;
00142    }
00143 
00144    write_info = data;
00145 
00146    if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
00147       ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
00148       return -1;
00149    }
00150 
00151 
00152 startover:
00153    ast_channel_lock(chan);
00154 
00155    p = chan->tech_pvt;
00156    if (!p) {
00157       ast_channel_unlock(chan);
00158       ast_log(LOG_WARNING, "Could not update other side of %s, local_pvt went away.\n", chan->name);
00159       return -1;
00160    }
00161 
00162    while (ao2_trylock(p)) {
00163       ast_channel_unlock(chan);
00164       sched_yield();
00165       ast_channel_lock(chan);
00166       p = chan->tech_pvt;
00167       if (!p) {
00168          ast_channel_unlock(chan);
00169          ast_log(LOG_WARNING, "Could not update other side of %s, local_pvt went away.\n", chan->name);
00170          return -1;
00171       }
00172    }
00173 
00174    otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
00175 
00176    if (!otherchan || otherchan == write_info->chan) {
00177       ao2_unlock(p);
00178       ast_channel_unlock(chan);
00179       ast_log(LOG_WARNING, "Could not update other side of %s, other side went away.\n", chan->name);
00180       return 0;
00181    }
00182 
00183    if (ast_channel_trylock(otherchan)) {
00184       ao2_unlock(p);
00185       ast_channel_unlock(chan);
00186       goto startover;
00187    }
00188 
00189    res = write_info->write_fn(otherchan, write_info->function, write_info->data, write_info->value);
00190 
00191    ast_channel_unlock(otherchan);
00192    ao2_unlock(p);
00193    ast_channel_unlock(chan);
00194 
00195    return res;
00196 }
00197 
00198 /*! \brief Adds devicestate to local channels */
00199 static int local_devicestate(void *data)
00200 {
00201    char *exten = ast_strdupa(data);
00202    char *context = NULL, *opts = NULL;
00203    int res;
00204    struct local_pvt *lp;
00205    struct ao2_iterator it;
00206 
00207    if (!(context = strchr(exten, '@'))) {
00208       ast_log(LOG_WARNING, "Someone used Local/%s somewhere without a @context. This is bad.\n", exten);
00209       return AST_DEVICE_INVALID; 
00210    }
00211 
00212    *context++ = '\0';
00213 
00214    /* Strip options if they exist */
00215    if ((opts = strchr(context, '/')))
00216       *opts = '\0';
00217 
00218    ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
00219 
00220    res = ast_exists_extension(NULL, context, exten, 1, NULL);
00221    if (!res)      
00222       return AST_DEVICE_INVALID;
00223    
00224    res = AST_DEVICE_NOT_INUSE;
00225 
00226    it = ao2_iterator_init(locals, 0);
00227    while ((lp = ao2_iterator_next(&it))) {
00228       if (!strcmp(exten, lp->exten) && !strcmp(context, lp->context) && lp->owner) {
00229          res = AST_DEVICE_INUSE;
00230          ao2_ref(lp, -1);
00231          break;
00232       }
00233       ao2_ref(lp, -1);
00234    }
00235    ao2_iterator_destroy(&it);
00236 
00237    return res;
00238 }
00239 
00240 /*! \brief Return the bridged channel of a Local channel */
00241 static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
00242 {
00243    struct local_pvt *p = bridge->tech_pvt;
00244    struct ast_channel *bridged = bridge;
00245 
00246    if (!p) {
00247       ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning <none>\n",
00248          chan->name, bridge->name);
00249       return NULL;
00250    }
00251 
00252    ao2_lock(p);
00253 
00254    if (ast_test_flag(p, LOCAL_BRIDGE)) {
00255       /* Find the opposite channel */
00256       bridged = (bridge == p->owner ? p->chan : p->owner);
00257       
00258       /* Now see if the opposite channel is bridged to anything */
00259       if (!bridged) {
00260          bridged = bridge;
00261       } else if (bridged->_bridge) {
00262          bridged = bridged->_bridge;
00263       }
00264    }
00265 
00266    ao2_unlock(p);
00267 
00268    return bridged;
00269 }
00270 
00271 static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
00272 {
00273    struct local_pvt *p = ast->tech_pvt;
00274    struct ast_channel *chan, *bridged;
00275    int res;
00276 
00277    if (!p) {
00278       return -1;
00279    }
00280 
00281    if (option != AST_OPTION_T38_STATE) {
00282       /* AST_OPTION_T38_STATE is the only supported option at this time */
00283       return -1;
00284    }
00285 
00286    ao2_lock(p);
00287    chan = IS_OUTBOUND(ast, p) ? p->owner : p->chan;
00288 
00289 try_again:
00290    if (!chan) {
00291       ao2_unlock(p);
00292       return -1;
00293    }
00294 
00295    if (ast_channel_trylock(chan)) {
00296       ao2_unlock(p);
00297       sched_yield();
00298       ao2_lock(p);
00299       chan = IS_OUTBOUND(ast, p) ? p->owner : p->chan;
00300       goto try_again;
00301    }
00302 
00303    bridged = ast_bridged_channel(chan);
00304    if (!bridged) {
00305       /* can't query channel unless we are bridged */
00306       ao2_unlock(p);
00307       ast_channel_unlock(chan);
00308       return -1;
00309    }
00310 
00311    if (ast_channel_trylock(bridged)) {
00312       ast_channel_unlock(chan);
00313       ao2_unlock(p);
00314       sched_yield();
00315       ao2_lock(p);
00316       chan = IS_OUTBOUND(ast, p) ? p->owner : p->chan;
00317       goto try_again;
00318    }
00319 
00320    res = ast_channel_queryoption(bridged, option, data, datalen, 0);
00321    ao2_unlock(p);
00322    ast_channel_unlock(chan);
00323    ast_channel_unlock(bridged);
00324    return res;
00325 }
00326 
00327 /*! \brief queue a frame on a to either the p->owner or p->chan
00328  *
00329  * \note the local_pvt MUST have it's ref count bumped before entering this function and
00330  * decremented after this function is called.  This is a side effect of the deadlock
00331  * avoidance that is necessary to lock 2 channels and a tech_pvt.  Without a ref counted
00332  * local_pvt, it is impossible to guarantee it will not be destroyed by another thread
00333  * during deadlock avoidance.
00334  */
00335 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, 
00336    struct ast_channel *us, int us_locked)
00337 {
00338    struct ast_channel *other = NULL;
00339 
00340    /* Recalculate outbound channel */
00341    other = isoutbound ? p->owner : p->chan;
00342 
00343    if (!other) {
00344       return 0;
00345    }
00346 
00347    /* do not queue frame if generator is on both local channels */
00348    if (us && us->generator && other->generator) {
00349       return 0;
00350    }
00351 
00352    /* Ensure that we have both channels locked */
00353    while (other && ast_channel_trylock(other)) {
00354       int res;
00355       if ((res = ao2_unlock(p))) {
00356          ast_log(LOG_ERROR, "chan_local bug! '&p->lock' was not locked when entering local_queue_frame! (%s)\n", strerror(res));
00357          return -1;
00358       }
00359       if (us && us_locked) {
00360          do {
00361             CHANNEL_DEADLOCK_AVOIDANCE(us);
00362          } while (ao2_trylock(p));
00363       } else {
00364          usleep(1);
00365          ao2_lock(p);
00366       }
00367       other = isoutbound ? p->owner : p->chan;
00368    }
00369 
00370    if (other) {
00371       if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_RINGING) {
00372          ast_setstate(other, AST_STATE_RINGING);
00373       }
00374       ast_queue_frame(other, f);
00375       ast_channel_unlock(other);
00376    }
00377 
00378    return 0;
00379 }
00380 
00381 static int local_answer(struct ast_channel *ast)
00382 {
00383    struct local_pvt *p = ast->tech_pvt;
00384    int isoutbound;
00385    int res = -1;
00386 
00387    if (!p)
00388       return -1;
00389 
00390    ao2_lock(p);
00391    ao2_ref(p, 1);
00392    isoutbound = IS_OUTBOUND(ast, p);
00393    if (isoutbound) {
00394       /* Pass along answer since somebody answered us */
00395       struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00396       res = local_queue_frame(p, isoutbound, &answer, ast, 1);
00397    } else {
00398       ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
00399    }
00400    ao2_unlock(p);
00401    ao2_ref(p, -1);
00402    return res;
00403 }
00404 
00405 /*!
00406  * \internal
00407  * \note This function assumes that we're only called from the "outbound" local channel side
00408  */
00409 static void check_bridge(struct local_pvt *p)
00410 {
00411    struct ast_channel_monitor *tmp;
00412    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)))
00413       return;
00414 
00415    /* only do the masquerade if we are being called on the outbound channel,
00416       if it has been bridged to another channel and if there are no pending
00417       frames on the owner channel (because they would be transferred to the
00418       outbound channel during the masquerade)
00419    */
00420    if (p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */ && AST_LIST_EMPTY(&p->owner->readq)) {
00421       /* Masquerade bridged channel into owner */
00422       /* Lock everything we need, one by one, and give up if
00423          we can't get everything.  Remember, we'll get another
00424          chance in just a little bit */
00425       if (!ast_channel_trylock(p->chan->_bridge)) {
00426          if (!ast_check_hangup(p->chan->_bridge)) {
00427             if (!ast_channel_trylock(p->owner)) {
00428                if (!ast_check_hangup(p->owner)) {
00429                   if (p->owner->monitor && !p->chan->_bridge->monitor) {
00430                      /* If a local channel is being monitored, we don't want a masquerade
00431                       * to cause the monitor to go away. Since the masquerade swaps the monitors,
00432                       * pre-swapping the monitors before the masquerade will ensure that the monitor
00433                       * ends up where it is expected.
00434                       */
00435                      tmp = p->owner->monitor;
00436                      p->owner->monitor = p->chan->_bridge->monitor;
00437                      p->chan->_bridge->monitor = tmp;
00438                   }
00439                   if (p->chan->audiohooks) {
00440                      struct ast_audiohook_list *audiohooks_swapper;
00441                      audiohooks_swapper = p->chan->audiohooks;
00442                      p->chan->audiohooks = p->owner->audiohooks;
00443                      p->owner->audiohooks = audiohooks_swapper;
00444                   }
00445 
00446                   /* If any Caller ID was set, preserve it after masquerade like above. We must check
00447                    * to see if Caller ID was set because otherwise we'll mistakingly copy info not
00448                    * set from the dialplan and will overwrite the real channel Caller ID. The reason
00449                    * for this whole preswapping action is because the Caller ID is set on the channel
00450                    * thread (which is the to be masqueraded away local channel) before both local
00451                    * channels are optimized away.
00452                    */
00453                   if (p->owner->cid.cid_dnid || p->owner->cid.cid_num ||
00454                      p->owner->cid.cid_name || p->owner->cid.cid_ani ||
00455                      p->owner->cid.cid_rdnis || p->owner->cid.cid_pres ||  
00456                      p->owner->cid.cid_ani2 || p->owner->cid.cid_ton ||  
00457                      p->owner->cid.cid_tns) {
00458 
00459                      struct ast_callerid tmpcid;
00460                      tmpcid = p->owner->cid;
00461                      p->owner->cid = p->chan->_bridge->cid;
00462                      p->chan->_bridge->cid = tmpcid;
00463                   }
00464 
00465                   ast_app_group_update(p->chan, p->owner);
00466                   ast_channel_masquerade(p->owner, p->chan->_bridge);
00467                   ast_set_flag(p, LOCAL_ALREADY_MASQED);
00468                }
00469                ast_channel_unlock(p->owner);
00470             }
00471             ast_channel_unlock(p->chan->_bridge);
00472          }
00473       }
00474    }
00475 }
00476 
00477 static struct ast_frame  *local_read(struct ast_channel *ast)
00478 {
00479    return &ast_null_frame;
00480 }
00481 
00482 static int local_write(struct ast_channel *ast, struct ast_frame *f)
00483 {
00484    struct local_pvt *p = ast->tech_pvt;
00485    int res = -1;
00486    int isoutbound;
00487 
00488    if (!p)
00489       return -1;
00490 
00491    /* Just queue for delivery to the other side */
00492    ao2_lock(p);
00493    ao2_ref(p, 1); /* ref for local_queue_frame */
00494    isoutbound = IS_OUTBOUND(ast, p);
00495    if (isoutbound && f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO))
00496       check_bridge(p);
00497    if (!ast_test_flag(p, LOCAL_ALREADY_MASQED))
00498       res = local_queue_frame(p, isoutbound, f, ast, 1);
00499    else {
00500       ast_debug(1, "Not posting to queue since already masked on '%s'\n", ast->name);
00501       res = 0;
00502    }
00503    ao2_unlock(p);
00504    ao2_ref(p, -1);
00505 
00506    return res;
00507 }
00508 
00509 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00510 {
00511    struct local_pvt *p = newchan->tech_pvt;
00512 
00513    if (!p)
00514       return -1;
00515 
00516    ao2_lock(p);
00517 
00518    if ((p->owner != oldchan) && (p->chan != oldchan)) {
00519       ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
00520       ao2_unlock(p);
00521       return -1;
00522    }
00523    if (p->owner == oldchan)
00524       p->owner = newchan;
00525    else
00526       p->chan = newchan;
00527 
00528    /* Do not let a masquerade cause a Local channel to be bridged to itself! */
00529    if (!ast_check_hangup(newchan) && (p->owner->_bridge == p->chan || p->chan->_bridge == p->owner)) {
00530       ast_log(LOG_WARNING, "You can not bridge a Local channel to itself!\n");
00531       ao2_unlock(p);
00532       ast_queue_hangup(newchan);
00533       return -1;
00534    }
00535 
00536    ao2_unlock(p);
00537    return 0;
00538 }
00539 
00540 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
00541 {
00542    struct local_pvt *p = ast->tech_pvt;
00543    int res = 0;
00544    struct ast_frame f = { AST_FRAME_CONTROL, };
00545    int isoutbound;
00546 
00547    if (!p)
00548       return -1;
00549 
00550    ao2_ref(p, 1); /* ref for local_queue_frame */
00551 
00552    /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
00553    if (!ast_test_flag(p, LOCAL_MOH_PASSTHRU) && condition == AST_CONTROL_HOLD) {
00554       ast_moh_start(ast, data, NULL);
00555    } else if (!ast_test_flag(p, LOCAL_MOH_PASSTHRU) && condition == AST_CONTROL_UNHOLD) {
00556       ast_moh_stop(ast);
00557    } else {
00558       /* Queue up a frame representing the indication as a control frame */
00559       ao2_lock(p);
00560       isoutbound = IS_OUTBOUND(ast, p);
00561       f.subclass = condition;
00562       f.data.ptr = (void*)data;
00563       f.datalen = datalen;
00564       res = local_queue_frame(p, isoutbound, &f, ast, 1);
00565       ao2_unlock(p);
00566    }
00567 
00568    ao2_ref(p, -1);
00569    return res;
00570 }
00571 
00572 static int local_digit_begin(struct ast_channel *ast, char digit)
00573 {
00574    struct local_pvt *p = ast->tech_pvt;
00575    int res = -1;
00576    struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
00577    int isoutbound;
00578 
00579    if (!p)
00580       return -1;
00581 
00582    ao2_ref(p, 1); /* ref for local_queue_frame */
00583    ao2_lock(p);
00584    isoutbound = IS_OUTBOUND(ast, p);
00585    f.subclass = digit;
00586    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00587    ao2_unlock(p);
00588    ao2_ref(p, -1);
00589 
00590    return res;
00591 }
00592 
00593 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
00594 {
00595    struct local_pvt *p = ast->tech_pvt;
00596    int res = -1;
00597    struct ast_frame f = { AST_FRAME_DTMF_END, };
00598    int isoutbound;
00599 
00600    if (!p)
00601       return -1;
00602 
00603    ao2_lock(p);
00604    ao2_ref(p, 1); /* ref for local_queue_frame */
00605    isoutbound = IS_OUTBOUND(ast, p);
00606    f.subclass = digit;
00607    f.len = duration;
00608    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00609    ao2_unlock(p);
00610    ao2_ref(p, -1);
00611 
00612    return res;
00613 }
00614 
00615 static int local_sendtext(struct ast_channel *ast, const char *text)
00616 {
00617    struct local_pvt *p = ast->tech_pvt;
00618    int res = -1;
00619    struct ast_frame f = { AST_FRAME_TEXT, };
00620    int isoutbound;
00621 
00622    if (!p)
00623       return -1;
00624 
00625    ao2_lock(p);
00626    ao2_ref(p, 1); /* ref for local_queue_frame */
00627    isoutbound = IS_OUTBOUND(ast, p);
00628    f.data.ptr = (char *) text;
00629    f.datalen = strlen(text) + 1;
00630    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00631    ao2_unlock(p);
00632    ao2_ref(p, -1);
00633    return res;
00634 }
00635 
00636 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
00637 {
00638    struct local_pvt *p = ast->tech_pvt;
00639    int res = -1;
00640    struct ast_frame f = { AST_FRAME_HTML, };
00641    int isoutbound;
00642 
00643    if (!p)
00644       return -1;
00645    
00646    ao2_lock(p);
00647    ao2_ref(p, 1); /* ref for local_queue_frame */
00648    isoutbound = IS_OUTBOUND(ast, p);
00649    f.subclass = subclass;
00650    f.data.ptr = (char *)data;
00651    f.datalen = datalen;
00652    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00653    ao2_unlock(p);
00654    ao2_ref(p, -1);
00655    return res;
00656 }
00657 
00658 /*! \brief Initiate new call, part of PBX interface 
00659  *    dest is the dial string */
00660 static int local_call(struct ast_channel *ast, char *dest, int timeout)
00661 {
00662    struct local_pvt *p = ast->tech_pvt;
00663    int res = 0;
00664    struct ast_var_t *varptr = NULL, *new;
00665    size_t len, namelen;
00666 
00667    if (!p)
00668       return -1;
00669 
00670    ao2_lock(p);
00671 
00672    /*
00673     * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
00674     * call, so it's done here instead.
00675     */
00676    p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid);
00677    p->chan->cid.cid_num = ast_strdup(p->owner->cid.cid_num);
00678    p->chan->cid.cid_name = ast_strdup(p->owner->cid.cid_name);
00679    p->chan->cid.cid_rdnis = ast_strdup(p->owner->cid.cid_rdnis);
00680    p->chan->cid.cid_ani = ast_strdup(p->owner->cid.cid_ani);
00681    p->chan->cid.cid_pres = p->owner->cid.cid_pres;
00682    p->chan->cid.cid_ani2 = p->owner->cid.cid_ani2;
00683    p->chan->cid.cid_ton = p->owner->cid.cid_ton;
00684    p->chan->cid.cid_tns = p->owner->cid.cid_tns;
00685    ast_string_field_set(p->chan, language, p->owner->language);
00686    ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
00687    ast_string_field_set(p->chan, musicclass, p->owner->musicclass);
00688    ast_cdr_update(p->chan);
00689    p->chan->cdrflags = p->owner->cdrflags;
00690 
00691    /* Make sure we inherit the ANSWERED_ELSEWHERE flag if it's set on the queue/dial call request in the dialplan */
00692    if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
00693       ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
00694    }
00695 
00696    /* copy the channel variables from the incoming channel to the outgoing channel */
00697    /* Note that due to certain assumptions, they MUST be in the same order */
00698    AST_LIST_TRAVERSE(&p->owner->varshead, varptr, entries) {
00699       namelen = strlen(varptr->name);
00700       len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
00701       if ((new = ast_calloc(1, len))) {
00702          memcpy(new, varptr, len);
00703          new->value = &(new->name[0]) + namelen + 1;
00704          AST_LIST_INSERT_TAIL(&p->chan->varshead, new, entries);
00705       }
00706    }
00707    ast_channel_datastore_inherit(p->owner, p->chan);
00708 
00709    if (!ast_exists_extension(p->chan, p->chan->context, p->chan->exten, 1, p->owner->cid.cid_num)) {
00710       ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n", p->chan->exten, p->chan->context);
00711       ao2_unlock(p);
00712       return -1;
00713    }
00714 
00715    /* Start switch on sub channel */
00716    if (!(res = ast_pbx_start(p->chan)))
00717       ast_set_flag(p, LOCAL_LAUNCHED_PBX);
00718 
00719    ao2_unlock(p);
00720    return res;
00721 }
00722 
00723 /*! \brief Hangup a call through the local proxy channel */
00724 static int local_hangup(struct ast_channel *ast)
00725 {
00726    struct local_pvt *p = ast->tech_pvt;
00727    int isoutbound;
00728    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP, .data.uint32 = ast->hangupcause };
00729    struct ast_channel *ochan = NULL;
00730 
00731    if (!p)
00732       return -1;
00733 
00734    /* we MUST give the tech_pvt a ref here since we are unlocking the
00735     * channel during deadlock avoidance. */
00736    ao2_ref(p, 1);
00737 
00738    ao2_lock(p);
00739 
00740    isoutbound = IS_OUTBOUND(ast, p);
00741 
00742    if (p->chan && ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
00743       ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
00744       ast_debug(2, "This local call has the ANSWERED_ELSEWHERE flag set.\n");
00745    }
00746 
00747    if (isoutbound) {
00748       const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
00749       if ((status) && (p->owner)) {
00750          /* Deadlock avoidance */
00751          while (p->owner && ast_channel_trylock(p->owner)) {
00752             ao2_unlock(p);
00753             if (p->chan) {
00754                ast_channel_unlock(p->chan);
00755             }
00756             sched_yield();
00757             if (p->chan) {
00758                ast_channel_lock(p->chan);
00759             }
00760             ao2_lock(p);
00761          }
00762          if (p->owner) {
00763             p->owner->hangupcause = p->chan->hangupcause;
00764             pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
00765             ast_channel_unlock(p->owner);
00766          }
00767       }
00768       if (!p->chan) {
00769          /* chan was == to ast and was !NULL before deadlock avoidance started, if chan
00770           * is NULL now, then we should bail because that channel
00771           * hungup already. This is possible because we let go of the
00772           * lock given to the ast channel passed to this function during
00773           * deadlock avoidance. */
00774          ao2_unlock(p);
00775          ao2_ref(p, -1);
00776          return 0;
00777       }
00778       p->chan = NULL;
00779       ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
00780       ast_module_user_remove(p->u_chan);
00781    } else {
00782       ast_module_user_remove(p->u_owner);
00783       while (p->chan && ast_channel_trylock(p->chan)) {
00784             ao2_unlock(p);
00785             if (p->owner) {
00786                ast_channel_unlock(p->owner);
00787             }
00788             sched_yield();
00789             if (p->owner) {
00790                ast_channel_lock(p->owner);
00791             }
00792             ao2_lock(p);
00793       }
00794       if (p->chan) {
00795          ast_queue_hangup(p->chan);
00796          ast_channel_unlock(p->chan);
00797       }
00798 
00799       if (!p->owner) {
00800          /* owner was == to ast and was !NULL before deadlock avoidance started, if
00801           * owner is NULL now, then we should bail because that channel
00802           * hungup already. This is possible because we let go of the
00803           * lock given to the ast channel passed to this function during
00804           * deadlock avoidance. */
00805          ao2_unlock(p);
00806          ao2_ref(p, -1);
00807          return 0;
00808       }
00809       p->owner = NULL;
00810    }
00811 
00812    ast->tech_pvt = NULL;
00813 
00814    if (!p->owner && !p->chan) {
00815       ao2_unlock(p);
00816 
00817       /* Remove from list */
00818       ao2_unlink(locals, p);
00819       ao2_ref(p, -1);
00820       return 0;
00821    }
00822    if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX)) {
00823       /* Need to actually hangup since there is no PBX */
00824       ochan = p->chan;
00825    } else {
00826       local_queue_frame(p, isoutbound, &f, NULL, 1);
00827    }
00828 
00829    ao2_unlock(p);
00830    if (ochan) {
00831       ast_hangup(ochan);
00832    }
00833 
00834    ao2_ref(p, -1);
00835    return 0;
00836 }
00837 
00838 /*! \brief Create a call structure */
00839 static struct local_pvt *local_alloc(const char *data, int format)
00840 {
00841    struct local_pvt *tmp = NULL;
00842    char *c = NULL, *opts = NULL;
00843 
00844    if (!(tmp = ao2_alloc(sizeof(*tmp), NULL))) {
00845       return NULL;
00846    }
00847 
00848    /* Initialize private structure information */
00849    ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
00850 
00851    memcpy(&tmp->jb_conf, &g_jb_conf, sizeof(tmp->jb_conf));
00852 
00853    /* Look for options */
00854    if ((opts = strchr(tmp->exten, '/'))) {
00855       *opts++ = '\0';
00856       if (strchr(opts, 'n'))
00857          ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
00858       if (strchr(opts, 'j')) {
00859          if (ast_test_flag(tmp, LOCAL_NO_OPTIMIZATION))
00860             ast_set_flag(&tmp->jb_conf, AST_JB_ENABLED);
00861          else {
00862             ast_log(LOG_ERROR, "You must use the 'n' option for chan_local "
00863                "to use the 'j' option to enable the jitterbuffer\n");
00864          }
00865       }
00866       if (strchr(opts, 'b')) {
00867          ast_set_flag(tmp, LOCAL_BRIDGE);
00868       }
00869       if (strchr(opts, 'm')) {
00870          ast_set_flag(tmp, LOCAL_MOH_PASSTHRU);
00871       }
00872    }
00873 
00874    /* Look for a context */
00875    if ((c = strchr(tmp->exten, '@')))
00876       *c++ = '\0';
00877 
00878    ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
00879 
00880    tmp->reqformat = format;
00881 
00882 #if 0
00883    /* We can't do this check here, because we don't know the CallerID yet, and
00884     * the CallerID could potentially affect what step is actually taken (or
00885     * even if that step exists). */
00886    if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
00887       ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
00888       tmp = local_pvt_destroy(tmp);
00889    } else {
00890 #endif
00891       /* Add to list */
00892       ao2_link(locals, tmp);
00893 #if 0
00894    }
00895 #endif
00896    return tmp; /* this is returned with a ref */
00897 }
00898 
00899 /*! \brief Start new local channel */
00900 static struct ast_channel *local_new(struct local_pvt *p, int state)
00901 {
00902    struct ast_channel *tmp = NULL, *tmp2 = NULL;
00903    int randnum = ast_random() & 0xffff, fmt = 0;
00904    const char *t;
00905    int ama;
00906 
00907    /* Allocate two new Asterisk channels */
00908    /* safe accountcode */
00909    if (p->owner && p->owner->accountcode)
00910       t = p->owner->accountcode;
00911    else
00912       t = "";
00913 
00914    if (p->owner)
00915       ama = p->owner->amaflags;
00916    else
00917       ama = 0;
00918    if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;1", p->exten, p->context, randnum)) 
00919          || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, ama, "Local/%s@%s-%04x;2", p->exten, p->context, randnum))) {
00920       if (tmp)
00921          ast_channel_free(tmp);
00922       if (tmp2)
00923          ast_channel_free(tmp2);
00924       ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
00925       return NULL;
00926    } 
00927 
00928    tmp2->tech = tmp->tech = &local_tech;
00929 
00930    tmp->nativeformats = p->reqformat;
00931    tmp2->nativeformats = p->reqformat;
00932 
00933    /* Determine our read/write format and set it on each channel */
00934    fmt = ast_best_codec(p->reqformat);
00935    tmp->writeformat = fmt;
00936    tmp2->writeformat = fmt;
00937    tmp->rawwriteformat = fmt;
00938    tmp2->rawwriteformat = fmt;
00939    tmp->readformat = fmt;
00940    tmp2->readformat = fmt;
00941    tmp->rawreadformat = fmt;
00942    tmp2->rawreadformat = fmt;
00943 
00944    tmp->tech_pvt = p;
00945    tmp2->tech_pvt = p;
00946 
00947    p->owner = tmp;
00948    p->chan = tmp2;
00949    p->u_owner = ast_module_user_add(p->owner);
00950    p->u_chan = ast_module_user_add(p->chan);
00951 
00952    ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
00953    ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
00954    ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
00955    tmp->priority = 1;
00956    tmp2->priority = 1;
00957 
00958    ast_jb_configure(tmp, &p->jb_conf);
00959 
00960    return tmp;
00961 }
00962 
00963 /*! \brief Part of PBX interface */
00964 static struct ast_channel *local_request(const char *type, int format, void *data, int *cause)
00965 {
00966    struct local_pvt *p = NULL;
00967    struct ast_channel *chan = NULL;
00968 
00969    /* Allocate a new private structure and then Asterisk channel */
00970    if ((p = local_alloc(data, format))) {
00971       if (!(chan = local_new(p, AST_STATE_DOWN))) {
00972          ao2_unlink(locals, p);
00973       }
00974       ao2_ref(p, -1); /* kill the ref from the alloc */
00975    }
00976 
00977    return chan;
00978 }
00979 
00980 /*! \brief CLI command "local show channels" */
00981 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00982 {
00983    struct local_pvt *p = NULL;
00984    struct ao2_iterator it;
00985 
00986    switch (cmd) {
00987    case CLI_INIT:
00988       e->command = "local show channels";
00989       e->usage =
00990          "Usage: local show channels\n"
00991          "       Provides summary information on active local proxy channels.\n";
00992       return NULL;
00993    case CLI_GENERATE:
00994       return NULL;
00995    }
00996 
00997    if (a->argc != 3)
00998       return CLI_SHOWUSAGE;
00999 
01000    if (ao2_container_count(locals) == 0) {
01001       ast_cli(a->fd, "No local channels in use\n");
01002       return RESULT_SUCCESS;
01003    }
01004 
01005    it = ao2_iterator_init(locals, 0);
01006    while ((p = ao2_iterator_next(&it))) {
01007       ao2_lock(p);
01008       ast_cli(a->fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
01009       ao2_unlock(p);
01010       ao2_ref(p, -1);
01011    }
01012    ao2_iterator_destroy(&it);
01013 
01014    return CLI_SUCCESS;
01015 }
01016 
01017 static struct ast_cli_entry cli_local[] = {
01018    AST_CLI_DEFINE(locals_show, "List status of local channels"),
01019 };
01020 
01021 static int locals_cmp_cb(void *obj, void *arg, int flags)
01022 {
01023    return (obj == arg) ? CMP_MATCH : 0;
01024 }
01025 
01026 /*! \brief Load module into PBX, register channel */
01027 static int load_module(void)
01028 {
01029    if (!(locals = ao2_container_alloc(BUCKET_SIZE, NULL, locals_cmp_cb))) {
01030       return AST_MODULE_LOAD_FAILURE;
01031    }
01032 
01033    /* Make sure we can register our channel type */
01034    if (ast_channel_register(&local_tech)) {
01035       ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
01036       ao2_ref(locals, -1);
01037       return AST_MODULE_LOAD_FAILURE;
01038    }
01039    ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
01040    return AST_MODULE_LOAD_SUCCESS;
01041 }
01042 
01043 /*! \brief Unload the local proxy channel from Asterisk */
01044 static int unload_module(void)
01045 {
01046    struct local_pvt *p = NULL;
01047    struct ao2_iterator it;
01048 
01049    /* First, take us out of the channel loop */
01050    ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
01051    ast_channel_unregister(&local_tech);
01052 
01053    it = ao2_iterator_init(locals, 0);
01054    while ((p = ao2_iterator_next(&it))) {
01055       if (p->owner) {
01056          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01057       }
01058       ao2_ref(p, -1);
01059    }
01060    ao2_iterator_destroy(&it);
01061    ao2_ref(locals, -1);
01062    return 0;
01063 }
01064 
01065 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Local Proxy Channel (Note: used internally by other modules)");