Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
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 (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 const struct ast_channel_techdahdi_tech
 
static struct ast_bridge_technology native_bridge
 

Detailed Description

Native DAHDI bridging support.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

See Also:

Definition in file bridge_native_dahdi.c.

Function Documentation

◆ dahdi_native_load()

int dahdi_native_load ( const struct ast_channel_tech tech)

Definition at line 904 of file bridge_native_dahdi.c.

References ast_bridge_technology_register, and dahdi_native_unload().

Referenced by load_module().

905 {
906  dahdi_tech = tech;
907 
910  return -1;
911  }
912 
913  return 0;
914 }
static const struct ast_channel_tech * dahdi_tech
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()
void dahdi_native_unload(void)
static struct ast_bridge_technology native_bridge

◆ dahdi_native_unload()

void dahdi_native_unload ( void  )

Definition at line 891 of file bridge_native_dahdi.c.

References ast_bridge_technology_unregister().

Referenced by __unload_module(), and dahdi_native_load().

892 {
894 }
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:265
static struct ast_bridge_technology native_bridge

◆ native_bridge_changed()

static int native_bridge_changed ( struct ast_bridge bridge)
static

Definition at line 793 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().

794 {
795  struct ast_bridge_channel *cur;
796 
797  AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
798  if (native_chan_changed(cur)) {
799  ast_debug(1, "Bridge %s: Something changed on channel '%s'.\n",
800  bridge->uniqueid, ast_channel_name(cur->chan));
801  return -1;
802  }
803  }
804  return 0;
805 }
const ast_string_field uniqueid
Definition: bridge.h:409
static int native_chan_changed(struct ast_bridge_channel *bridge_channel)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
const char * ast_channel_name(const struct ast_channel *chan)
Definition: search.h:40

◆ native_bridge_compatible()

static int native_bridge_compatible ( struct ast_bridge bridge)
static

Definition at line 705 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.

706 {
707  struct ast_bridge_channel *cur;
708 
709  /* We require two channels before even considering native bridging. */
710  if (bridge->num_channels != 2) {
711  ast_debug(1, "Bridge %s: Cannot use native DAHDI. Must have two channels.\n",
712  bridge->uniqueid);
713  return 0;
714  }
715 
716  AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
717  if (!native_bridge_is_capable(cur)) {
718  ast_debug(1, "Bridge %s: Cannot use native DAHDI. Channel '%s' not compatible.\n",
719  bridge->uniqueid, ast_channel_name(cur->chan));
720  return 0;
721  }
722  }
723 
724  return -1;
725 }
const ast_string_field uniqueid
Definition: bridge.h:409
static int native_bridge_is_capable(struct ast_bridge_channel *bridge_channel)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
const char * ast_channel_name(const struct ast_channel *chan)
Definition: search.h:40
unsigned int num_channels
Definition: bridge.h:381

◆ native_bridge_create()

static int native_bridge_create ( struct ast_bridge bridge)
static

Definition at line 98 of file bridge_native_dahdi.c.

References ast_assert, ast_calloc, and ast_bridge::tech_pvt.

99 {
100  struct native_pvt_bridge *tech_pvt;
101 
102  ast_assert(!bridge->tech_pvt);
103 
104  tech_pvt = ast_calloc(1, sizeof(*tech_pvt));
105  if (!tech_pvt) {
106  return -1;
107  }
108 
109  bridge->tech_pvt = tech_pvt;
110  return 0;
111 }
#define ast_assert(a)
Definition: utils.h:695
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * tech_pvt
Definition: bridge.h:365

◆ native_bridge_destroy()

static void native_bridge_destroy ( struct ast_bridge bridge)
static

Definition at line 120 of file bridge_native_dahdi.c.

References ast_free, NULL, and ast_bridge::tech_pvt.

121 {
122  struct native_pvt_bridge *tech_pvt;
123 
124  tech_pvt = bridge->tech_pvt;
125  bridge->tech_pvt = NULL;
126  ast_free(tech_pvt);
127 }
#define NULL
Definition: resample.c:96
#define ast_free(a)
Definition: astmm.h:182
void * tech_pvt
Definition: bridge.h:365

◆ native_bridge_is_capable()

static int native_bridge_is_capable ( struct ast_bridge_channel bridge_channel)
static

