bridge_native_dahdi.c File Reference

Native DAHDI bridging support. More...

#include "asterisk.h"
#include "../sig_analog.h"
#include "../chan_dahdi.h"
#include "bridge_native_dahdi.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
#include "asterisk/format_cache.h"

Include dependency graph for bridge_native_dahdi.c:

Go to the source code of this file.

Data Structures

struct  native_pvt_bridge
struct  native_pvt_chan

Functions

int dahdi_native_load (struct ast_module *mod, const struct ast_channel_tech *tech)
void dahdi_native_unload (void)
static int native_bridge_changed (struct ast_bridge *bridge)
static int native_bridge_compatible (struct ast_bridge *bridge)
static int native_bridge_create (struct ast_bridge *bridge)
static void native_bridge_destroy (struct ast_bridge *bridge)
static int native_bridge_is_capable (struct ast_bridge_channel *bridge_channel)
static int native_bridge_join (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static void native_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static int native_bridge_start (struct ast_bridge *bridge)
static void native_bridge_stop (struct ast_bridge *bridge)
static void native_bridge_suspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static void native_bridge_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static int native_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static int native_chan_changed (struct ast_bridge_channel *bridge_channel)
static void native_request_start (struct ast_bridge *bridge)
static void native_request_stop (struct ast_bridge *bridge)
static int native_start (struct ast_bridge *bridge)
static void native_stop (struct ast_bridge *bridge)

Variables

static struct ast_channel_techdahdi_tech
static struct ast_bridge_technology native_bridge


Detailed Description

Native DAHDI bridging support.

Author:
Richard Mudgett <rmudgett@digium.com>
See Also:

Definition in file bridge_native_dahdi.c.


Function Documentation

int dahdi_native_load ( struct ast_module mod,
const struct ast_channel_tech tech 
)

Definition at line 906 of file bridge_native_dahdi.c.

References __ast_bridge_technology_register(), and dahdi_native_unload().

Referenced by load_module().

00907 {
00908    dahdi_tech = tech;
00909 
00910    if (__ast_bridge_technology_register(&native_bridge, mod)) {
00911       dahdi_native_unload();
00912       return -1;
00913    }
00914 
00915    return 0;
00916 }

void dahdi_native_unload ( void   ) 

Definition at line 893 of file bridge_native_dahdi.c.

References ast_bridge_technology_unregister().

Referenced by __unload_module(), and dahdi_native_load().

static int native_bridge_changed ( struct ast_bridge bridge  )  [static]

Definition at line 795 of file bridge_native_dahdi.c.

References ast_channel_name(), ast_debug, AST_LIST_TRAVERSE, ast_bridge_channel::chan, ast_bridge::channels, native_chan_changed(), and ast_bridge::uniqueid.

Referenced by native_bridge_write().

00796 {
00797    struct ast_bridge_channel *cur;
00798 
00799    AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
00800       if (native_chan_changed(cur)) {
00801          ast_debug(1, "Bridge %s: Something changed on channel '%s'.\n",
00802             bridge->uniqueid, ast_channel_name(cur->chan));
00803          return -1;
00804       }
00805    }
00806    return 0;
00807 }

static int native_bridge_compatible ( struct ast_bridge bridge  )  [static]

Definition at line 707 of file bridge_native_dahdi.c.

References ast_channel_name(), ast_debug, AST_LIST_TRAVERSE, ast_bridge_channel::chan, ast_bridge::channels, native_bridge_is_capable(), ast_bridge::num_channels, and ast_bridge::uniqueid.

00708 {
00709    struct ast_bridge_channel *cur;
00710 
00711    /* We require two channels before even considering native bridging. */
00712    if (bridge->num_channels != 2) {
00713       ast_debug(1, "Bridge %s: Cannot use native DAHDI.  Must have two channels.\n",
00714          bridge->uniqueid);
00715       return 0;
00716    }
00717 
00718    AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
00719       if (!native_bridge_is_capable(cur)) {
00720          ast_debug(1, "Bridge %s: Cannot use native DAHDI.  Channel '%s' not compatible.\n",
00721             bridge->uniqueid, ast_channel_name(cur->chan));
00722          return 0;
00723       }
00724    }
00725 
00726    return -1;
00727 }

