Asterisk - The Open Source Telephony Project GIT-master-f36a736
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 896 of file bridge_native_dahdi.c.

897{
898 dahdi_tech = tech;
899
902 return -1;
903 }
904
905 return 0;
906}
static const struct ast_channel_tech * dahdi_tech
void dahdi_native_unload(void)
static struct ast_bridge_technology native_bridge
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()

References ast_bridge_technology_register, dahdi_native_unload(), dahdi_tech, and native_bridge.

Referenced by load_module().

◆ dahdi_native_unload()

void dahdi_native_unload ( void  )

Definition at line 883 of file bridge_native_dahdi.c.

884{
886}
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:263

References ast_bridge_technology_unregister(), and native_bridge.

Referenced by __unload_module(), and dahdi_native_load().

◆ native_bridge_changed()

static int native_bridge_changed ( struct ast_bridge bridge)
static

Definition at line 787 of file bridge_native_dahdi.c.

788{
789 struct ast_bridge_channel *cur;
790
792 if (native_chan_changed(cur)) {
793 ast_debug(1, "Bridge %s: Something changed on channel '%s'.\n",
795 return -1;
796 }
797 }
798 return 0;
799}
static int native_chan_changed(struct ast_bridge_channel *bridge_channel)
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
Structure that contains information regarding a channel in a bridge.
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_channel * chan
const ast_string_field uniqueid
Definition: bridge.h:401
struct ast_bridge_channels_list channels
Definition: bridge.h:363
Definition: search.h:40

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

Referenced by native_bridge_write().

◆ native_bridge_compatible()

static int native_bridge_compatible ( struct ast_bridge bridge)
static

Definition at line 699 of file bridge_native_dahdi.c.