Definition at line 643 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, native_pvt_chan::pvt, dahdi_pvt::sig, and ast_channel_tech::type.

Referenced by native_bridge_compatible().

644 {
645  struct ast_channel *chan = bridge_channel->chan;
646  struct dahdi_pvt *pvt;
647  int is_capable;
648 
649  if (ao2_container_count(bridge_channel->features->dtmf_hooks)) {
650  ast_debug(2, "Channel '%s' has DTMF hooks.\n", ast_channel_name(chan));
651  return 0;
652  }
653 
654  ast_channel_lock(chan);
655 
656  if (dahdi_tech != ast_channel_tech(chan)) {
657  ast_debug(2, "Channel '%s' is not %s.\n",
659  ast_channel_unlock(chan);
660  return 0;
661  }
663  ast_debug(2, "Channel '%s' has an active monitor, audiohook, or framehook.\n",
664  ast_channel_name(chan));
665  ast_channel_unlock(chan);
666  return 0;
667  }
668  pvt = ast_channel_tech_pvt(chan);
669  if (!pvt || !pvt->sig) {
670  /* No private; or signaling is for a pseudo channel. */
671  ast_channel_unlock(chan);
672  return 0;
673  }
674 
675  is_capable = 1;
676  ast_mutex_lock(&pvt->lock);
677 
678  if (pvt->callwaiting && pvt->callwaitingcallerid) {
679  /*
680  * Call Waiting Caller ID requires DTMF detection to know if it
681  * can send the CID spill.
682  */
683  ast_debug(2, "Channel '%s' has call waiting caller ID enabled.\n",
684  ast_channel_name(chan));
685  is_capable = 0;
686  }
687 
688  ast_mutex_unlock(&pvt->lock);
689  ast_channel_unlock(chan);
690 
691  return is_capable;
692 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
const char *const type
Definition: channel.h:630
unsigned int callwaiting
TRUE if busy extensions will hear the call-waiting tone and can use hook-flash to switch between call...
Definition: chan_dahdi.h:202
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ast_bridge_features * features
void * ast_channel_tech_pvt(const struct ast_channel *chan)
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:207
struct ao2_container * dtmf_hooks
#define ast_mutex_lock(a)
Definition: lock.h:187
static const struct ast_channel_tech * dahdi_tech
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
ast_mutex_t lock
Definition: chan_dahdi.h:125
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_channel * chan
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_has_audio_frame_or_monitor(struct ast_channel *chan)
Check if the channel has active audiohooks, active framehooks, or a monitor.
Definition: channel.c:2523
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ native_bridge_join()

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

Definition at line 563 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(), ast_channel::tech_pvt, and ast_bridge_channel::tech_pvt.

564 {
565  struct native_pvt_chan *tech_pvt;
566  struct ast_channel *c0;
567  struct ast_channel *c1;
568 
569  ast_assert(!bridge_channel->tech_pvt);
570 
571  tech_pvt = ast_calloc(1, sizeof(*tech_pvt));
572  if (!tech_pvt) {
573  return -1;
574  }
575 
576  bridge_channel->tech_pvt = tech_pvt;
577  native_request_start(bridge);
578 
579  /*
580  * Make the channels compatible in case the native bridge did
581  * not start for some reason and we need to fallback to 1-1
582  * bridging.
583  */
584  c0 = AST_LIST_FIRST(&bridge->channels)->chan;
585  c1 = AST_LIST_LAST(&bridge->channels)->chan;
586  if (c0 == c1) {
587  return 0;
588  }
589  return ast_channel_make_compatible(c0, c1);
590 }
Main Channel structure associated with a channel.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define ast_assert(a)
Definition: utils.h:695
static void native_request_start(struct ast_bridge *bridge)
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6817
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void * tech_pvt
Private information unique to the bridge technology.
struct ast_bridge_channels_list channels
Definition: bridge.h:371

◆ native_bridge_leave()

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

Definition at line 599 of file bridge_native_dahdi.c.

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

600 {
601  struct native_pvt_chan *tech_pvt;
602 
603  native_request_stop(bridge);
604 
605  tech_pvt = bridge_channel->tech_pvt;
606  bridge_channel->tech_pvt = NULL;
607  ast_free(tech_pvt);
608 }
#define NULL
Definition: resample.c:96
static void native_request_stop(struct ast_bridge *bridge)
#define ast_free(a)
Definition: astmm.h:182
void * tech_pvt
Private information unique to the bridge technology.

◆ native_bridge_start()

static int native_bridge_start ( struct ast_bridge bridge)
static

Definition at line 520 of file bridge_native_dahdi.c.

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

521 {
522  struct native_pvt_bridge *tech_pvt;
523 
524  ast_assert(bridge->tech_pvt != NULL);
525 
526  tech_pvt = bridge->tech_pvt;
527  tech_pvt->saw_start = 1;
528 
529  native_request_start(bridge);
530  return 0;
531 }
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static void native_request_start(struct ast_bridge *bridge)
void * tech_pvt
Definition: bridge.h:365

◆ native_bridge_stop()

static void native_bridge_stop ( struct ast_bridge bridge)
static

Definition at line 540 of file bridge_native_dahdi.c.

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

541 {
542  struct native_pvt_bridge *tech_pvt;
543 
544  tech_pvt = bridge->tech_pvt;
545  if (!tech_pvt) {
546  return;
547  }
548 
549  tech_pvt->saw_start = 0;
550  native_request_stop(bridge);
551 }
static void native_request_stop(struct ast_bridge *bridge)
void * tech_pvt
Definition: bridge.h:365

◆ native_bridge_suspend()

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

Definition at line 617 of file bridge_native_dahdi.c.

References native_request_stop().

618 {
619  native_request_stop(bridge);
620 }
static void native_request_stop(struct ast_bridge *bridge)

◆ native_bridge_unsuspend()

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

Definition at line 629 of file bridge_native_dahdi.c.

References native_request_start().

630 {
631  native_request_start(bridge);
632 }
static void native_request_start(struct ast_bridge *bridge)

◆ native_bridge_write()

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

Definition at line 819 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.

820 {
821  struct native_pvt_bridge *tech_pvt;
822 
823  /*
824  * When we are not native bridged by DAHDI, we are like a normal
825  * 1-1 bridge.
826  */
827 
828  ast_assert(bridge->tech_pvt != NULL);
829 
830  /* Recheck native bridging validity. */
831  tech_pvt = bridge->tech_pvt;
832  switch (frame->frametype) {
833  case AST_FRAME_VOICE:
834  case AST_FRAME_VIDEO:
835  if (!tech_pvt->connected) {
836  /* Don't try to start native mode on media frames. */
837  break;
838  }
839  if (native_bridge_changed(bridge)) {
840  native_request_stop(bridge);
841  native_request_start(bridge);
842  if (!tech_pvt->connected) {
843  break;
844  }
845  }
846 
847  /*
848  * Native bridge handles voice frames in hardware. However, it
849  * also passes the frames up to Asterisk anyway. Discard the
850  * media frames.
851  */
852  return 0;
853  default:
854  if (!tech_pvt->connected) {
855  native_request_start(bridge);
856  break;
857  }
858  if (native_bridge_changed(bridge)) {
859  native_request_stop(bridge);
860  native_request_start(bridge);
861  }
862  break;
863  }
864 
865  return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
866 }
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Queue the given frame to everyone else.
static void native_request_start(struct ast_bridge *bridge)
static int native_bridge_changed(struct ast_bridge *bridge)
static void native_request_stop(struct ast_bridge *bridge)
void * tech_pvt
Definition: bridge.h:365
enum ast_frame_type frametype

◆ native_chan_changed()

static int native_chan_changed ( struct ast_bridge_channel bridge_channel)
static

Definition at line 739 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, native_pvt_chan::inthreeway, dahdi_subchannel::inthreeway, NULL, native_pvt_chan::owner, dahdi_subchannel::owner, dahdi_pvt::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().

740 {
741  struct native_pvt_chan *tech_pvt;
742  struct ast_channel *chan;
743  struct dahdi_pvt *pvt;
744  int idx = -1;
745 
746  ast_assert(bridge_channel->tech_pvt != NULL);
747 
748  tech_pvt = bridge_channel->tech_pvt;
749 
750  chan = bridge_channel->chan;
751  ast_channel_lock(chan);
752  pvt = ast_channel_tech_pvt(chan);
753  if (tech_pvt->pvt == pvt) {
754  idx = dahdi_get_index(chan, pvt, 1);
755  }
756  ast_channel_unlock(chan);
757 
758  if (/* Did chan get masqueraded or PRI change associated B channel? */
759  tech_pvt->pvt != pvt
760  /* Did the pvt active owner change? */
761  || tech_pvt->owner != pvt->owner
762  /* Did the pvt three way call status change? */
763  || tech_pvt->inthreeway != pvt->subs[SUB_REAL].inthreeway
764  /* Did the owner index change? */
765  || tech_pvt->index != idx
766  /*
767  * Did chan file descriptor change? (This seems redundant with
768  * masquerade and active owner change checks.)
769  */
770  || tech_pvt->fd0 != ast_channel_fd(chan, 0)
771  /* Did chan state change? i.e. Did it stop ringing? */
772  || (pvt->subs[SUB_REAL].owner
773  && tech_pvt->state > -1
774  && tech_pvt->state != ast_channel_state(pvt->subs[SUB_REAL].owner))) {
775  return -1;
776  }
777 
778  return 0;
779 }
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:827
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_channel * owner
Definition: chan_dahdi.h:127
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
struct ast_channel * owner
Definition: chan_dahdi.h:79
unsigned int inthreeway
unsigned int inthreeway
Definition: chan_dahdi.h:91
#define SUB_REAL
Definition: chan_dahdi.h:57
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * tech_pvt
Private information unique to the bridge technology.
int ast_channel_fd(const struct ast_channel *chan, int which)
struct ast_channel * chan
struct dahdi_pvt * pvt
struct ast_channel * owner

◆ native_request_start()

static void native_request_start ( struct ast_bridge bridge)
static

Definition at line 484 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().

485 {
486  struct native_pvt_bridge *tech_pvt;
487  struct ast_bridge_channel *cur;
488 
489  ast_assert(bridge->tech_pvt != NULL);
490 
491  tech_pvt = bridge->tech_pvt;
492 
493  if (bridge->num_channels != 2 || !tech_pvt->saw_start || tech_pvt->connected) {
494  return;
495  }
496  AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
497  if (cur->suspended || !cur->tech_pvt) {
498  return;
499  }
500  }
501 
502  /* Actually try starting the native bridge. */
503  if (native_start(bridge)) {
504  return;
505  }
506  tech_pvt->connected = 1;
507 }
static int native_start(struct ast_bridge *bridge)
unsigned int suspended
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void * tech_pvt
Private information unique to the bridge technology.
struct ast_bridge_channels_list channels
Definition: bridge.h:371
Structure that contains information regarding a channel in a bridge.
void * tech_pvt
Definition: bridge.h:365
Definition: search.h:40
unsigned int num_channels
Definition: bridge.h:381