static int native_bridge_create ( struct ast_bridge bridge  )  [static]

Definition at line 100 of file bridge_native_dahdi.c.

References ast_assert, ast_calloc, and ast_bridge::tech_pvt.

00101 {
00102    struct native_pvt_bridge *tech_pvt;
00103 
00104    ast_assert(!bridge->tech_pvt);
00105 
00106    tech_pvt = ast_calloc(1, sizeof(*tech_pvt));
00107    if (!tech_pvt) {
00108       return -1;
00109    }
00110 
00111    bridge->tech_pvt = tech_pvt;
00112    return 0;
00113 }

static void native_bridge_destroy ( struct ast_bridge bridge  )  [static]

Definition at line 122 of file bridge_native_dahdi.c.

References ast_free, NULL, and ast_bridge::tech_pvt.

00123 {
00124    struct native_pvt_bridge *tech_pvt;
00125 
00126    tech_pvt = bridge->tech_pvt;
00127    bridge->tech_pvt = NULL;
00128    ast_free(tech_pvt);
00129 }

static int native_bridge_is_capable ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 645 of file bridge_native_dahdi.c.

References ao2_container_count(), ast_channel_has_audio_frame_or_monitor(), ast_channel_lock, ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), ast_channel_unlock, ast_debug, ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, ast_bridge_channel::chan, ast_bridge_features::dtmf_hooks, ast_bridge_channel::features, dahdi_pvt::lock, dahdi_pvt::sig, and ast_channel_tech::type.

Referenced by native_bridge_compatible().

00646 {
00647    struct ast_channel *chan = bridge_channel->chan;
00648    struct dahdi_pvt *pvt;
00649    int is_capable;
00650 
00651    if (ao2_container_count(bridge_channel->features->dtmf_hooks)) {
00652       ast_debug(2, "Channel '%s' has DTMF hooks.\n", ast_channel_name(chan));
00653       return 0;
00654    }
00655 
00656    ast_channel_lock(chan);
00657 
00658    if (dahdi_tech != ast_channel_tech(chan)) {
00659       ast_debug(2, "Channel '%s' is not %s.\n",
00660          ast_channel_name(chan), dahdi_tech->type);
00661       ast_channel_unlock(chan);
00662       return 0;
00663    }
00664    if (ast_channel_has_audio_frame_or_monitor(chan)) {
00665       ast_debug(2, "Channel '%s' has an active monitor, audiohook, or framehook.\n",
00666          ast_channel_name(chan));
00667       ast_channel_unlock(chan);
00668       return 0;
00669    }
00670    pvt = ast_channel_tech_pvt(chan);
00671    if (!pvt || !pvt->sig) {
00672       /* No private; or signaling is for a pseudo channel. */
00673       ast_channel_unlock(chan);
00674       return 0;
00675    }
00676 
00677    is_capable = 1;
00678    ast_mutex_lock(&pvt->lock);
00679 
00680    if (pvt->callwaiting && pvt->callwaitingcallerid) {
00681       /*
00682        * Call Waiting Caller ID requires DTMF detection to know if it
00683        * can send the CID spill.
00684        */
00685       ast_debug(2, "Channel '%s' has call waiting caller ID enabled.\n",
00686          ast_channel_name(chan));
00687       is_capable = 0;
00688    }
00689 
00690    ast_mutex_unlock(&pvt->lock);
00691    ast_channel_unlock(chan);
00692 
00693    return is_capable;
00694 }

static int native_bridge_join ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 565 of file bridge_native_dahdi.c.

References ast_assert, ast_calloc, ast_channel_make_compatible(), AST_LIST_FIRST, AST_LIST_LAST, ast_bridge::channels, native_request_start(), and ast_bridge_channel::tech_pvt.