700{
701 struct ast_bridge_channel *cur;
702
703 /* We require two channels before even considering native bridging. */
704 if (bridge->num_channels != 2) {
705 ast_debug(1, "Bridge %s: Cannot use native DAHDI. Must have two channels.\n",
707 return 0;
708 }
709
711 if (!native_bridge_is_capable(cur)) {
712 ast_debug(1, "Bridge %s: Cannot use native DAHDI. Channel '%s' not compatible.\n",
714 return 0;
715 }
716 }
717
718 return -1;
719}
static int native_bridge_is_capable(struct ast_bridge_channel *bridge_channel)
unsigned int num_channels
Definition: bridge.h:373

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

◆ native_bridge_create()

static int native_bridge_create ( struct ast_bridge bridge)
static

Definition at line 98 of file bridge_native_dahdi.c.

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_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
void * tech_pvt
Definition: bridge.h:357
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_calloc, and ast_bridge::tech_pvt.

◆ native_bridge_destroy()

static void native_bridge_destroy ( struct ast_bridge bridge)
static

Definition at line 120 of file bridge_native_dahdi.c.

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 ast_free(a)
Definition: astmm.h:180
#define NULL
Definition: resample.c:96

References ast_free, NULL, and ast_bridge::tech_pvt.

◆ native_bridge_is_capable()

static int native_bridge_is_capable ( struct ast_bridge_channel bridge_channel)
static

Definition at line 637 of file bridge_native_dahdi.c.

638{
639 struct ast_channel *chan = bridge_channel->chan;
640 struct dahdi_pvt *pvt;
641 int is_capable;
642
643 if (ao2_container_count(bridge_channel->features->dtmf_hooks)) {
644 ast_debug(2, "Channel '%s' has DTMF hooks.\n", ast_channel_name(chan));
645 return 0;
646 }
647
648 ast_channel_lock(chan);
649
650 if (dahdi_tech != ast_channel_tech(chan)) {
651 ast_debug(2, "Channel '%s' is not %s.\n",
653 ast_channel_unlock(chan);
654 return 0;
655 }
657 ast_debug(2, "Channel '%s' has an active monitor, audiohook, or framehook.\n",
658 ast_channel_name(chan));
659 ast_channel_unlock(chan);
660 return 0;
661 }
662 pvt = ast_channel_tech_pvt(chan);
663 if (!pvt || !pvt->sig) {
664 /* No private; or signaling is for a pseudo channel. */
665 ast_channel_unlock(chan);
666 return 0;
667 }
668
669 is_capable = 1;
670 ast_mutex_lock(&pvt->lock);
671
672 if (pvt->callwaiting && pvt->callwaitingcallerid) {
673 /*
674 * Call Waiting Caller ID requires DTMF detection to know if it
675 * can send the CID spill.
676 */
677 ast_debug(2, "Channel '%s' has call waiting caller ID enabled.\n",
678 ast_channel_name(chan));
679 is_capable = 0;
680 }
681
682 ast_mutex_unlock(&pvt->lock);
683 ast_channel_unlock(chan);
684
685 return is_capable;
686}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2968
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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:2537
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
struct ast_bridge_features * features
struct ao2_container * dtmf_hooks
const char *const type
Definition: channel.h:649
Main Channel structure associated with a channel.
struct ast_bridge_channel * bridge_channel
unsigned int callwaitingcallerid
TRUE if send caller ID for Call Waiting.
Definition: chan_dahdi.h:231
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:226
ast_mutex_t lock
Definition: chan_dahdi.h:125

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, ast_channel::bridge_channel, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, ast_bridge_channel::chan, dahdi_tech, 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().

◆ native_bridge_join()

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

Definition at line 557 of file bridge_native_dahdi.c.

558{
559 struct native_pvt_chan *tech_pvt;
560 struct ast_channel *c0;
561 struct ast_channel *c1;
562
564
565 tech_pvt = ast_calloc(1, sizeof(*tech_pvt));
566 if (!tech_pvt) {
567 return -1;
568 }
569
572
573 /*
574 * Make the channels compatible in case the native bridge did
575 * not start for some reason and we need to fallback to 1-1
576 * bridging.
577 */
578 c0 = AST_LIST_FIRST(&bridge->channels)->chan;
579 c1 = AST_LIST_LAST(&bridge->channels)->chan;
580 if (c0 == c1) {
581 return 0;
582 }
583 return ast_channel_make_compatible(c0, c1);
584}
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:6739
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
void * tech_pvt
Private information unique to the bridge technology.
struct ast_bridge * bridge

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

◆ native_bridge_leave()

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

Definition at line 593 of file bridge_native_dahdi.c.

594{
595 struct native_pvt_chan *tech_pvt;
596
597 native_request_stop(bridge);
598
599 tech_pvt = bridge_channel->tech_pvt;
600 bridge_channel->tech_pvt = NULL;
601 ast_free(tech_pvt);
602}
static void native_request_stop(struct ast_bridge *bridge)

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

◆ native_bridge_start()

static int native_bridge_start ( struct ast_bridge bridge)
static

Definition at line 514 of file bridge_native_dahdi.c.

515{
516 struct native_pvt_bridge *tech_pvt;
517
518 ast_assert(bridge->tech_pvt != NULL);
519
520 tech_pvt = bridge->tech_pvt;
521 tech_pvt->saw_start = 1;
522
523 native_request_start(bridge);
524 return 0;
525}

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

◆ native_bridge_stop()

static void native_bridge_stop ( struct ast_bridge bridge)
static

Definition at line 534 of file bridge_native_dahdi.c.

535{
536 struct native_pvt_bridge *tech_pvt;
537
538 tech_pvt = bridge->tech_pvt;
539 if (!tech_pvt) {
540 return;
541 }
542
543 tech_pvt->saw_start = 0;
544 native_request_stop(bridge);
545}

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

◆ native_bridge_suspend()

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

Definition at line 611 of file bridge_native_dahdi.c.

612{
613 native_request_stop(bridge);
614}

References native_request_stop().

◆ native_bridge_unsuspend()

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

Definition at line 623 of file bridge_native_dahdi.c.

624{
625 native_request_start(bridge);
626}

References native_request_start().

◆ 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 813 of file bridge_native_dahdi.c.

814{
815 struct native_pvt_bridge *tech_pvt;
816
817 /*
818 * When we are not native bridged by DAHDI, we are like a normal
819 * 1-1 bridge.
820 */
821
822 ast_assert(bridge->tech_pvt != NULL);
823
824 /* Recheck native bridging validity. */
825 tech_pvt = bridge->tech_pvt;
826 switch (frame->frametype) {
827 case AST_FRAME_VOICE:
828 case AST_FRAME_VIDEO:
829 if (!tech_pvt->connected) {
830 /* Don't try to start native mode on media frames. */
831 break;
832 }
833 if (native_bridge_changed(bridge)) {
834 native_request_stop(bridge);
835 native_request_start(bridge);
836 if (!tech_pvt->connected) {
837 break;
838 }
839 }
840
841 /*
842 * Native bridge handles voice frames in hardware. However, it
843 * also passes the frames up to Asterisk anyway. Discard the
844 * media frames.
845 */
846 return 0;
847 default:
848 if (!tech_pvt->connected) {
849 native_request_start(bridge);
850 break;
851 }
852 if (native_bridge_changed(bridge)) {
853 native_request_stop(bridge);
854 native_request_start(bridge);
855 }
856 break;
857 }
858
859 return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
860}
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 int native_bridge_changed(struct ast_bridge *bridge)
@ AST_FRAME_VIDEO
@ AST_FRAME_VOICE
enum ast_frame_type frametype

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.

◆ native_chan_changed()

static int native_chan_changed ( struct ast_bridge_channel bridge_channel)
static

Definition at line 733 of file bridge_native_dahdi.c.

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

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().

◆ native_request_start()

static void native_request_start ( struct ast_bridge bridge)
static

Definition at line 478 of file bridge_native_dahdi.c.

479{
480 struct native_pvt_bridge *tech_pvt;
481 struct ast_bridge_channel *cur;
482
484
486
487 if (bridge->num_channels != 2 || !tech_pvt->saw_start || tech_pvt->connected) {
488 return;
489 }
491 if (cur->suspended || !cur->tech_pvt) {
492 return;
493 }
494 }
495
496 /* Actually try starting the native bridge. */
497 if (native_start(bridge)) {
498 return;
499 }
500 tech_pvt->connected = 1;
501}
static int native_start(struct ast_bridge *bridge)
unsigned int suspended

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

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

