Wed Nov 28 2012 04:18:06

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 /*** MODULEINFO
00029    <support_level>core</support_level>
00030  ***/
00031 
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 373878 $")
00035 
00036 #include <fcntl.h>
00037 #include <sys/signal.h>
00038 
00039 #include "asterisk/lock.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/config.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/pbx.h"
00044 #include "asterisk/sched.h"
00045 #include "asterisk/io.h"
00046 #include "asterisk/acl.h"
00047 #include "asterisk/callerid.h"
00048 #include "asterisk/file.h"
00049 #include "asterisk/cli.h"
00050 #include "asterisk/app.h"
00051 #include "asterisk/musiconhold.h"
00052 #include "asterisk/manager.h"
00053 #include "asterisk/stringfields.h"
00054 #include "asterisk/devicestate.h"
00055 #include "asterisk/astobj2.h"
00056 
00057 /*** DOCUMENTATION
00058    <manager name="LocalOptimizeAway" language="en_US">
00059       <synopsis>
00060          Optimize away a local channel when possible.
00061       </synopsis>
00062       <syntax>
00063          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00064          <parameter name="Channel" required="true">
00065             <para>The channel name to optimize away.</para>
00066          </parameter>
00067       </syntax>
00068       <description>
00069          <para>A local channel created with "/n" will not automatically optimize away.
00070          Calling this command on the local channel will clear that flag and allow
00071          it to optimize away if it's bridged or when it becomes bridged.</para>
00072       </description>
00073    </manager>
00074  ***/
00075 
00076 static const char tdesc[] = "Local Proxy Channel Driver";
00077 
00078 #define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
00079 
00080 /* right now we are treating the locals astobj2 container as a
00081  * list.  If there is ever a reason to make this more efficient
00082  * increasing the bucket size would help. */
00083 static const int BUCKET_SIZE = 1;
00084 
00085 static struct ao2_container *locals;
00086 
00087 static unsigned int name_sequence = 0;
00088 
00089 static struct ast_jb_conf g_jb_conf = {
00090    .flags = 0,
00091    .max_size = -1,
00092    .resync_threshold = -1,
00093    .impl = "",
00094    .target_extra = -1,
00095 };
00096 
00097 static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
00098 static int local_digit_begin(struct ast_channel *ast, char digit);
00099 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00100 static int local_call(struct ast_channel *ast, char *dest, int timeout);
00101 static int local_hangup(struct ast_channel *ast);
00102 static int local_answer(struct ast_channel *ast);
00103 static struct ast_frame *local_read(struct ast_channel *ast);
00104 static int local_write(struct ast_channel *ast, struct ast_frame *f);
00105 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
00106 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00107 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
00108 static int local_sendtext(struct ast_channel *ast, const char *text);
00109 static int local_devicestate(void *data);
00110 static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
00111 static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen);
00112 static int local_setoption(struct ast_channel *chan, int option, void *data, int datalen);
00113 
00114 /* PBX interface structure for channel registration */
00115 static const struct ast_channel_tech local_tech = {
00116    .type = "Local",
00117    .description = tdesc,
00118    .capabilities = -1,
00119    .requester = local_request,
00120    .send_digit_begin = local_digit_begin,
00121    .send_digit_end = local_digit_end,
00122    .call = local_call,
00123    .hangup = local_hangup,
00124    .answer = local_answer,
00125    .read = local_read,
00126    .write = local_write,
00127    .write_video = local_write,
00128    .exception = local_read,
00129    .indicate = local_indicate,
00130    .fixup = local_fixup,
00131    .send_html = local_sendhtml,
00132    .send_text = local_sendtext,
00133    .devicestate = local_devicestate,
00134    .bridged_channel = local_bridgedchannel,
00135    .queryoption = local_queryoption,
00136    .setoption = local_setoption,
00137 };
00138 
00139 /*! \brief the local pvt structure for all channels
00140 
00141    The local channel pvt has two ast_chan objects - the "owner" and the "next channel", the outbound channel
00142 
00143    ast_chan owner -> local_pvt -> ast_chan chan -> yet-another-pvt-depending-on-channel-type
00144 
00145 */
00146 struct local_pvt {
00147    unsigned int flags;                     /*!< Private flags */
00148    char context[AST_MAX_CONTEXT];      /*!< Context to call */
00149    char exten[AST_MAX_EXTENSION];      /*!< Extension to call */
00150    format_t reqformat;           /*!< Requested format */
00151    struct ast_jb_conf jb_conf;      /*!< jitterbuffer configuration for this local channel */
00152    struct ast_channel *owner;    /*!< Master Channel - Bridging happens here */
00153    struct ast_channel *chan;     /*!< Outbound channel - PBX is run here */
00154    struct ast_module_user *u_owner; /*!< reference to keep the module loaded while in use */
00155    struct ast_module_user *u_chan;     /*!< reference to keep the module loaded while in use */
00156 };
00157 
00158 #define LOCAL_ALREADY_MASQED  (1 << 0) /*!< Already masqueraded */
00159 #define LOCAL_LAUNCHED_PBX    (1 << 1) /*!< PBX was launched */
00160 #define LOCAL_NO_OPTIMIZATION (1 << 2) /*!< Do not optimize using masquerading */
00161 #define LOCAL_BRIDGE          (1 << 3) /*!< Report back the "true" channel as being bridged to */
00162 #define LOCAL_MOH_PASSTHRU    (1 << 4) /*!< Pass through music on hold start/stop frames */
00163 
00164 /* 
00165  * \brief Send a pvt in with no locks held and get all locks
00166  *
00167  * \note NO locks should be held prior to calling this function
00168  * \note The pvt must have a ref held before calling this function
00169  * \note if outchan or outowner is set != NULL after calling this function
00170  *       those channels are locked and reffed.
00171  * \note Batman.
00172  */
00173 static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
00174 {
00175    struct ast_channel *chan = NULL;
00176    struct ast_channel *owner = NULL;
00177 
00178    for (;;) {
00179       ao2_lock(p);
00180       if (p->chan) {
00181          chan = p->chan;
00182          ast_channel_ref(chan);
00183       }
00184       if (p->owner) {
00185          owner = p->owner;
00186          ast_channel_ref(owner);
00187       }
00188       ao2_unlock(p);
00189 
00190       /* if we don't have both channels, then this is very easy */
00191       if (!owner || !chan) {
00192          if (owner) {
00193             ast_channel_lock(owner);
00194          } else if(chan) {
00195             ast_channel_lock(chan);
00196          }
00197          ao2_lock(p);
00198       } else {
00199          /* lock both channels first, then get the pvt lock */
00200          ast_channel_lock(chan);
00201          while (ast_channel_trylock(owner)) {
00202             CHANNEL_DEADLOCK_AVOIDANCE(chan);
00203          }
00204          ao2_lock(p);
00205       }
00206 
00207       /* Now that we have all the locks, validate that nothing changed */
00208       if (p->owner != owner || p->chan != chan) {
00209          if (owner) {
00210             ast_channel_unlock(owner);
00211             owner = ast_channel_unref(owner);
00212          }
00213          if (chan) {
00214             ast_channel_unlock(chan);
00215             chan = ast_channel_unref(chan);
00216          }
00217          ao2_unlock(p);
00218          continue;
00219       }
00220 
00221       break;
00222    }
00223    *outowner = p->owner;
00224    *outchan = p->chan;
00225 }
00226 
00227 /* Called with ast locked */
00228 static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen)
00229 {
00230    int res = 0;
00231    struct local_pvt *p = NULL;
00232    struct ast_channel *otherchan = NULL;
00233    ast_chan_write_info_t *write_info;
00234 
00235    if (option != AST_OPTION_CHANNEL_WRITE) {
00236       return -1;
00237    }
00238 
00239    write_info = data;
00240 
00241    if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
00242       ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
00243       return -1;
00244    }
00245 
00246    /* get the tech pvt */
00247    if (!(p = ast->tech_pvt)) {
00248       return -1;
00249    }
00250    ao2_ref(p, 1);
00251    ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
00252 
00253    /* get the channel we are supposed to write to */
00254    ao2_lock(p);
00255    otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
00256    if (!otherchan || otherchan == write_info->chan) {
00257       res = -1;
00258       otherchan = NULL;
00259       ao2_unlock(p);
00260       goto setoption_cleanup;
00261    }
00262    ast_channel_ref(otherchan);
00263 
00264    /* clear the pvt lock before grabbing the channel */
00265    ao2_unlock(p);
00266 
00267    ast_channel_lock(otherchan);
00268    res = write_info->write_fn(otherchan, write_info->function, write_info->data, write_info->value);
00269    ast_channel_unlock(otherchan);
00270 
00271 setoption_cleanup:
00272    if (p) {
00273       ao2_ref(p, -1);
00274    }
00275    if (otherchan) {
00276       ast_channel_unref(otherchan);
00277    }
00278    ast_channel_lock(ast); /* Lock back before we leave */
00279    return res;
00280 }
00281 
00282 /*! \brief Adds devicestate to local channels */
00283 static int local_devicestate(void *data)
00284 {
00285    char *exten = ast_strdupa(data);
00286    char *context = NULL, *opts = NULL;
00287    int res;
00288    struct local_pvt *lp;
00289    struct ao2_iterator it;
00290 
00291    if (!(context = strchr(exten, '@'))) {
00292       ast_log(LOG_WARNING, "Someone used Local/%s somewhere without a @context. This is bad.\n", exten);
00293       return AST_DEVICE_INVALID; 
00294    }
00295 
00296    *context++ = '\0';
00297 
00298    /* Strip options if they exist */
00299    if ((opts = strchr(context, '/')))
00300       *opts = '\0';
00301 
00302    ast_debug(3, "Checking if extension %s@%s exists (devicestate)\n", exten, context);
00303 
00304    res = ast_exists_extension(NULL, context, exten, 1, NULL);
00305    if (!res)      
00306       return AST_DEVICE_INVALID;
00307    
00308    res = AST_DEVICE_NOT_INUSE;
00309 
00310    it = ao2_iterator_init(locals, 0);
00311    while ((lp = ao2_iterator_next(&it)) && (res == AST_DEVICE_NOT_INUSE)) {
00312       if (!strcmp(exten, lp->exten) && !strcmp(context, lp->context) && lp->owner) {
00313          ao2_lock(lp);
00314          if (ast_test_flag(lp, LOCAL_LAUNCHED_PBX)) {
00315             res = AST_DEVICE_INUSE;
00316          }
00317          ao2_unlock(lp);
00318       }
00319       ao2_ref(lp, -1);
00320    }
00321    ao2_iterator_destroy(&it);
00322 
00323    return res;
00324 }
00325 
00326 /*! \brief Return the bridged channel of a Local channel */
00327 static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
00328 {
00329    struct local_pvt *p = bridge->tech_pvt;
00330    struct ast_channel *bridged = bridge;
00331 
00332    if (!p) {
00333       ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning <none>\n",
00334          chan->name, bridge->name);
00335       return NULL;
00336    }
00337 
00338    ao2_lock(p);
00339 
00340    if (ast_test_flag(p, LOCAL_BRIDGE)) {
00341       /* Find the opposite channel */
00342       bridged = (bridge == p->owner ? p->chan : p->owner);
00343       
00344       /* Now see if the opposite channel is bridged to anything */
00345       if (!bridged) {
00346          bridged = bridge;
00347       } else if (bridged->_bridge) {
00348          bridged = bridged->_bridge;
00349       }
00350    }
00351 
00352    ao2_unlock(p);
00353 
00354    return bridged;
00355 }
00356 
00357 /* Called with ast locked */
00358 static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
00359 {
00360    struct local_pvt *p;
00361    struct ast_channel *bridged = NULL;
00362    struct ast_channel *tmp = NULL;
00363    int res = 0;
00364 
00365    if (option != AST_OPTION_T38_STATE) {
00366       /* AST_OPTION_T38_STATE is the only supported option at this time */
00367       return -1;
00368    }
00369 
00370    /* for some reason the channel is not locked in channel.c when this function is called */
00371    if (!(p = ast->tech_pvt)) {
00372       return -1;
00373    }
00374 
00375    ao2_lock(p);
00376    if (!(tmp = IS_OUTBOUND(ast, p) ? p->owner : p->chan)) {
00377       ao2_unlock(p);
00378       return -1;
00379    }
00380    ast_channel_ref(tmp);
00381    ao2_unlock(p);
00382    ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
00383 
00384    ast_channel_lock(tmp);
00385    if (!(bridged = ast_bridged_channel(tmp))) {
00386       res = -1;
00387       ast_channel_unlock(tmp);
00388       goto query_cleanup;
00389    }
00390    ast_channel_ref(bridged);
00391    ast_channel_unlock(tmp);
00392 
00393 query_cleanup:
00394    if (bridged) {
00395       res = ast_channel_queryoption(bridged, option, data, datalen, 0);
00396       bridged = ast_channel_unref(bridged);
00397    }
00398    if (tmp) {
00399       tmp = ast_channel_unref(tmp);
00400    }
00401    ast_channel_lock(ast); /* Lock back before we leave */
00402 
00403    return res;
00404 }
00405 
00406 /*! \brief queue a frame on a to either the p->owner or p->chan
00407  *
00408  * \note the local_pvt MUST have it's ref count bumped before entering this function and
00409  * decremented after this function is called.  This is a side effect of the deadlock
00410  * avoidance that is necessary to lock 2 channels and a tech_pvt.  Without a ref counted
00411  * local_pvt, it is impossible to guarantee it will not be destroyed by another thread
00412  * during deadlock avoidance.
00413  */
00414 static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, 
00415    struct ast_channel *us, int us_locked)
00416 {
00417    struct ast_channel *other = NULL;
00418 
00419    /* Recalculate outbound channel */
00420    other = isoutbound ? p->owner : p->chan;
00421 
00422    if (!other) {
00423       return 0;
00424    }
00425 
00426    /* do not queue frame if generator is on both local channels */
00427    if (us && us->generator && other->generator) {
00428       return 0;
00429    }
00430 
00431    /* grab a ref on the channel before unlocking the pvt,
00432     * other can not go away from us now regardless of locking */
00433    ast_channel_ref(other);
00434    if (us && us_locked) {
00435       ast_channel_unlock(us);
00436    }
00437    ao2_unlock(p);
00438 
00439    if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_RINGING) {
00440       ast_setstate(other, AST_STATE_RINGING);
00441    }
00442    ast_queue_frame(other, f);
00443 
00444    other = ast_channel_unref(other);
00445    if (us && us_locked) {
00446       ast_channel_lock(us);
00447    }
00448    ao2_lock(p);
00449 
00450    return 0;
00451 }
00452 
00453 static int local_answer(struct ast_channel *ast)
00454 {
00455    struct local_pvt *p = ast->tech_pvt;
00456    int isoutbound;
00457    int res = -1;
00458 
00459    if (!p)
00460       return -1;
00461 
00462    ao2_lock(p);
00463    ao2_ref(p, 1);
00464    isoutbound = IS_OUTBOUND(ast, p);
00465    if (isoutbound) {
00466       /* Pass along answer since somebody answered us */
00467       struct ast_frame answer = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
00468       res = local_queue_frame(p, isoutbound, &answer, ast, 1);
00469    } else {
00470       ast_log(LOG_WARNING, "Huh?  Local is being asked to answer?\n");
00471    }
00472    ao2_unlock(p);
00473    ao2_ref(p, -1);
00474    return res;
00475 }
00476 
00477 /*!
00478  * \internal
00479  * \note This function assumes that we're only called from the "outbound" local channel side
00480  *
00481  * \note it is assummed p is locked and reffed before entering this function
00482  */
00483 static void check_bridge(struct ast_channel *ast, struct local_pvt *p)
00484 {
00485    struct ast_channel *owner;
00486    struct ast_channel *chan;
00487    struct ast_channel *bridged_chan;
00488    struct ast_frame *f;
00489 
00490    /* Do a few conditional checks early on just to see if this optimization is possible */
00491    if (ast_test_flag(p, LOCAL_NO_OPTIMIZATION | LOCAL_ALREADY_MASQED)
00492       || !p->chan || !p->owner) {
00493       return;
00494    }
00495 
00496    /* Safely get the channel bridged to p->chan */
00497    chan = ast_channel_ref(p->chan);
00498 
00499    ao2_unlock(p); /* don't call bridged channel with the pvt locked */
00500    bridged_chan = ast_bridged_channel(chan);
00501    ao2_lock(p);
00502 
00503    chan = ast_channel_unref(chan);
00504 
00505    /* since we had to unlock p to get the bridged chan, validate our
00506     * data once again and verify the bridged channel is what we expect
00507     * it to be in order to perform this optimization */
00508    if (ast_test_flag(p, LOCAL_NO_OPTIMIZATION | LOCAL_ALREADY_MASQED)
00509       || !p->chan || !p->owner
00510       || (p->chan->_bridge != bridged_chan)) {
00511       return;
00512    }
00513 
00514    /* only do the masquerade if we are being called on the outbound channel,
00515       if it has been bridged to another channel and if there are no pending
00516       frames on the owner channel (because they would be transferred to the
00517       outbound channel during the masquerade)
00518    */
00519    if (!p->chan->_bridge /* Not ast_bridged_channel!  Only go one step! */
00520       || !AST_LIST_EMPTY(&p->owner->readq)
00521       || ast != p->chan /* Sanity check (should always be false) */) {
00522       return;
00523    }
00524 
00525    /* Masquerade bridged channel into owner */
00526    /* Lock everything we need, one by one, and give up if
00527       we can't get everything.  Remember, we'll get another
00528       chance in just a little bit */
00529    if (ast_channel_trylock(p->chan->_bridge)) {
00530       return;
00531    }
00532    if (ast_check_hangup(p->chan->_bridge) || ast_channel_trylock(p->owner)) {
00533       ast_channel_unlock(p->chan->_bridge);
00534       return;
00535    }
00536 
00537    /*
00538     * At this point we have 4 locks:
00539     * p, p->chan (same as ast), p->chan->_bridge, p->owner
00540     *
00541     * Flush a voice or video frame on the outbound channel to make
00542     * the queue empty faster so we can get optimized out.
00543     */
00544    f = AST_LIST_FIRST(&p->chan->readq);
00545    if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
00546       AST_LIST_REMOVE_HEAD(&p->chan->readq, frame_list);
00547       ast_frfree(f);
00548       f = AST_LIST_FIRST(&p->chan->readq);
00549    }
00550 
00551    if (f
00552       || ast_check_hangup(p->owner)
00553       || ast_channel_masquerade(p->owner, p->chan->_bridge)) {
00554       ast_channel_unlock(p->owner);
00555       ast_channel_unlock(p->chan->_bridge);
00556       return;
00557    }
00558 
00559    /* Masquerade got setup. */
00560    ast_debug(4, "Masquerading %s <- %s\n",
00561       p->owner->name, p->chan->_bridge->name);
00562    if (p->owner->monitor && !p->chan->_bridge->monitor) {
00563       struct ast_channel_monitor *tmp;
00564 
00565       /* If a local channel is being monitored, we don't want a masquerade
00566        * to cause the monitor to go away. Since the masquerade swaps the monitors,
00567        * pre-swapping the monitors before the masquerade will ensure that the monitor
00568        * ends up where it is expected.
00569        */
00570       tmp = p->owner->monitor;
00571       p->owner->monitor = p->chan->_bridge->monitor;
00572       p->chan->_bridge->monitor = tmp;
00573    }
00574    if (p->chan->audiohooks) {
00575       struct ast_audiohook_list *audiohooks_swapper;
00576       audiohooks_swapper = p->chan->audiohooks;
00577       p->chan->audiohooks = p->owner->audiohooks;
00578       p->owner->audiohooks = audiohooks_swapper;
00579    }
00580 
00581    /* If any Caller ID was set, preserve it after masquerade like above. We must check
00582     * to see if Caller ID was set because otherwise we'll mistakingly copy info not
00583     * set from the dialplan and will overwrite the real channel Caller ID. The reason
00584     * for this whole preswapping action is because the Caller ID is set on the channel
00585     * thread (which is the to be masqueraded away local channel) before both local
00586     * channels are optimized away.
00587     */
00588    if (p->owner->caller.id.name.valid || p->owner->caller.id.number.valid
00589       || p->owner->caller.id.subaddress.valid || p->owner->caller.ani.name.valid
00590       || p->owner->caller.ani.number.valid || p->owner->caller.ani.subaddress.valid) {
00591       struct ast_party_caller tmp;
00592 
00593       tmp = p->owner->caller;
00594       p->owner->caller = p->chan->_bridge->caller;
00595       p->chan->_bridge->caller = tmp;
00596    }
00597    if (p->owner->redirecting.from.name.valid || p->owner->redirecting.from.number.valid
00598       || p->owner->redirecting.from.subaddress.valid || p->owner->redirecting.to.name.valid
00599       || p->owner->redirecting.to.number.valid || p->owner->redirecting.to.subaddress.valid) {
00600       struct ast_party_redirecting tmp;
00601 
00602       tmp = p->owner->redirecting;
00603       p->owner->redirecting = p->chan->_bridge->redirecting;
00604       p->chan->_bridge->redirecting = tmp;
00605    }
00606    if (p->owner->dialed.number.str || p->owner->dialed.subaddress.valid) {
00607       struct ast_party_dialed tmp;
00608 
00609       tmp = p->owner->dialed;
00610       p->owner->dialed = p->chan->_bridge->dialed;
00611       p->chan->_bridge->dialed = tmp;
00612    }
00613    ast_app_group_update(p->chan, p->owner);
00614    ast_set_flag(p, LOCAL_ALREADY_MASQED);
00615 
00616    ast_channel_unlock(p->owner);
00617    ast_channel_unlock(p->chan->_bridge);
00618 
00619    /* Do the masquerade now. */
00620    owner = ast_channel_ref(p->owner);
00621    ao2_unlock(p);
00622    ast_channel_unlock(ast);
00623    ast_do_masquerade(owner);
00624    ast_channel_unref(owner);
00625    ast_channel_lock(ast);
00626    ao2_lock(p);
00627 }
00628 
00629 static struct ast_frame  *local_read(struct ast_channel *ast)
00630 {
00631    return &ast_null_frame;
00632 }
00633 
00634 static int local_write(struct ast_channel *ast, struct ast_frame *f)
00635 {
00636    struct local_pvt *p = ast->tech_pvt;
00637    int res = -1;
00638    int isoutbound;
00639 
00640    if (!p) {
00641       return -1;
00642    }
00643 
00644    /* Just queue for delivery to the other side */
00645    ao2_ref(p, 1); /* ref for local_queue_frame */
00646    ao2_lock(p);
00647    isoutbound = IS_OUTBOUND(ast, p);
00648 
00649    if (isoutbound
00650       && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
00651       check_bridge(ast, p);
00652    }
00653 
00654    if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) {
00655       res = local_queue_frame(p, isoutbound, f, ast, 1);
00656    } else {
00657       ast_debug(1, "Not posting to '%s' queue since already masqueraded out\n",
00658          ast->name);
00659       res = 0;
00660    }
00661    ao2_unlock(p);
00662    ao2_ref(p, -1);
00663 
00664    return res;
00665 }
00666 
00667 static int local_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00668 {
00669    struct local_pvt *p = newchan->tech_pvt;
00670 
00671    if (!p)
00672       return -1;
00673 
00674    ao2_lock(p);
00675 
00676    if ((p->owner != oldchan) && (p->chan != oldchan)) {
00677       ast_log(LOG_WARNING, "Old channel wasn't %p but was %p/%p\n", oldchan, p->owner, p->chan);
00678       ao2_unlock(p);
00679       return -1;
00680    }
00681    if (p->owner == oldchan)
00682       p->owner = newchan;
00683    else
00684       p->chan = newchan;
00685 
00686    /* Do not let a masquerade cause a Local channel to be bridged to itself! */
00687    if (!ast_check_hangup(newchan) && ((p->owner && p->owner->_bridge == p->chan) || (p->chan && p->chan->_bridge == p->owner))) {
00688       ast_log(LOG_WARNING, "You can not bridge a Local channel to itself!\n");
00689       ao2_unlock(p);
00690       ast_queue_hangup(newchan);
00691       return -1;
00692    }
00693 
00694    ao2_unlock(p);
00695    return 0;
00696 }
00697 
00698 static int local_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
00699 {
00700    struct local_pvt *p = ast->tech_pvt;
00701    int res = 0;
00702    struct ast_frame f = { AST_FRAME_CONTROL, };
00703    int isoutbound;
00704 
00705    if (!p)
00706       return -1;
00707 
00708    ao2_ref(p, 1); /* ref for local_queue_frame */
00709 
00710    /* If this is an MOH hold or unhold, do it on the Local channel versus real channel */
00711    if (!ast_test_flag(p, LOCAL_MOH_PASSTHRU) && condition == AST_CONTROL_HOLD) {
00712       ast_moh_start(ast, data, NULL);
00713    } else if (!ast_test_flag(p, LOCAL_MOH_PASSTHRU) && condition == AST_CONTROL_UNHOLD) {
00714       ast_moh_stop(ast);
00715    } else if (condition == AST_CONTROL_CONNECTED_LINE || condition == AST_CONTROL_REDIRECTING) {
00716       struct ast_channel *this_channel;
00717       struct ast_channel *the_other_channel;
00718       /* A connected line update frame may only contain a partial amount of data, such
00719        * as just a source, or just a ton, and not the full amount of information. However,
00720        * the collected information is all stored in the outgoing channel's connectedline
00721        * structure, so when receiving a connected line update on an outgoing local channel,
00722        * we need to transmit the collected connected line information instead of whatever
00723        * happens to be in this control frame. The same applies for redirecting information, which
00724        * is why it is handled here as well.*/
00725       ao2_lock(p);
00726       isoutbound = IS_OUTBOUND(ast, p);
00727       if (isoutbound) {
00728          this_channel = p->chan;
00729          the_other_channel = p->owner;
00730       } else {
00731          this_channel = p->owner;
00732          the_other_channel = p->chan;
00733       }
00734       if (the_other_channel) {
00735          unsigned char frame_data[1024];
00736          if (condition == AST_CONTROL_CONNECTED_LINE) {
00737             if (isoutbound) {
00738                ast_connected_line_copy_to_caller(&the_other_channel->caller, &this_channel->connected);
00739             }
00740             f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected, NULL);
00741          } else {
00742             f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting, NULL);
00743          }
00744          f.subclass.integer = condition;
00745          f.data.ptr = frame_data;
00746          res = local_queue_frame(p, isoutbound, &f, ast, 1);
00747       }
00748       ao2_unlock(p);
00749    } else {
00750       /* Queue up a frame representing the indication as a control frame */
00751       ao2_lock(p);
00752       /*
00753        * Block -1 stop tones events if we are to be optimized out.  We
00754        * don't need a flurry of these events on a local channel chain
00755        * when initially connected to slow the optimization process.
00756        */
00757       if (0 <= condition || ast_test_flag(p, LOCAL_NO_OPTIMIZATION)) {
00758          isoutbound = IS_OUTBOUND(ast, p);
00759          f.subclass.integer = condition;
00760          f.data.ptr = (void *) data;
00761          f.datalen = datalen;
00762          res = local_queue_frame(p, isoutbound, &f, ast, 1);
00763 
00764          if (!res && (condition == AST_CONTROL_T38_PARAMETERS) &&
00765              (datalen == sizeof(struct ast_control_t38_parameters))) {
00766             const struct ast_control_t38_parameters *parameters = data;
00767             
00768             if (parameters->request_response == AST_T38_REQUEST_PARMS) {
00769                res = AST_T38_REQUEST_PARMS;
00770             }
00771          }
00772       } else {
00773          ast_debug(4, "Blocked indication %d\n", condition);
00774       }
00775       ao2_unlock(p);
00776    }
00777 
00778    ao2_ref(p, -1);
00779    return res;
00780 }
00781 
00782 static int local_digit_begin(struct ast_channel *ast, char digit)
00783 {
00784    struct local_pvt *p = ast->tech_pvt;
00785    int res = -1;
00786    struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
00787    int isoutbound;
00788 
00789    if (!p)
00790       return -1;
00791 
00792    ao2_ref(p, 1); /* ref for local_queue_frame */
00793    ao2_lock(p);
00794    isoutbound = IS_OUTBOUND(ast, p);
00795    f.subclass.integer = digit;
00796    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00797    ao2_unlock(p);
00798    ao2_ref(p, -1);
00799 
00800    return res;
00801 }
00802 
00803 static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
00804 {
00805    struct local_pvt *p = ast->tech_pvt;
00806    int res = -1;
00807    struct ast_frame f = { AST_FRAME_DTMF_END, };
00808    int isoutbound;
00809 
00810    if (!p)
00811       return -1;
00812 
00813    ao2_ref(p, 1); /* ref for local_queue_frame */
00814    ao2_lock(p);
00815    isoutbound = IS_OUTBOUND(ast, p);
00816    f.subclass.integer = digit;
00817    f.len = duration;
00818    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00819    ao2_unlock(p);
00820    ao2_ref(p, -1);
00821 
00822    return res;
00823 }
00824 
00825 static int local_sendtext(struct ast_channel *ast, const char *text)
00826 {
00827    struct local_pvt *p = ast->tech_pvt;
00828    int res = -1;
00829    struct ast_frame f = { AST_FRAME_TEXT, };
00830    int isoutbound;
00831 
00832    if (!p)
00833       return -1;
00834 
00835    ao2_lock(p);
00836    ao2_ref(p, 1); /* ref for local_queue_frame */
00837    isoutbound = IS_OUTBOUND(ast, p);
00838    f.data.ptr = (char *) text;
00839    f.datalen = strlen(text) + 1;
00840    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00841    ao2_unlock(p);
00842    ao2_ref(p, -1);
00843    return res;
00844 }
00845 
00846 static int local_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
00847 {
00848    struct local_pvt *p = ast->tech_pvt;
00849    int res = -1;
00850    struct ast_frame f = { AST_FRAME_HTML, };
00851    int isoutbound;
00852 
00853    if (!p)
00854       return -1;
00855 
00856    ao2_lock(p);
00857    ao2_ref(p, 1); /* ref for local_queue_frame */
00858    isoutbound = IS_OUTBOUND(ast, p);
00859    f.subclass.integer = subclass;
00860    f.data.ptr = (char *)data;
00861    f.datalen = datalen;
00862    res = local_queue_frame(p, isoutbound, &f, ast, 0);
00863    ao2_unlock(p);
00864    ao2_ref(p, -1);
00865 
00866    return res;
00867 }
00868 
00869 /*! \brief Initiate new call, part of PBX interface 
00870  *    dest is the dial string */
00871 static int local_call(struct ast_channel *ast, char *dest, int timeout)
00872 {
00873    struct local_pvt *p = ast->tech_pvt;
00874    int pvt_locked = 0;
00875 
00876    struct ast_channel *owner = NULL;
00877    struct ast_channel *chan = NULL;
00878    int res;
00879    struct ast_var_t *varptr = NULL, *new;
00880    size_t len, namelen;
00881    char *reduced_dest = ast_strdupa(dest);
00882    char *slash;
00883    const char *exten;
00884    const char *context;
00885 
00886    if (!p) {
00887       return -1;
00888    }
00889 
00890    /* since we are letting go of channel locks that were locked coming into
00891     * this function, then we need to give the tech pvt a ref */
00892    ao2_ref(p, 1);
00893    ast_channel_unlock(ast);
00894 
00895    awesome_locking(p, &chan, &owner);
00896    pvt_locked = 1;
00897 
00898    if (owner != ast) {
00899       res = -1;
00900       goto return_cleanup;
00901    }
00902 
00903    if (!owner || !chan) {
00904       res = -1;
00905       goto return_cleanup;
00906    }
00907 
00908    /*
00909     * Note that cid_num and cid_name aren't passed in the ast_channel_alloc
00910     * call, so it's done here instead.
00911     *
00912     * All these failure points just return -1. The individual strings will
00913     * be cleared when we destroy the channel.
00914     */
00915    ast_party_redirecting_copy(&chan->redirecting, &owner->redirecting);
00916 
00917    ast_party_dialed_copy(&chan->dialed, &owner->dialed);
00918 
00919    ast_connected_line_copy_to_caller(&chan->caller, &owner->connected);
00920    ast_connected_line_copy_from_caller(&chan->connected, &owner->caller);
00921 
00922    ast_string_field_set(chan, language, owner->language);
00923    ast_string_field_set(chan, accountcode, owner->accountcode);
00924    ast_string_field_set(chan, musicclass, owner->musicclass);
00925    ast_cdr_update(chan);
00926 
00927    ast_channel_cc_params_init(chan, ast_channel_get_cc_config_params(owner));
00928 
00929    /* Make sure we inherit the ANSWERED_ELSEWHERE flag if it's set on the queue/dial call request in the dialplan */
00930    if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
00931       ast_set_flag(chan, AST_FLAG_ANSWERED_ELSEWHERE);
00932    }
00933 
00934    /* copy the channel variables from the incoming channel to the outgoing channel */
00935    /* Note that due to certain assumptions, they MUST be in the same order */
00936    AST_LIST_TRAVERSE(&owner->varshead, varptr, entries) {
00937       namelen = strlen(varptr->name);
00938       len = sizeof(struct ast_var_t) + namelen + strlen(varptr->value) + 2;
00939       if ((new = ast_calloc(1, len))) {
00940          memcpy(new, varptr, len);
00941          new->value = &(new->name[0]) + namelen + 1;
00942          AST_LIST_INSERT_TAIL(&chan->varshead, new, entries);
00943       }
00944    }
00945    ast_channel_datastore_inherit(owner, chan);
00946    /* If the local channel has /n or /b on the end of it,
00947     * we need to lop that off for our argument to setting
00948     * up the CC_INTERFACES variable
00949     */
00950    if ((slash = strrchr(reduced_dest, '/'))) {
00951       *slash = '\0';
00952    }
00953    ast_set_cc_interfaces_chanvar(chan, reduced_dest);
00954 
00955    exten = ast_strdupa(chan->exten);
00956    context = ast_strdupa(chan->context);
00957 
00958    ao2_unlock(p);
00959    pvt_locked = 0;
00960 
00961    ast_channel_unlock(chan);
00962 
00963    if (!ast_exists_extension(chan, context, exten, 1,
00964       S_COR(owner->caller.id.number.valid, owner->caller.id.number.str, NULL))) {
00965       ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n", exten, context);
00966       res = -1;
00967       chan = ast_channel_unref(chan); /* we already unlocked it, so clear it hear so the cleanup label won't touch it. */
00968       goto return_cleanup;
00969    }
00970 
00971    /* Start switch on sub channel */
00972    if (!(res = ast_pbx_start(chan))) {
00973       ao2_lock(p);
00974       ast_set_flag(p, LOCAL_LAUNCHED_PBX);
00975       ao2_unlock(p);
00976    }
00977    chan = ast_channel_unref(chan); /* chan is already unlocked, clear it here so the cleanup lable won't touch it. */
00978 
00979 return_cleanup:
00980    if (p) {
00981       if (pvt_locked) {
00982          ao2_unlock(p);
00983       }
00984       ao2_ref(p, -1);
00985    }
00986    if (chan) {
00987       ast_channel_unlock(chan);
00988       chan = ast_channel_unref(chan);
00989    }
00990 
00991    /* owner is supposed to be == to ast,  if it
00992     * is, don't unlock it because ast must exit locked */
00993    if (owner) {
00994       if (owner != ast) {
00995          ast_channel_unlock(owner);
00996          ast_channel_lock(ast);
00997       }
00998       owner = ast_channel_unref(owner);
00999    } else {
01000       /* we have to exit with ast locked */
01001       ast_channel_lock(ast);
01002    }
01003 
01004    return res;
01005 }
01006 
01007 /*! \brief Hangup a call through the local proxy channel */
01008 static int local_hangup(struct ast_channel *ast)
01009 {
01010    struct local_pvt *p = ast->tech_pvt;
01011    int isoutbound;
01012    int hangup_chan = 0;
01013    int res = 0;
01014    struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_HANGUP }, .data.uint32 = ast->hangupcause };
01015    struct ast_channel *owner = NULL;
01016    struct ast_channel *chan = NULL;
01017 
01018    if (!p) {
01019       return -1;
01020    }
01021 
01022    /* give the pvt a ref since we are unlocking the channel. */
01023    ao2_ref(p, 1);
01024 
01025    /* the pvt isn't going anywhere, we gave it a ref */
01026    ast_channel_unlock(ast);
01027 
01028    /* lock everything */
01029    awesome_locking(p, &chan, &owner);
01030 
01031    if (ast != chan && ast != owner) {
01032       res = -1;
01033       goto local_hangup_cleanup;
01034    }
01035 
01036    isoutbound = IS_OUTBOUND(ast, p); /* just comparing pointer of ast */
01037 
01038    if (p->chan && ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) {
01039       ast_set_flag(p->chan, AST_FLAG_ANSWERED_ELSEWHERE);
01040       ast_debug(2, "This local call has the ANSWERED_ELSEWHERE flag set.\n");
01041    }
01042 
01043    if (isoutbound) {
01044       const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
01045       if ((status) && (p->owner)) {
01046          p->owner->hangupcause = p->chan->hangupcause;
01047          pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
01048       }
01049 
01050       ast_clear_flag(p, LOCAL_LAUNCHED_PBX);
01051       ast_module_user_remove(p->u_chan);
01052       p->chan = NULL;
01053    } else {
01054       ast_module_user_remove(p->u_owner);
01055       if (p->chan) {
01056          ast_queue_hangup(p->chan);
01057       }
01058       p->owner = NULL;
01059    }
01060 
01061    ast->tech_pvt = NULL; /* this is one of our locked channels, doesn't matter which */
01062 
01063    if (!p->owner && !p->chan) {
01064       ao2_unlock(p);
01065       /* Remove from list */
01066       ao2_unlink(locals, p);
01067       ao2_ref(p, -1);
01068       p = NULL;
01069       res = 0;
01070       goto local_hangup_cleanup;
01071    }
01072    if (p->chan && !ast_test_flag(p, LOCAL_LAUNCHED_PBX)) {
01073       /* Need to actually hangup since there is no PBX */
01074       hangup_chan = 1;
01075    } else {
01076       local_queue_frame(p, isoutbound, &f, NULL, 0);
01077    }
01078 
01079 local_hangup_cleanup:
01080    if (p) {
01081       ao2_unlock(p);
01082       ao2_ref(p, -1);
01083    }
01084    if (chan) {
01085       ast_channel_unlock(chan);
01086       if (hangup_chan) {
01087          ast_hangup(chan);
01088       }
01089       chan = ast_channel_unref(chan);
01090    }
01091    if (owner) {
01092       ast_channel_unlock(owner);
01093       owner = ast_channel_unref(owner);
01094    }
01095 
01096    /* leave with the same stupid channel locked that came in */
01097    ast_channel_lock(ast);
01098    return res;
01099 }
01100 
01101 /*! \brief Create a call structure */
01102 static struct local_pvt *local_alloc(const char *data, format_t format)
01103 {
01104    struct local_pvt *tmp = NULL;
01105    char *c = NULL, *opts = NULL;
01106 
01107    if (!(tmp = ao2_alloc(sizeof(*tmp), NULL))) {
01108       return NULL;
01109    }
01110 
01111    /* Initialize private structure information */
01112    ast_copy_string(tmp->exten, data, sizeof(tmp->exten));
01113 
01114    memcpy(&tmp->jb_conf, &g_jb_conf, sizeof(tmp->jb_conf));
01115 
01116    /* Look for options */
01117    if ((opts = strchr(tmp->exten, '/'))) {
01118       *opts++ = '\0';
01119       if (strchr(opts, 'n'))
01120          ast_set_flag(tmp, LOCAL_NO_OPTIMIZATION);
01121       if (strchr(opts, 'j')) {
01122          if (ast_test_flag(tmp, LOCAL_NO_OPTIMIZATION))
01123             ast_set_flag(&tmp->jb_conf, AST_JB_ENABLED);
01124          else {
01125             ast_log(LOG_ERROR, "You must use the 'n' option for chan_local "
01126                "to use the 'j' option to enable the jitterbuffer\n");
01127          }
01128       }
01129       if (strchr(opts, 'b')) {
01130          ast_set_flag(tmp, LOCAL_BRIDGE);
01131       }
01132       if (strchr(opts, 'm')) {
01133          ast_set_flag(tmp, LOCAL_MOH_PASSTHRU);
01134       }
01135    }
01136 
01137    /* Look for a context */
01138    if ((c = strchr(tmp->exten, '@')))
01139       *c++ = '\0';
01140 
01141    ast_copy_string(tmp->context, c ? c : "default", sizeof(tmp->context));
01142 
01143    tmp->reqformat = format;
01144 
01145 #if 0
01146    /* We can't do this check here, because we don't know the CallerID yet, and
01147     * the CallerID could potentially affect what step is actually taken (or
01148     * even if that step exists). */
01149    if (!ast_exists_extension(NULL, tmp->context, tmp->exten, 1, NULL)) {
01150       ast_log(LOG_NOTICE, "No such extension/context %s@%s creating local channel\n", tmp->exten, tmp->context);
01151       tmp = local_pvt_destroy(tmp);
01152    } else {
01153 #endif
01154       /* Add to list */
01155       ao2_link(locals, tmp);
01156 #if 0
01157    }
01158 #endif
01159    return tmp; /* this is returned with a ref */
01160 }
01161 
01162 /*! \brief Start new local channel */
01163 static struct ast_channel *local_new(struct local_pvt *p, int state, const char *linkedid)
01164 {
01165    struct ast_channel *tmp = NULL, *tmp2 = NULL;
01166    int fmt = 0;
01167    int generated_seqno = ast_atomic_fetchadd_int((int *)&name_sequence, +1);
01168    const char *t;
01169    int ama;
01170 
01171    /* Allocate two new Asterisk channels */
01172    /* safe accountcode */
01173    if (p->owner && p->owner->accountcode)
01174       t = p->owner->accountcode;
01175    else
01176       t = "";
01177 
01178    if (p->owner)
01179       ama = p->owner->amaflags;
01180    else
01181       ama = 0;
01182 
01183    /* Make sure that the ;2 channel gets the same linkedid as ;1. You can't pass linkedid to both
01184     * allocations since if linkedid isn't set, then each channel will generate its own linkedid. */
01185    if (!(tmp = ast_channel_alloc(1, state, 0, 0, t, p->exten, p->context, linkedid, ama, "Local/%s@%s-%08x;1", p->exten, p->context, generated_seqno))
01186       || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, t, p->exten, p->context, tmp->linkedid, ama, "Local/%s@%s-%08x;2", p->exten, p->context, generated_seqno))) {
01187       if (tmp) {
01188          tmp = ast_channel_release(tmp);
01189       }
01190       ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
01191       return NULL;
01192    }
01193 
01194    tmp2->tech = tmp->tech = &local_tech;
01195 
01196    tmp->nativeformats = p->reqformat;
01197    tmp2->nativeformats = p->reqformat;
01198 
01199    /* Determine our read/write format and set it on each channel */
01200    fmt = ast_best_codec(p->reqformat);
01201    tmp->writeformat = fmt;
01202    tmp2->writeformat = fmt;
01203    tmp->rawwriteformat = fmt;
01204    tmp2->rawwriteformat = fmt;
01205    tmp->readformat = fmt;
01206    tmp2->readformat = fmt;
01207    tmp->rawreadformat = fmt;
01208    tmp2->rawreadformat = fmt;
01209 
01210    tmp->tech_pvt = p;
01211    tmp2->tech_pvt = p;
01212 
01213    p->owner = tmp;
01214    p->chan = tmp2;
01215    p->u_owner = ast_module_user_add(p->owner);
01216    p->u_chan = ast_module_user_add(p->chan);
01217 
01218    ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
01219    ast_copy_string(tmp2->context, p->context, sizeof(tmp2->context));
01220    ast_copy_string(tmp2->exten, p->exten, sizeof(tmp->exten));
01221    tmp->priority = 1;
01222    tmp2->priority = 1;
01223 
01224    ast_jb_configure(tmp, &p->jb_conf);
01225 
01226    return tmp;
01227 }
01228 
01229 /*! \brief Part of PBX interface */
01230 static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
01231 {
01232    struct local_pvt *p;
01233    struct ast_channel *chan;
01234 
01235    /* Allocate a new private structure and then Asterisk channels */
01236    p = local_alloc(data, format);
01237    if (!p) {
01238       return NULL;
01239    }
01240    chan = local_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
01241    if (!chan) {
01242       ao2_unlink(locals, p);
01243    } else if (ast_channel_cc_params_init(chan, requestor ? ast_channel_get_cc_config_params((struct ast_channel *)requestor) : NULL)) {
01244       ao2_unlink(locals, p);
01245       p->owner = ast_channel_release(p->owner);
01246       ast_module_user_remove(p->u_owner);
01247       p->chan = ast_channel_release(p->chan);
01248       ast_module_user_remove(p->u_chan);
01249       chan = NULL;
01250    }
01251    ao2_ref(p, -1); /* kill the ref from the alloc */
01252 
01253    return chan;
01254 }
01255 
01256 /*! \brief CLI command "local show channels" */
01257 static char *locals_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01258 {
01259    struct local_pvt *p = NULL;
01260    struct ao2_iterator it;
01261 
01262    switch (cmd) {
01263    case CLI_INIT:
01264       e->command = "local show channels";
01265       e->usage =
01266          "Usage: local show channels\n"
01267          "       Provides summary information on active local proxy channels.\n";
01268       return NULL;
01269    case CLI_GENERATE:
01270       return NULL;
01271    }
01272 
01273    if (a->argc != 3)
01274       return CLI_SHOWUSAGE;
01275 
01276    if (ao2_container_count(locals) == 0) {
01277       ast_cli(a->fd, "No local channels in use\n");
01278       return RESULT_SUCCESS;
01279    }
01280 
01281    it = ao2_iterator_init(locals, 0);
01282    while ((p = ao2_iterator_next(&it))) {
01283       ao2_lock(p);
01284       ast_cli(a->fd, "%s -- %s@%s\n", p->owner ? p->owner->name : "<unowned>", p->exten, p->context);
01285       ao2_unlock(p);
01286       ao2_ref(p, -1);
01287    }
01288    ao2_iterator_destroy(&it);
01289 
01290    return CLI_SUCCESS;
01291 }
01292 
01293 static struct ast_cli_entry cli_local[] = {
01294    AST_CLI_DEFINE(locals_show, "List status of local channels"),
01295 };
01296 
01297 static int manager_optimize_away(struct mansession *s, const struct message *m)
01298 {
01299    const char *channel;
01300    struct local_pvt *p, *tmp = NULL;
01301    struct ast_channel *c;
01302    int found = 0;
01303    struct ao2_iterator it;
01304 
01305    channel = astman_get_header(m, "Channel");
01306 
01307    if (ast_strlen_zero(channel)) {
01308       astman_send_error(s, m, "'Channel' not specified.");
01309       return 0;
01310    }
01311 
01312    c = ast_channel_get_by_name(channel);
01313    if (!c) {
01314       astman_send_error(s, m, "Channel does not exist.");
01315       return 0;
01316    }
01317 
01318    p = c->tech_pvt;
01319    ast_channel_unref(c);
01320    c = NULL;
01321 
01322    it = ao2_iterator_init(locals, 0);
01323    while ((tmp = ao2_iterator_next(&it))) {
01324       if (tmp == p) {
01325          ao2_lock(tmp);
01326          found = 1;
01327          ast_clear_flag(tmp, LOCAL_NO_OPTIMIZATION);
01328          ao2_unlock(tmp);
01329          ao2_ref(tmp, -1);
01330          break;
01331       }
01332       ao2_ref(tmp, -1);
01333    }
01334    ao2_iterator_destroy(&it);
01335 
01336    if (found) {
01337       astman_send_ack(s, m, "Queued channel to be optimized away");
01338    } else {
01339       astman_send_error(s, m, "Unable to find channel");
01340    }
01341 
01342    return 0;
01343 }
01344 
01345 
01346 static int locals_cmp_cb(void *obj, void *arg, int flags)
01347 {
01348    return (obj == arg) ? CMP_MATCH : 0;
01349 }
01350 
01351 /*! \brief Load module into PBX, register channel */
01352 static int load_module(void)
01353 {
01354    if (!(locals = ao2_container_alloc(BUCKET_SIZE, NULL, locals_cmp_cb))) {
01355       return AST_MODULE_LOAD_FAILURE;
01356    }
01357 
01358    /* Make sure we can register our channel type */
01359    if (ast_channel_register(&local_tech)) {
01360       ast_log(LOG_ERROR, "Unable to register channel class 'Local'\n");
01361       ao2_ref(locals, -1);
01362       return AST_MODULE_LOAD_FAILURE;
01363    }
01364    ast_cli_register_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
01365    ast_manager_register_xml("LocalOptimizeAway", EVENT_FLAG_SYSTEM|EVENT_FLAG_CALL, manager_optimize_away);
01366 
01367    return AST_MODULE_LOAD_SUCCESS;
01368 }
01369 
01370 /*! \brief Unload the local proxy channel from Asterisk */
01371 static int unload_module(void)
01372 {
01373    struct local_pvt *p = NULL;
01374    struct ao2_iterator it;
01375 
01376    /* First, take us out of the channel loop */
01377    ast_cli_unregister_multiple(cli_local, sizeof(cli_local) / sizeof(struct ast_cli_entry));
01378    ast_manager_unregister("LocalOptimizeAway");
01379    ast_channel_unregister(&local_tech);
01380 
01381    it = ao2_iterator_init(locals, 0);
01382    while ((p = ao2_iterator_next(&it))) {
01383       if (p->owner) {
01384          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
01385       }
01386       ao2_ref(p, -1);
01387    }
01388    ao2_iterator_destroy(&it);
01389    ao2_ref(locals, -1);
01390 
01391    return 0;
01392 }
01393 
01394 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Local Proxy Channel (Note: used internally by other modules)",
01395       .load = load_module,
01396       .unload = unload_module,
01397       .load_pri = AST_MODPRI_CHANNEL_DRIVER,
01398    );