00566 {
00567    struct native_pvt_chan *tech_pvt;
00568    struct ast_channel *c0;
00569    struct ast_channel *c1;
00570 
00571    ast_assert(!bridge_channel->tech_pvt);
00572 
00573    tech_pvt = ast_calloc(1, sizeof(*tech_pvt));
00574    if (!tech_pvt) {
00575       return -1;
00576    }
00577 
00578    bridge_channel->tech_pvt = tech_pvt;
00579    native_request_start(bridge);
00580 
00581    /*
00582     * Make the channels compatible in case the native bridge did
00583     * not start for some reason and we need to fallback to 1-1
00584     * bridging.
00585     */
00586    c0 = AST_LIST_FIRST(&bridge->channels)->chan;
00587    c1 = AST_LIST_LAST(&bridge->channels)->chan;
00588    if (c0 == c1) {
00589       return 0;
00590    }
00591    return ast_channel_make_compatible(c0, c1);
00592 }

static void native_bridge_leave ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 601 of file bridge_native_dahdi.c.

References ast_free, native_request_stop(), NULL, and ast_bridge_channel::tech_pvt.

00602 {
00603    struct native_pvt_chan *tech_pvt;
00604 
00605    native_request_stop(bridge);
00606 
00607    tech_pvt = bridge_channel->tech_pvt;
00608    bridge_channel->tech_pvt = NULL;
00609    ast_free(tech_pvt);
00610 }

static int native_bridge_start ( struct ast_bridge bridge  )  [static]

Definition at line 522 of file bridge_native_dahdi.c.

References ast_assert, native_request_start(), NULL, native_pvt_bridge::saw_start, and ast_bridge::tech_pvt.

00523 {
00524    struct native_pvt_bridge *tech_pvt;
00525 
00526    ast_assert(bridge->tech_pvt != NULL);
00527 
00528    tech_pvt = bridge->tech_pvt;
00529    tech_pvt->saw_start = 1;
00530 
00531    native_request_start(bridge);
00532    return 0;
00533 }

static void native_bridge_stop ( struct ast_bridge bridge  )  [static]

Definition at line 542 of file bridge_native_dahdi.c.

References native_request_stop(), native_pvt_bridge::saw_start, and ast_bridge::tech_pvt.

00543 {
00544    struct native_pvt_bridge *tech_pvt;
00545 
00546    tech_pvt = bridge->tech_pvt;
00547    if (!tech_pvt) {
00548       return;
00549    }
00550 
00551    tech_pvt->saw_start = 0;
00552    native_request_stop(bridge);
00553 }

static void native_bridge_suspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 619 of file bridge_native_dahdi.c.

References native_request_stop().

00620 {
00621    native_request_stop(bridge);
00622 }

static void native_bridge_unsuspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 631 of file bridge_native_dahdi.c.

References native_request_start().

00632 {
00633    native_request_start(bridge);
00634 }

static int native_bridge_write ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static]

Definition at line 821 of file bridge_native_dahdi.c.

References ast_assert, ast_bridge_queue_everyone_else(), AST_FRAME_VIDEO, AST_FRAME_VOICE, native_pvt_bridge::connected, ast_frame::frametype, native_bridge_changed(), native_request_start(), native_request_stop(), NULL, and ast_bridge::tech_pvt.