◆ native_request_stop()

static void native_request_stop ( struct ast_bridge bridge)
static

Definition at line 180 of file bridge_native_dahdi.c.

181{
182 struct native_pvt_bridge *tech_pvt;
183
184 ast_assert(bridge->tech_pvt != NULL);
185
186 tech_pvt = bridge->tech_pvt;
187 if (!tech_pvt->connected) {
188 return;
189 }
190 tech_pvt->connected = 0;
191
192 /* Now to actually stop the bridge. */
193 native_stop(bridge);
194}
static void native_stop(struct ast_bridge *bridge)

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().

◆ native_start()

static int native_start ( struct ast_bridge bridge)
static

Definition at line 209 of file bridge_native_dahdi.c.

210{
211 struct native_pvt_bridge *tech_pvt;
212 struct ast_bridge_channel *bc0;
213 struct ast_bridge_channel *bc1;
214 struct native_pvt_chan *npc0;
215 struct native_pvt_chan *npc1;
216 struct ast_channel *c0;
217 struct ast_channel *c1;
218 struct dahdi_pvt *p0;
219 struct dahdi_pvt *p1;
220 struct dahdi_pvt *master;
221 struct dahdi_pvt *slave;
222 int inconf;
223 int nothing_ok;
224
225 ast_assert(bridge->tech_pvt != NULL);
226
227 bc0 = AST_LIST_FIRST(&bridge->channels);
228 bc1 = AST_LIST_LAST(&bridge->channels);
229 c0 = bc0->chan;
230 c1 = bc1->chan;
231
232 /* Lock channels and privates */
233 for (;;) {
235 if (!ast_channel_trylock(c1)) {
236 p0 = ast_channel_tech_pvt(c0);
237 if (!ast_mutex_trylock(&p0->lock)) {
238 p1 = ast_channel_tech_pvt(c1);
239 if (!ast_mutex_trylock(&p1->lock)) {
240 /* Got all locks */
241 break;
242 }
244 }
246 }
248 sched_yield();
249 }
250
251 npc0 = bc0->tech_pvt;
252 ast_assert(npc0 != NULL);
253 npc0->pvt = p0;
254 npc0->owner = p0->owner;
255 npc0->index = dahdi_get_index(c0, p0, 0);
256 npc0->fd0 = ast_channel_fd(c0, 0);
257 npc0->state = -1;
258 npc0->inthreeway = p0->subs[SUB_REAL].inthreeway;
259
260 npc1 = bc1->tech_pvt;
261 ast_assert(npc1 != NULL);
262 npc1->pvt = p1;
263 npc1->owner = p1->owner;
264 npc1->index = dahdi_get_index(c1, p1, 0);
265 npc1->fd0 = ast_channel_fd(c1, 0);
266 npc1->state = -1;
267 npc1->inthreeway = p1->subs[SUB_REAL].inthreeway;
268
269 /*
270 * Check things that can change on the privates while in native
271 * bridging and cause native to not activate.
272 */
273 if (npc0->index < 0 || npc1->index < 0
274#if defined(HAVE_PRI)
275 /*
276 * PRI nobch channels (hold and call waiting) are equivalent to
277 * pseudo channels and cannot be natively bridged.
278 */
280 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
282 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)
283#endif /* defined(HAVE_PRI) */
284 ) {
289 return -1;
290 }
291
292 inconf = 0;
293 nothing_ok = 1;
294 master = NULL;
295 slave = NULL;
296 if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
297 if (p0->owner && p1->owner) {
298 /*
299 * If we don't have a call-wait in a 3-way, and we aren't in a
300 * 3-way, we can be master.
301 */
302 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
303 master = p0;
304 slave = p1;
305 inconf = 1;
306 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
307 master = p1;
308 slave = p0;
309 inconf = 1;
310 } else {
311 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
312 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
313 p0->channel,
314 npc0->index, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
316 p0->channel,
317 npc0->index, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
319 }
320 nothing_ok = 0;
321 }
322 } else if (npc0->index == SUB_REAL && npc1->index == SUB_THREEWAY) {
323 if (p1->subs[SUB_THREEWAY].inthreeway) {
324 master = p1;
325 slave = p0;
326 nothing_ok = 0;
327 }
328 } else if (npc0->index == SUB_THREEWAY && npc1->index == SUB_REAL) {
329 if (p0->subs[SUB_THREEWAY].inthreeway) {
330 master = p0;
331 slave = p1;
332 nothing_ok = 0;
333 }
334 } else if (npc0->index == SUB_REAL && npc1->index == SUB_CALLWAIT) {
335 /*
336 * We have a real and a call wait. If we're in a three way
337 * call, put us in it, otherwise, don't put us in anything.
338 */
339 if (p1->subs[SUB_CALLWAIT].inthreeway) {
340 master = p1;
341 slave = p0;
342 nothing_ok = 0;
343 }
344 } else if (npc0->index == SUB_CALLWAIT && npc1->index == SUB_REAL) {
345 /* Same as previous */
346 if (p0->subs[SUB_CALLWAIT].inthreeway) {
347 master = p0;
348 slave = p1;
349 nothing_ok = 0;
350 }
351 }
352 ast_debug(3, "master: %d, slave: %d, nothing_ok: %d\n",
353 master ? master->channel : 0,
354 slave ? slave->channel : 0,
355 nothing_ok);
356 if (master && slave) {
357 /*
358 * Stop any tones, or play ringtone as appropriate. If they are
359 * bridged in an active threeway call with a channel that is
360 * ringing, we should indicate ringing.
361 */
362 if (npc1->index == SUB_THREEWAY
364 && p1->subs[SUB_REAL].owner
365 && p1->subs[SUB_REAL].inthreeway
367 ast_debug(2,
368 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
369 p0->channel, npc0->index, ast_channel_name(c0),
370 p1->channel, npc1->index, ast_channel_name(c1));
371 tone_zone_play_tone(p0->subs[npc0->index].dfd, DAHDI_TONE_RINGTONE);
373 } else {
374 ast_debug(2, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
375 p0->channel, npc0->index, ast_channel_name(c0),
376 p1->channel, npc1->index, ast_channel_name(c1));
377 tone_zone_play_tone(p0->subs[npc0->index].dfd, -1);
378 }
379
380 if (npc0->index == SUB_THREEWAY
382 && p0->subs[SUB_REAL].owner
383 && p0->subs[SUB_REAL].inthreeway
385 ast_debug(2,
386 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
387 p1->channel, npc1->index, ast_channel_name(c1),
388 p0->channel, npc0->index, ast_channel_name(c0));
389 tone_zone_play_tone(p1->subs[npc1->index].dfd, DAHDI_TONE_RINGTONE);
391 } else {
392 ast_debug(2, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
393 p1->channel, npc1->index, ast_channel_name(c1),
394 p0->channel, npc0->index, ast_channel_name(c0));
395 tone_zone_play_tone(p1->subs[npc1->index].dfd, -1);
396 }
397
398 if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
399 if (!p0->echocanbridged || !p1->echocanbridged) {
400 /* Disable echo cancellation if appropriate */
403 }
404 }
406 master->inconference = inconf;
407 } else if (!nothing_ok) {
408 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n",
409 p0->channel, subnames[npc0->index],
410 p1->channel, subnames[npc1->index]);
411 }
414
417
418 /* Native bridge failed */
419 if ((!master || !slave) && !nothing_ok) {
422 return -1;
423 }
424
425 if (npc0->index == SUB_REAL) {
427 }
428 if (npc1->index == SUB_REAL) {
430 }
431
434
435 tech_pvt = bridge->tech_pvt;
436 tech_pvt->master = master;
437 tech_pvt->slave = slave;
438
439 ast_debug(2, "Start native bridging %s and %s\n",
441
442#if defined(HAVE_PRI) && defined(PRI_2BCT)
443 if (!tech_pvt->tried_trombone_removal) {
444 tech_pvt->tried_trombone_removal = 1;
445
446 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
447 q931_call *q931_c0;
448 q931_call *q931_c1;
449
450 /* Try to eliminate the tromboned call. */
451 ast_mutex_lock(&p0->pri->lock);
454 q931_c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
455 q931_c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
456 if (q931_c0 && q931_c1) {
457 pri_channel_bridge(q931_c0, q931_c1);
458 ast_debug(2, "Attempt to eliminate tromboned call with %s and %s\n",
460 }
461 ast_mutex_unlock(&p0->pri->lock);
462 }
463 }
464#endif /* defined(HAVE_PRI) && defined(PRI_2BCT) */
465 return 0;
466}
#define ast_log
Definition: astobj2.c:42
void dahdi_conf_update(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4843
void dahdi_ec_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4970
void dahdi_dtmf_detect_disable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6763
void dahdi_master_slave_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
Definition: chan_dahdi.c:7400
const char *const subnames[]
Definition: chan_dahdi.c:916
static int dahdi_sig_pri_lib_handles(int signaling)
Definition: chan_dahdi.h:825
#define SUB_THREEWAY
Definition: chan_dahdi.h:59
#define SUB_CALLWAIT
Definition: chan_dahdi.h:58
static int call(void *data)
Definition: chan_pjsip.c:2394
#define ast_channel_trylock(chan)
Definition: channel.h:2970
@ AST_STATE_RINGING
Definition: channelstate.h:41
#define LOG_WARNING
#define ast_mutex_trylock(a)
Definition: lock.h:191
struct dahdi_pvt * master
Definition: chan_dahdi.h:135
void * sig_pvt
Definition: chan_dahdi.h:764
unsigned int echocanbridged
TRUE if echo cancellation enabled when bridged.
Definition: chan_dahdi.h:270
unsigned int transfer
TRUE if call transfer is enabled.
Definition: chan_dahdi.h:382
int channel
Definition: chan_dahdi.h:585
int inconference
Definition: chan_dahdi.h:136
struct dahdi_pvt * master
struct dahdi_pvt * slave

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, dahdi_pvt::master, native_pvt_bridge::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::tech_pvt, ast_bridge_channel::tech_pvt, and dahdi_pvt::transfer.

Referenced by native_request_start().

◆ native_stop()

static void native_stop ( struct ast_bridge bridge)
static

Definition at line 138 of file bridge_native_dahdi.c.

139{
140 struct native_pvt_bridge *bridge_tech_pvt;
141 struct ast_bridge_channel *cur;
142
144
146 struct native_pvt_chan *chan_tech_pvt;
147
148 chan_tech_pvt = cur->tech_pvt;
149 if (!chan_tech_pvt) {
150 continue;
151 }
152
153 ast_mutex_lock(&chan_tech_pvt->pvt->lock);
154 if (chan_tech_pvt->pvt == ast_channel_tech_pvt(cur->chan)) {
155 dahdi_ec_enable(chan_tech_pvt->pvt);
156 }
157 if (chan_tech_pvt->index == SUB_REAL) {
158 dahdi_dtmf_detect_enable(chan_tech_pvt->pvt);
159 }
160 ast_mutex_unlock(&chan_tech_pvt->pvt->lock);
161 }
162
163 bridge_tech_pvt = bridge->tech_pvt;
164 dahdi_master_slave_unlink(bridge_tech_pvt->slave, bridge_tech_pvt->master, 1);
165
166 ast_debug(2, "Stop native bridging %s and %s\n",
168 ast_channel_name(AST_LIST_LAST(&bridge->channels)->chan));
169}
void dahdi_ec_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:4898
void dahdi_dtmf_detect_enable(struct dahdi_pvt *p)
Definition: chan_dahdi.c:6777
void dahdi_master_slave_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
Definition: chan_dahdi.c:7344

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::bridge, 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::tech_pvt, and ast_bridge_channel::tech_pvt.

Referenced by native_request_stop().

Variable Documentation

◆ dahdi_tech

const struct ast_channel_tech* dahdi_tech
static

Definition at line 49 of file bridge_native_dahdi.c.

Referenced by dahdi_native_load(), and native_bridge_is_capable().

◆ native_bridge

struct ast_bridge_technology native_bridge
static

Definition at line 862 of file bridge_native_dahdi.c.

Referenced by dahdi_native_load(), and dahdi_native_unload().