◆ native_request_stop()

static void native_request_stop ( struct ast_bridge bridge)
static

Definition at line 184 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().

185 {
186  struct native_pvt_bridge *tech_pvt;
187 
188  ast_assert(bridge->tech_pvt != NULL);
189 
190  tech_pvt = bridge->tech_pvt;
191  if (!tech_pvt->connected) {
192  return;
193  }
194  tech_pvt->connected = 0;
195 
196  /* Now to actually stop the bridge. */
197  native_stop(bridge);
198 }
static void native_stop(struct ast_bridge *bridge)
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
void * tech_pvt
Definition: bridge.h:365

◆ native_start()

static int native_start ( struct ast_bridge bridge)
static

Definition at line 213 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, native_pvt_chan::inthreeway, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_WARNING, native_pvt_bridge::master, dahdi_pvt::master, NULL, native_pvt_chan::owner, dahdi_subchannel::owner, dahdi_pvt::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().

214 {
215  struct native_pvt_bridge *tech_pvt;
216  struct ast_bridge_channel *bc0;
217  struct ast_bridge_channel *bc1;
218  struct native_pvt_chan *npc0;
219  struct native_pvt_chan *npc1;
220  struct ast_channel *c0;
221  struct ast_channel *c1;
222  struct dahdi_pvt *p0;
223  struct dahdi_pvt *p1;
224  struct dahdi_pvt *master;
225  struct dahdi_pvt *slave;
226  int inconf;
227  int nothing_ok;
228 
229  ast_assert(bridge->tech_pvt != NULL);
230 
231  bc0 = AST_LIST_FIRST(&bridge->channels);
232  bc1 = AST_LIST_LAST(&bridge->channels);
233  c0 = bc0->chan;
234  c1 = bc1->chan;
235 
236  /* Lock channels and privates */
237  for (;;) {
238  ast_channel_lock(c0);
239  if (!ast_channel_trylock(c1)) {
240  p0 = ast_channel_tech_pvt(c0);
241  if (!ast_mutex_trylock(&p0->lock)) {
242  p1 = ast_channel_tech_pvt(c1);
243  if (!ast_mutex_trylock(&p1->lock)) {
244  /* Got all locks */
245  break;
246  }
247  ast_mutex_unlock(&p0->lock);
248  }
249  ast_channel_unlock(c1);
250  }
251  ast_channel_unlock(c0);
252  sched_yield();
253  }
254 
255  npc0 = bc0->tech_pvt;
256  ast_assert(npc0 != NULL);
257  npc0->pvt = p0;
258  npc0->owner = p0->owner;
259  npc0->index = dahdi_get_index(c0, p0, 0);
260  npc0->fd0 = ast_channel_fd(c0, 0);
261  npc0->state = -1;
262  npc0->inthreeway = p0->subs[SUB_REAL].inthreeway;
263 
264  npc1 = bc1->tech_pvt;
265  ast_assert(npc1 != NULL);
266  npc1->pvt = p1;
267  npc1->owner = p1->owner;
268  npc1->index = dahdi_get_index(c1, p1, 0);
269  npc1->fd0 = ast_channel_fd(c1, 0);
270  npc1->state = -1;
271  npc1->inthreeway = p1->subs[SUB_REAL].inthreeway;
272 
273  /*
274  * Check things that can change on the privates while in native
275  * bridging and cause native to not activate.
276  */
277  if (npc0->index < 0 || npc1->index < 0
278 #if defined(HAVE_PRI)
279  /*
280  * PRI nobch channels (hold and call waiting) are equivalent to
281  * pseudo channels and cannot be nativly bridged.
282  */
284  && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
286  && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)
287 #endif /* defined(HAVE_PRI) */
288  ) {
289  ast_mutex_unlock(&p0->lock);
290  ast_mutex_unlock(&p1->lock);
291  ast_channel_unlock(c0);
292  ast_channel_unlock(c1);
293  return -1;
294  }
295 
296  inconf = 0;
297  nothing_ok = 1;
298  master = NULL;
299  slave = NULL;
300  if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
301  if (p0->owner && p1->owner) {
302  /*
303  * If we don't have a call-wait in a 3-way, and we aren't in a
304  * 3-way, we can be master.
305  */
306  if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
307  master = p0;
308  slave = p1;
309  inconf = 1;
310  } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
311  master = p1;
312  slave = p0;
313  inconf = 1;
314  } else {
315  ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
316  ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
317  p0->channel,
318  npc0->index, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
319  p0->subs[SUB_REAL].inthreeway,
320  p0->channel,
321  npc0->index, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
322  p1->subs[SUB_REAL].inthreeway);
323  }
324  nothing_ok = 0;
325  }
326  } else if (npc0->index == SUB_REAL && npc1->index == SUB_THREEWAY) {
327  if (p1->subs[SUB_THREEWAY].inthreeway) {
328  master = p1;
329  slave = p0;
330  nothing_ok = 0;
331  }
332  } else if (npc0->index == SUB_THREEWAY && npc1->index == SUB_REAL) {
333  if (p0->subs[SUB_THREEWAY].inthreeway) {
334  master = p0;
335  slave = p1;
336  nothing_ok = 0;
337  }
338  } else if (npc0->index == SUB_REAL && npc1->index == SUB_CALLWAIT) {
339  /*
340  * We have a real and a call wait. If we're in a three way
341  * call, put us in it, otherwise, don't put us in anything.
342  */
343  if (p1->subs[SUB_CALLWAIT].inthreeway) {
344  master = p1;
345  slave = p0;
346  nothing_ok = 0;
347  }
348  } else if (npc0->index == SUB_CALLWAIT && npc1->index == SUB_REAL) {
349  /* Same as previous */
350  if (p0->subs[SUB_CALLWAIT].inthreeway) {
351  master = p0;
352  slave = p1;
353  nothing_ok = 0;
354  }
355  }
356  ast_debug(3, "master: %d, slave: %d, nothing_ok: %d\n",
357  master ? master->channel : 0,
358  slave ? slave->channel : 0,
359  nothing_ok);
360  if (master && slave) {
361  /*
362  * Stop any tones, or play ringtone as appropriate. If they are
363  * bridged in an active threeway call with a channel that is
364  * ringing, we should indicate ringing.
365  */
366  if (npc1->index == SUB_THREEWAY
368  && p1->subs[SUB_REAL].owner
369  && p1->subs[SUB_REAL].inthreeway
371  ast_debug(2,
372  "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
373  p0->channel, npc0->index, ast_channel_name(c0),
374  p1->channel, npc1->index, ast_channel_name(c1));
375  tone_zone_play_tone(p0->subs[npc0->index].dfd, DAHDI_TONE_RINGTONE);
376  npc1->state = ast_channel_state(p1->subs[SUB_REAL].owner);
377  } else {
378  ast_debug(2, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
379  p0->channel, npc0->index, ast_channel_name(c0),
380  p1->channel, npc1->index, ast_channel_name(c1));
381  tone_zone_play_tone(p0->subs[npc0->index].dfd, -1);
382  }
383 
384  if (npc0->index == SUB_THREEWAY
386  && p0->subs[SUB_REAL].owner
387  && p0->subs[SUB_REAL].inthreeway
389  ast_debug(2,
390  "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
391  p1->channel, npc1->index, ast_channel_name(c1),
392  p0->channel, npc0->index, ast_channel_name(c0));
393  tone_zone_play_tone(p1->subs[npc1->index].dfd, DAHDI_TONE_RINGTONE);
394  npc0->state = ast_channel_state(p0->subs[SUB_REAL].owner);
395  } else {
396  ast_debug(2, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
397  p1->channel, npc1->index, ast_channel_name(c1),
398  p0->channel, npc0->index, ast_channel_name(c0));
399  tone_zone_play_tone(p1->subs[npc1->index].dfd, -1);
400  }
401 
402  if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
403  if (!p0->echocanbridged || !p1->echocanbridged) {
404  /* Disable echo cancellation if appropriate */
405  dahdi_ec_disable(p0);
406  dahdi_ec_disable(p1);
407  }
408  }
409  dahdi_master_slave_link(slave, master);
410  master->inconference = inconf;
411  } else if (!nothing_ok) {
412  ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n",
413  p0->channel, subnames[npc0->index],
414  p1->channel, subnames[npc1->index]);
415  }
416  dahdi_conf_update(p0);
417  dahdi_conf_update(p1);
418 
419  ast_channel_unlock(c0);
420  ast_channel_unlock(c1);
421 
422  /* Native bridge failed */
423  if ((!master || !slave) && !nothing_ok) {
424  ast_mutex_unlock(&p0->lock);
425  ast_mutex_unlock(&p1->lock);
426  return -1;
427  }
428 
429  if (npc0->index == SUB_REAL) {
431  }
432  if (npc1->index == SUB_REAL) {
434  }
435 
436  ast_mutex_unlock(&p0->lock);
437  ast_mutex_unlock(&p1->lock);
438 
439  tech_pvt = bridge->tech_pvt;
440  tech_pvt->master = master;
441  tech_pvt->slave = slave;
442 
443  ast_debug(2, "Start native bridging %s and %s\n",
445 
446 #if defined(HAVE_PRI) && defined(PRI_2BCT)
447  if (!tech_pvt->tried_trombone_removal) {
448  tech_pvt->tried_trombone_removal = 1;
449 
450  if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
451  q931_call *q931_c0;
452  q931_call *q931_c1;
453 
454  /* Try to eliminate the tromboned call. */
455  ast_mutex_lock(&p0->pri->lock);
458  q931_c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
459  q931_c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
460  if (q931_c0 && q931_c1) {
461  pri_channel_bridge(q931_c0, q931_c1);
462  ast_debug(2, "Attempt to eliminate tromboned call with %s and %s\n",
464  }
465  ast_mutex_unlock(&p0->pri->lock);
466  }
467  }
468 #endif /* defined(HAVE_PRI) && defined(PRI_2BCT) */
469  return 0;
470 }
#define dahdi_get_index(ast, p, nullok)
Definition: chan_dahdi.h:827
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6473
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:770
struct dahdi_subchannel subs[3]
Definition: chan_dahdi.h:131
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
#define LOG_WARNING
Definition: logger.h:274
struct ast_channel * owner
Definition: chan_dahdi.h:127
ast_channel_state
ast_channel states
Definition: channelstate.h:35
void * sig_pvt
Definition: chan_dahdi.h:709
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4710
#define ast_assert(a)
Definition: utils.h:695
#define ast_mutex_lock(a)
Definition: lock.h:187
static int call(void *data)
Definition: chan_pjsip.c:2358
#define NULL
Definition: resample.c:96
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4583
int inconference
Definition: chan_dahdi.h:136
const char *const subnames[]
Definition: chan_dahdi.c:795
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:339
#define ast_mutex_trylock(a)
Definition: lock.h:189
ast_mutex_t lock
Definition: chan_dahdi.h:125
struct ast_channel * owner
Definition: chan_dahdi.h:79
unsigned int inthreeway
unsigned int inthreeway
Definition: chan_dahdi.h:91
#define SUB_REAL
Definition: chan_dahdi.h:57
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct dahdi_pvt * master
void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
Definition: chan_dahdi.c:7037
void * tech_pvt
Private information unique to the bridge technology.
int ast_channel_fd(const struct ast_channel *chan, int which)
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct ast_channel * chan
struct dahdi_pvt * slave
Structure that contains information regarding a channel in a bridge.
const char * ast_channel_name(const struct ast_channel *chan)
void * tech_pvt
Definition: bridge.h:365
struct dahdi_pvt * pvt
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:246
#define ast_channel_trylock(chan)
Definition: channel.h:2947
struct ast_channel * owner
int channel
Definition: chan_dahdi.h:538
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58

