summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorMatt Jordan <mjordan@digium.com>2015-12-06 16:32:32 -0600
committerMatt Jordan <mjordan@digium.com>2015-12-06 16:32:32 -0600
commit529535f0c2dd2fca84e31287dd7a00622cacd3c8 (patch)
treecfb4dd85a5759f4e5beb5e954f7a6809fab9a3db /bridges
parent9c0aaf06096c8f6b16eb98283916f91823ea14eb (diff)
Revert "bridges/bridge_t38: Add a bridging module for managing T.38 state"
This reverts commit 6614babea27fbafbe11820ea03737dd5c4f9ecec. Unfortunately, using a bridge to manage T.38 state will cause severe deadlocks in core_unreal/chan_local. Local channels attempt to reach across both their peer and the peer's bridge to inspect T.38 state. Given the propensity of Local channel chains, managing the locking situation in such a scenario is practically infeasible. Change-Id: Ic687397ffea08dfb899345a443bd990ec3d0416a
Diffstat (limited to 'bridges')
-rw-r--r--bridges/bridge_t38.c261
1 files changed, 0 insertions, 261 deletions
diff --git a/bridges/bridge_t38.c b/bridges/bridge_t38.c
deleted file mode 100644
index 706ed227f..000000000
--- a/bridges/bridge_t38.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2015, Digium, Inc.
- *
- * Matt Jordan <mjordan@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Bridging module for maintaining T.38 state for faxing channels
- *
- * \author Matt Jordan <mjordan@digium.com>
- *
- * \ingroup bridges
- */
-
-/*** MODULEINFO
- <support_level>core</support_level>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include "asterisk/module.h"
-#include "asterisk/channel.h"
-#include "asterisk/bridge.h"
-#include "asterisk/bridge_technology.h"
-#include "asterisk/frame.h"
-
-/*! \brief The current state of the T.38 fax for the channels in our bridge */
-struct t38_bridge_state {
- /* \brief First channel in the bridge */
- struct ast_bridge_channel *bc0;
- /*! \brief Second channel in the bridge */
- struct ast_bridge_channel *bc1;
- /*! \brief T.38 state of \c bc0 */
- enum ast_t38_state c0_state;
- /*! \brief T.38 state of \c bc1 */
- enum ast_t38_state c1_state;
-};
-
-static void t38_bridge_destroy(struct ast_bridge *bridge)
-{
- struct t38_bridge_state *state = bridge->tech_pvt;
-
- ast_free(state);
- bridge->tech_pvt = NULL;
-}
-
-static int t38_bridge_create(struct ast_bridge *bridge)
-{
- struct t38_bridge_state *state;
-
- state = ast_calloc(1, sizeof(*state));
- if (!state) {
- return -1;
- }
-
- bridge->tech_pvt = state;
-
- return 0;
-}
-
-static int t38_bridge_start(struct ast_bridge *bridge)
-{
- struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
- struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
- struct t38_bridge_state *state = bridge->tech_pvt;
-
- state->bc0 = bc0;
- state->bc1 = bc1;
- state->c0_state = ast_channel_get_t38_state(state->bc0->chan);
- state->c1_state = ast_channel_get_t38_state(state->bc1->chan);
-
- return 0;
-}
-
-static void send_termination_update(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, enum ast_t38_state chan_state)
-{
- /* Inform the other side that T.38 faxing is done */
- struct ast_control_t38_parameters parameters = { .request_response = 0, };
-
- if (!bridge_channel) {
- return;
- }
-
- ast_debug(5, "Bridge %s T.38: Current state of %s is %d\n",
- bridge->uniqueid, ast_channel_name(bridge_channel->chan), chan_state);
- if (chan_state == T38_STATE_NEGOTIATING) {
- parameters.request_response = AST_T38_REFUSED;
- } else if (chan_state == T38_STATE_NEGOTIATED) {
- parameters.request_response = AST_T38_TERMINATED;
- }
-
- if (parameters.request_response) {
- struct ast_frame f = {
- .frametype = AST_FRAME_CONTROL,
- .subclass.integer = AST_CONTROL_T38_PARAMETERS,
- .data.ptr = &parameters,
- .datalen = sizeof(parameters),
- };
-
- /* When sending a termination update to a channel, the bridge is highly
- * likely to be getting torn down. Queueing a frame through the bridging
- * framework won't work, as the frame will likely just get tossed as the
- * bridge collapses. Hence, we write directly to the channel to ensure that
- * they know they aren't in a T.38 fax any longer.
- */
- ast_debug(3, "Bridge %s T.38: Informing %s to switch to %d\n",
- bridge->uniqueid, ast_channel_name(bridge_channel->chan), parameters.request_response);
- ast_write(bridge_channel->chan, &f);
- }
-}
-
-static void t38_bridge_stop(struct ast_bridge *bridge)
-{
- struct t38_bridge_state *state = bridge->tech_pvt;
-
- send_termination_update(bridge, state->bc0, state->c0_state);
- send_termination_update(bridge, state->bc1, state->c1_state);
-}
-
-static void t38_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
-{
- struct t38_bridge_state *state = bridge->tech_pvt;
-
- if (bridge_channel == state->bc0) {
- send_termination_update(bridge, state->bc0, state->c0_state);
- state->bc0 = NULL;
- state->c0_state = T38_STATE_UNKNOWN;
- } else {
- send_termination_update(bridge, state->bc1, state->c1_state);
- state->bc1 = NULL;
- state->c1_state = T38_STATE_UNKNOWN;
- }
-}
-
-static int t38_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
-{
- struct t38_bridge_state *state = bridge->tech_pvt;
- enum ast_t38_state *c_state;
- enum ast_t38_state *other_state;
-
- if (!bridge_channel) {
- return -1;
- }
-
- c_state = bridge_channel == state->bc0 ? &(state->c0_state) : &(state->c1_state);
- other_state = bridge_channel == state->bc0 ? &(state->c1_state) : &(state->c0_state);
-
- switch (frame->frametype) {
- case AST_FRAME_CONTROL:
- switch (frame->subclass.integer) {
- case AST_CONTROL_T38_PARAMETERS:
- {
- struct ast_control_t38_parameters *parameters = frame->data.ptr;
-
- switch (parameters->request_response) {
- case AST_T38_REQUEST_NEGOTIATE:
- *c_state = T38_STATE_NEGOTIATING;
- *other_state = T38_STATE_NEGOTIATING;
- break;
- case AST_T38_NEGOTIATED:
- *c_state = T38_STATE_NEGOTIATED;
- break;
- case AST_T38_TERMINATED:
- case AST_T38_REQUEST_TERMINATE:
- case AST_T38_REFUSED:
- *c_state = T38_STATE_REJECTED;
- break;
- case AST_T38_REQUEST_PARMS:
- default:
- /* No state change */
- break;
- }
- ast_debug(3, "Bridge %s T.38 state: %s: %d; %s: %d\n",
- bridge->uniqueid, ast_channel_name(state->bc0->chan), state->c0_state,
- ast_channel_name(state->bc1->chan), state->c1_state);
- break;
- }
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
-}
-
-static int t38_bridge_compatible(struct ast_bridge *bridge)
-{
- struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
- struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
- enum ast_t38_state c0_state;
- enum ast_t38_state c1_state;
-
- /* We must have two, and only two, channels in a T.38 bridge */
- if (bridge->num_channels != 2) {
- ast_debug(1, "Bridge '%s' can not use T.38 bridge as two channels are required\n",
- bridge->uniqueid);
- return 0;
- }
-
- /* We can be the bridge tech so long as one side is in the process
- * of negotiating T.38
- */
- c0_state = ast_channel_get_t38_state(bc0->chan);
- c1_state = ast_channel_get_t38_state(bc1->chan);
- if (c0_state != T38_STATE_NEGOTIATING && c0_state != T38_STATE_NEGOTIATED
- && c1_state != T38_STATE_NEGOTIATING && c1_state != T38_STATE_NEGOTIATED) {
- ast_debug(1, "Bridge '%s' can not use T.38 bridge: channel %s has T.38 state %d; channel %s has T.38 state %d\n",
- bridge->uniqueid, ast_channel_name(bc0->chan), c0_state, ast_channel_name(bc1->chan), c1_state);
- return 0;
- }
-
- return 1;
-}
-
-static struct ast_bridge_technology t38_bridge = {
- .name = "t38_bridge",
- .capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
- .preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX + 1,
- .create = t38_bridge_create,
- .destroy = t38_bridge_destroy,
- .start = t38_bridge_start,
- .stop = t38_bridge_stop,
- .leave = t38_bridge_leave,
- .write = t38_bridge_write,
- .compatible = t38_bridge_compatible,
-};
-
-static int unload_module(void)
-{
- ast_bridge_technology_unregister(&t38_bridge);
-
- return 0;
-}
-
-static int load_module(void)
-{
- if (ast_bridge_technology_register(&t38_bridge)) {
- return AST_MODULE_LOAD_DECLINE;
- }
- return AST_MODULE_LOAD_SUCCESS;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Two channel bridging module that maintains T.38 state");