00822 {
00823    struct native_pvt_bridge *tech_pvt;
00824 
00825    /*
00826     * When we are not native bridged by DAHDI, we are like a normal
00827     * 1-1 bridge.
00828     */
00829 
00830    ast_assert(bridge->tech_pvt != NULL);
00831 
00832    /* Recheck native bridging validity. */
00833    tech_pvt = bridge->tech_pvt;
00834    switch (frame->frametype) {
00835    case AST_FRAME_VOICE:
00836    case AST_FRAME_VIDEO:
00837       if (!tech_pvt->connected) {
00838          /* Don't try to start native mode on media frames. */
00839          break;
00840       }
00841       if (native_bridge_changed(bridge)) {
00842          native_request_stop(bridge);
00843          native_request_start(bridge);
00844          if (!tech_pvt->connected) {
00845             break;
00846          }
00847       }
00848 
00849       /*
00850        * Native bridge handles voice frames in hardware.  However, it
00851        * also passes the frames up to Asterisk anyway.  Discard the
00852        * media frames.
00853        */
00854       return 0;
00855    default:
00856       if (!tech_pvt->connected) {
00857          native_request_start(bridge);
00858          break;
00859       }
00860       if (native_bridge_changed(bridge)) {
00861          native_request_stop(bridge);
00862          native_request_start(bridge);
00863       }
00864       break;
00865    }
00866 
00867    return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
00868 }

static int native_chan_changed ( struct ast_bridge_channel bridge_channel  )  [static]

Definition at line 741 of file bridge_native_dahdi.c.

References ast_assert, ast_channel_fd(), ast_channel_lock, ast_channel_tech_pvt(), ast_channel_unlock, ast_bridge_channel::chan, dahdi_get_index, native_pvt_chan::fd0, native_pvt_chan::index, dahdi_subchannel::inthreeway, native_pvt_chan::inthreeway, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, native_pvt_chan::owner, native_pvt_chan::pvt, native_pvt_chan::state, SUB_REAL, dahdi_pvt::subs, and ast_bridge_channel::tech_pvt.

Referenced by native_bridge_changed().

00742 {
00743    struct native_pvt_chan *tech_pvt;
00744    struct ast_channel *chan;
00745    struct dahdi_pvt *pvt;
00746    int idx = -1;
00747 
00748    ast_assert(bridge_channel->tech_pvt != NULL);
00749 
00750    tech_pvt = bridge_channel->tech_pvt;
00751 
00752    chan = bridge_channel->chan;
00753    ast_channel_lock(chan);
00754    pvt = ast_channel_tech_pvt(chan);
00755    if (tech_pvt->pvt == pvt) {
00756       idx = dahdi_get_index(chan, pvt, 1);
00757    }
00758    ast_channel_unlock(chan);
00759 
00760    if (/* Did chan get masqueraded or PRI change associated B channel? */
00761       tech_pvt->pvt != pvt
00762       /* Did the pvt active owner change? */
00763       || tech_pvt->owner != pvt->owner
00764       /* Did the pvt three way call status change? */
00765       || tech_pvt->inthreeway != pvt->subs[SUB_REAL].inthreeway
00766       /* Did the owner index change? */
00767       || tech_pvt->index != idx
00768       /*
00769        * Did chan file descriptor change? (This seems redundant with
00770        * masquerade and active owner change checks.)
00771        */
00772       || tech_pvt->fd0 != ast_channel_fd(chan, 0)
00773       /* Did chan state change? i.e. Did it stop ringing? */
00774       || (pvt->subs[SUB_REAL].owner
00775          && tech_pvt->state > -1
00776          && tech_pvt->state != ast_channel_state(pvt->subs[SUB_REAL].owner))) {
00777       return -1;
00778    }
00779 
00780    return 0;
00781 }

static void native_request_start ( struct ast_bridge bridge  )  [static]

Definition at line 486 of file bridge_native_dahdi.c.

References ast_assert, AST_LIST_TRAVERSE, ast_bridge::channels, native_pvt_bridge::connected, native_start(), NULL, ast_bridge::num_channels, native_pvt_bridge::saw_start, ast_bridge_channel::suspended, ast_bridge_channel::tech_pvt, and ast_bridge::tech_pvt.

Referenced by native_bridge_join(), native_bridge_start(), native_bridge_unsuspend(), and native_bridge_write().