◆ native_stop()

static void native_stop ( struct ast_bridge bridge)
static

Definition at line 140 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().

141 {
142  struct native_pvt_bridge *bridge_tech_pvt;
143  struct ast_bridge_channel *cur;
144 
145  ast_assert(bridge->tech_pvt != NULL);
146 
147  AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
148  struct native_pvt_chan *chan_tech_pvt;
149 
150  chan_tech_pvt = cur->tech_pvt;
151  if (!chan_tech_pvt) {
152  continue;
153  }
154 
155  ast_mutex_lock(&chan_tech_pvt->pvt->lock);
156  if (chan_tech_pvt->pvt == ast_channel_tech_pvt(cur->chan)) {
157  dahdi_ec_enable(chan_tech_pvt->pvt);
158  }
159  if (chan_tech_pvt->index == SUB_REAL) {
160  dahdi_dtmf_detect_enable(chan_tech_pvt->pvt);
161  }
162  ast_mutex_unlock(&chan_tech_pvt->pvt->lock);
163  }
164 
165  bridge_tech_pvt = bridge->tech_pvt;
166  dahdi_master_slave_unlink(bridge_tech_pvt->slave, bridge_tech_pvt->master, 1);
167 
168  ast_debug(2, "Stop native bridging %s and %s\n",
169  ast_channel_name(AST_LIST_FIRST(&bridge->channels)->chan),
170  ast_channel_name(AST_LIST_LAST(&bridge->channels)->chan));
171 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:6981
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4638
#define ast_assert(a)
Definition: utils.h:695
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
ast_mutex_t lock
Definition: chan_dahdi.h:125
#define SUB_REAL
Definition: chan_dahdi.h:57
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct dahdi_pvt * master
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6487
void * tech_pvt
Private information unique to the bridge technology.
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct ast_channel * chan
struct dahdi_pvt * slave
Structure that contains information regarding a channel in a bridge.
const char * ast_channel_name(const struct ast_channel *chan)
void * tech_pvt
Definition: bridge.h:365
Definition: search.h:40
struct dahdi_pvt * pvt
#define ast_mutex_unlock(a)
Definition: lock.h:188

Variable Documentation

◆ dahdi_tech

const struct ast_channel_tech* dahdi_tech
static

Definition at line 49 of file bridge_native_dahdi.c.

◆ native_bridge

struct ast_bridge_technology native_bridge
static

Definition at line 868 of file bridge_native_dahdi.c.