00487 {
00488    struct native_pvt_bridge *tech_pvt;
00489    struct ast_bridge_channel *cur;
00490 
00491    ast_assert(bridge->tech_pvt != NULL);
00492 
00493    tech_pvt = bridge->tech_pvt;
00494 
00495    if (bridge->num_channels != 2 || !tech_pvt->saw_start || tech_pvt->connected) {
00496       return;
00497    }
00498    AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
00499       if (cur->suspended || !cur->tech_pvt) {
00500          return;
00501       }
00502    }
00503 
00504    /* Actually try starting the native bridge. */
00505    if (native_start(bridge)) {
00506       return;
00507    }
00508    tech_pvt->connected = 1;
00509 }

static void native_request_stop ( struct ast_bridge bridge  )  [static]

Definition at line 186 of file bridge_native_dahdi.c.

References ast_assert, native_pvt_bridge::connected, native_stop(), NULL, and ast_bridge::tech_pvt.

Referenced by native_bridge_leave(), native_bridge_stop(), native_bridge_suspend(), and native_bridge_write().

00187 {
00188    struct native_pvt_bridge *tech_pvt;
00189 
00190    ast_assert(bridge->tech_pvt != NULL);
00191 
00192    tech_pvt = bridge->tech_pvt;
00193    if (!tech_pvt->connected) {
00194       return;
00195    }
00196    tech_pvt->connected = 0;
00197 
00198    /* Now to actually stop the bridge. */
00199    native_stop(bridge);
00200 }

static int native_start ( struct ast_bridge bridge  )  [static]

Definition at line 215 of file bridge_native_dahdi.c.

References ast_assert, ast_channel_fd(), ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_trylock, ast_channel_unlock, ast_debug, AST_LIST_FIRST, AST_LIST_LAST, ast_log, ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, AST_STATE_RINGING, call(), ast_bridge_channel::chan, dahdi_pvt::channel, ast_bridge::channels, dahdi_conf_update(), dahdi_dtmf_detect_disable(), dahdi_ec_disable(), dahdi_get_index, dahdi_master_slave_link(), dahdi_sig_pri_lib_handles(), dahdi_subchannel::dfd, dahdi_pvt::echocanbridged, native_pvt_chan::fd0, dahdi_pvt::inconference, native_pvt_chan::index, dahdi_subchannel::inthreeway, native_pvt_chan::inthreeway, dahdi_pvt::lock, LOG_WARNING, native_pvt_bridge::master, dahdi_pvt::master, NULL, dahdi_subchannel::owner, dahdi_pvt::owner, native_pvt_chan::owner, native_pvt_chan::pvt, dahdi_pvt::sig, dahdi_pvt::sig_pvt, native_pvt_bridge::slave, native_pvt_chan::state, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, subnames, dahdi_pvt::subs, ast_bridge_channel::tech_pvt, ast_bridge::tech_pvt, and dahdi_pvt::transfer.

Referenced by native_request_start().

00216 {
00217    struct native_pvt_bridge *tech_pvt;
00218    struct ast_bridge_channel *bc0;
00219    struct ast_bridge_channel *bc1;
00220    struct native_pvt_chan *npc0;
00221    struct native_pvt_chan *npc1;
00222    struct ast_channel *c0;
00223    struct ast_channel *c1;
00224    struct dahdi_pvt *p0;
00225    struct dahdi_pvt *p1;
00226    struct dahdi_pvt *master;
00227    struct dahdi_pvt *slave;
00228    int inconf;
00229    int nothing_ok;
00230 
00231    ast_assert(bridge->tech_pvt != NULL);
00232 
00233    bc0 = AST_LIST_FIRST(&bridge->channels);
00234    bc1 = AST_LIST_LAST(&bridge->channels);
00235    c0 = bc0->chan;
00236    c1 = bc1->chan;
00237 
00238    /* Lock channels and privates */
00239    for (;;) {
00240       ast_channel_lock(c0);
00241       if (!ast_channel_trylock(c1)) {
00242          p0 = ast_channel_tech_pvt(c0);
00243          if (!ast_mutex_trylock(&p0->lock)) {
00244             p1 = ast_channel_tech_pvt(c1);
00245             if (!ast_mutex_trylock(&p1->lock)) {
00246                /* Got all locks */
00247                break;
00248             }
00249             ast_mutex_unlock(&p0->lock);
00250          }
00251          ast_channel_unlock(c1);
00252       }
00253       ast_channel_unlock(c0);
00254       sched_yield();
00255    }
00256 
00257    npc0 = bc0->tech_pvt;
00258    ast_assert(npc0 != NULL);
00259    npc0->pvt = p0;
00260    npc0->owner = p0->owner;
00261    npc0->index = dahdi_get_index(c0, p0, 0);
00262    npc0->fd0 = ast_channel_fd(c0, 0);
00263    npc0->state = -1;
00264    npc0->inthreeway = p0->subs[SUB_REAL].inthreeway;
00265 
00266    npc1 = bc1->tech_pvt;
00267    ast_assert(npc1 != NULL);
00268    npc1->pvt = p1;
00269    npc1->owner = p1->owner;
00270    npc1->index = dahdi_get_index(c1, p1, 0);
00271    npc1->fd0 = ast_channel_fd(c1, 0);
00272    npc1->state = -1;
00273    npc1->inthreeway = p1->subs[SUB_REAL].inthreeway;
00274 
00275    /*
00276     * Check things that can change on the privates while in native
00277     * bridging and cause native to not activate.
00278     */
00279    if (npc0->index < 0 || npc1->index < 0
00280 #if defined(HAVE_PRI)
00281       /*
00282        * PRI nobch channels (hold and call waiting) are equivalent to
00283        * pseudo channels and cannot be nativly bridged.
00284        */
00285       || (dahdi_sig_pri_lib_handles(p0->sig)
00286          && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
00287       || (dahdi_sig_pri_lib_handles(p1->sig)
00288          && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)
00289 #endif   /* defined(HAVE_PRI) */
00290       ) {
00291       ast_mutex_unlock(&p0->lock);
00292       ast_mutex_unlock(&p1->lock);
00293       ast_channel_unlock(c0);
00294       ast_channel_unlock(c1);
00295       return -1;
00296    }
00297 
00298    inconf = 0;
00299    nothing_ok = 1;
00300    master = NULL;
00301    slave = NULL;
00302    if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
00303       if (p0->owner && p1->owner) {
00304          /*
00305           * If we don't have a call-wait in a 3-way, and we aren't in a
00306           * 3-way, we can be master.
00307           */
00308          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
00309             master = p0;
00310             slave = p1;
00311             inconf = 1;
00312          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
00313             master = p1;
00314             slave = p0;
00315             inconf = 1;
00316          } else {
00317             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
00318             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
00319                p0->channel,
00320                npc0->index, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
00321                p0->subs[SUB_REAL].inthreeway,
00322                p0->channel,
00323                npc0->index, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
00324                p1->subs[SUB_REAL].inthreeway);
00325          }
00326          nothing_ok = 0;
00327       }
00328    } else if (npc0->index == SUB_REAL && npc1->index == SUB_THREEWAY) {
00329       if (p1->subs[SUB_THREEWAY].inthreeway) {
00330          master = p1;
00331          slave = p0;
00332          nothing_ok = 0;
00333       }
00334    } else if (npc0->index == SUB_THREEWAY && npc1->index == SUB_REAL) {
00335       if (p0->subs[SUB_THREEWAY].inthreeway) {
00336          master = p0;
00337          slave = p1;
00338          nothing_ok = 0;
00339       }
00340    } else if (npc0->index == SUB_REAL && npc1->index == SUB_CALLWAIT) {
00341       /*
00342        * We have a real and a call wait.  If we're in a three way
00343        * call, put us in it, otherwise, don't put us in anything.
00344        */
00345       if (p1->subs[SUB_CALLWAIT].inthreeway) {
00346          master = p1;
00347          slave = p0;
00348          nothing_ok = 0;
00349       }
00350    } else if (npc0->index == SUB_CALLWAIT && npc1->index == SUB_REAL) {
00351       /* Same as previous */
00352       if (p0->subs[SUB_CALLWAIT].inthreeway) {
00353          master = p0;
00354          slave = p1;
00355          nothing_ok = 0;
00356       }
00357    }
00358    ast_debug(3, "master: %d, slave: %d, nothing_ok: %d\n",
00359       master ? master->channel : 0,
00360       slave ? slave->channel : 0,
00361       nothing_ok);
00362    if (master && slave) {
00363       /*
00364        * Stop any tones, or play ringtone as appropriate.  If they are
00365        * bridged in an active threeway call with a channel that is
00366        * ringing, we should indicate ringing.
00367        */
00368       if (npc1->index == SUB_THREEWAY
00369          && p1->subs[SUB_THREEWAY].inthreeway
00370          && p1->subs[SUB_REAL].owner
00371          && p1->subs[SUB_REAL].inthreeway
00372          && ast_channel_state(p1->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
00373          ast_debug(2,
00374             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
00375             p0->channel, npc0->index, ast_channel_name(c0),
00376             p1->channel, npc1->index, ast_channel_name(c1));
00377          tone_zone_play_tone(p0->subs[npc0->index].dfd, DAHDI_TONE_RINGTONE);
00378          npc1->state = ast_channel_state(p1->subs[SUB_REAL].owner);
00379       } else {
00380          ast_debug(2, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
00381             p0->channel, npc0->index, ast_channel_name(c0),
00382             p1->channel, npc1->index, ast_channel_name(c1));
00383          tone_zone_play_tone(p0->subs[npc0->index].dfd, -1);
00384       }
00385 
00386       if (npc0->index == SUB_THREEWAY
00387          && p0->subs[SUB_THREEWAY].inthreeway
00388          && p0->subs[SUB_REAL].owner
00389          && p0->subs[SUB_REAL].inthreeway
00390          && ast_channel_state(p0->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
00391          ast_debug(2,
00392             "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
00393             p1->channel, npc1->index, ast_channel_name(c1),
00394             p0->channel, npc0->index, ast_channel_name(c0));
00395          tone_zone_play_tone(p1->subs[npc1->index].dfd, DAHDI_TONE_RINGTONE);
00396          npc0->state = ast_channel_state(p0->subs[SUB_REAL].owner);
00397       } else {
00398          ast_debug(2, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
00399             p1->channel, npc1->index, ast_channel_name(c1),
00400             p0->channel, npc0->index, ast_channel_name(c0));
00401          tone_zone_play_tone(p1->subs[npc1->index].dfd, -1);
00402       }
00403 
00404       if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
00405          if (!p0->echocanbridged || !p1->echocanbridged) {
00406             /* Disable echo cancellation if appropriate */
00407             dahdi_ec_disable(p0);
00408             dahdi_ec_disable(p1);
00409          }
00410       }
00411       dahdi_master_slave_link(slave, master);
00412       master->inconference = inconf;
00413    } else if (!nothing_ok) {
00414       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n",
00415          p0->channel, subnames[npc0->index],
00416          p1->channel, subnames[npc1->index]);
00417    }
00418    dahdi_conf_update(p0);
00419    dahdi_conf_update(p1);
00420 
00421    ast_channel_unlock(c0);
00422    ast_channel_unlock(c1);
00423 
00424    /* Native bridge failed */
00425    if ((!master || !slave) && !nothing_ok) {
00426       ast_mutex_unlock(&p0->lock);
00427       ast_mutex_unlock(&p1->lock);
00428       return -1;
00429    }
00430 
00431    if (npc0->index == SUB_REAL) {
00432       dahdi_dtmf_detect_disable(p0);
00433    }
00434    if (npc1->index == SUB_REAL) {
00435       dahdi_dtmf_detect_disable(p1);
00436    }
00437 
00438    ast_mutex_unlock(&p0->lock);
00439    ast_mutex_unlock(&p1->lock);
00440 
00441    tech_pvt = bridge->tech_pvt;
00442    tech_pvt->master = master;
00443    tech_pvt->slave = slave;
00444 
00445    ast_debug(2, "Start native bridging %s and %s\n",
00446       ast_channel_name(c0), ast_channel_name(c1));
00447 
00448 #if defined(HAVE_PRI) && defined(PRI_2BCT)
00449    if (!tech_pvt->tried_trombone_removal) {
00450       tech_pvt->tried_trombone_removal = 1;
00451 
00452       if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
00453          q931_call *q931_c0;
00454          q931_call *q931_c1;
00455 
00456          /* Try to eliminate the tromboned call. */
00457          ast_mutex_lock(&p0->pri->lock);
00458          ast_assert(dahdi_sig_pri_lib_handles(p0->sig));
00459          ast_assert(dahdi_sig_pri_lib_handles(p1->sig));
00460          q931_c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
00461          q931_c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
00462          if (q931_c0 && q931_c1) {
00463             pri_channel_bridge(q931_c0, q931_c1);
00464             ast_debug(2, "Attempt to eliminate tromboned call with %s and %s\n",
00465                ast_channel_name(c0), ast_channel_name(c1));
00466          }
00467          ast_mutex_unlock(&p0->pri->lock);
00468       }
00469    }
00470 #endif   /* defined(HAVE_PRI) && defined(PRI_2BCT) */
00471    return 0;
00472 }

static void native_stop ( struct ast_bridge bridge  )  [static]

Definition at line 142 of file bridge_native_dahdi.c.

References ast_assert, ast_channel_name(), ast_channel_tech_pvt(), ast_debug, AST_LIST_FIRST, AST_LIST_LAST, AST_LIST_TRAVERSE, ast_mutex_lock, ast_mutex_unlock, ast_bridge_channel::chan, ast_bridge::channels, dahdi_dtmf_detect_enable(), dahdi_ec_enable(), dahdi_master_slave_unlink(), native_pvt_chan::index, dahdi_pvt::lock, native_pvt_bridge::master, NULL, native_pvt_chan::pvt, native_pvt_bridge::slave, SUB_REAL, ast_bridge_channel::tech_pvt, and ast_bridge::tech_pvt.

Referenced by native_request_stop().

00143 {
00144    struct native_pvt_bridge *bridge_tech_pvt;
00145    struct ast_bridge_channel *cur;
00146 
00147    ast_assert(bridge->tech_pvt != NULL);
00148 
00149    AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
00150       struct native_pvt_chan *chan_tech_pvt;
00151 
00152       chan_tech_pvt = cur->tech_pvt;
00153       if (!chan_tech_pvt) {
00154          continue;
00155       }
00156 
00157       ast_mutex_lock(&chan_tech_pvt->pvt->lock);
00158       if (chan_tech_pvt->pvt == ast_channel_tech_pvt(cur->chan)) {
00159          dahdi_ec_enable(chan_tech_pvt->pvt);
00160       }
00161       if (chan_tech_pvt->index == SUB_REAL) {
00162          dahdi_dtmf_detect_enable(chan_tech_pvt->pvt);
00163       }
00164       ast_mutex_unlock(&chan_tech_pvt->pvt->lock);
00165    }
00166 
00167    bridge_tech_pvt = bridge->tech_pvt;
00168    dahdi_master_slave_unlink(bridge_tech_pvt->slave, bridge_tech_pvt->master, 1);
00169 
00170    ast_debug(2, "Stop native bridging %s and %s\n",
00171       ast_channel_name(AST_LIST_FIRST(&bridge->channels)->chan),
00172       ast_channel_name(AST_LIST_LAST(&bridge->channels)->chan));
00173 }


Variable Documentation

struct ast_channel_tech* dahdi_tech [static]

Definition at line 51 of file bridge_native_dahdi.c.

Definition at line 870 of file bridge_native_dahdi.c.


Generated on Thu Apr 16 06:29:12 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6