]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
bridge core: Add owed T.38 terminate when channel leaves a bridge. 01/2301/2
authorRichard Mudgett <rmudgett@digium.com>
Mon, 22 Feb 2016 19:54:47 +0000 (13:54 -0600)
committerRichard Mudgett <rmudgett@digium.com>
Mon, 29 Feb 2016 18:50:19 +0000 (12:50 -0600)
The channel is now going to get T.38 terminated when it leaves the
bridging system and the bridged peers are going to get T.38 terminated as
well.

ASTERISK-25582

Change-Id: I77a9205979910210e3068e1ddff400dbf35c4ca7

include/asterisk/bridge_channel.h
main/bridge_channel.c
main/channel.c

index 03fe30e002277e3d37a08cf1ece73e6a2812724c..55c2b3a7616215748eea9f7775fc5ddf3cf37b8c 100644 (file)
@@ -170,6 +170,8 @@ struct ast_bridge_channel {
                /*! Collected DTMF digits for DTMF hooks. */
                char collected[MAXIMUM_DTMF_FEATURE_STRING];
        } dtmf_hook_state;
+       /*! Non-zero if a T.38 session terminate is owed to the bridge. */
+       char owed_t38_terminate;
 };
 
 /*!
index fa15b0f71523a5200d5430c755da1b539b3ce6ee..c9262a84afe1edc5fce85935f6cb0eec974786d9 100644 (file)
@@ -637,6 +637,8 @@ void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int caus
  */
 static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
+       const struct ast_control_t38_parameters *t38_parameters;
+
        ast_assert(frame->frametype != AST_FRAME_BRIDGE_ACTION_SYNC);
 
        ast_bridge_channel_lock_bridge(bridge_channel);
@@ -663,6 +665,27 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel,
                 * We explicitly will not remember HOLD/UNHOLD frames because
                 * things like attended transfers will handle them.
                 */
+               switch (frame->subclass.integer) {
+               case AST_CONTROL_T38_PARAMETERS:
+                       t38_parameters = frame->data.ptr;
+                       switch (t38_parameters->request_response) {
+                       case AST_T38_REQUEST_NEGOTIATE:
+                       case AST_T38_NEGOTIATED:
+                               bridge_channel->owed_t38_terminate = 1;
+                               break;
+                       case AST_T38_REQUEST_TERMINATE:
+                       case AST_T38_TERMINATED:
+                       case AST_T38_REFUSED:
+                               bridge_channel->owed_t38_terminate = 0;
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               break;
        default:
                break;
        }
@@ -689,6 +712,7 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel,
 static void bridge_channel_cancel_owed_events(struct ast_bridge_channel *bridge_channel)
 {
        bridge_channel->owed.dtmf_digit = '\0';
+       bridge_channel->owed_t38_terminate = 0;
 }
 
 void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct ast_bridge_channel *bridge_channel)
@@ -710,6 +734,23 @@ void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct as
                bridge_channel->owed.dtmf_digit = '\0';
                orig_bridge->technology->write(orig_bridge, NULL, &frame);
        }
+       if (bridge_channel->owed_t38_terminate) {
+               struct ast_control_t38_parameters t38_parameters = {
+                       .request_response = AST_T38_TERMINATED,
+               };
+               struct ast_frame frame = {
+                       .frametype = AST_FRAME_CONTROL,
+                       .subclass.integer = AST_CONTROL_T38_PARAMETERS,
+                       .data.ptr = &t38_parameters,
+                       .datalen = sizeof(t38_parameters),
+                       .src = "Bridge channel owed T.38 terminate",
+               };
+
+               ast_debug(1, "T.38 terminate simulated to bridge %s because %s left.\n",
+                       orig_bridge->uniqueid, ast_channel_name(bridge_channel->chan));
+               bridge_channel->owed_t38_terminate = 0;
+               orig_bridge->technology->write(orig_bridge, NULL, &frame);
+       }
 }
 
 /*!
@@ -2736,6 +2777,18 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel,
                        ast_channel_sending_dtmf_tv(bridge_channel->chan), "bridge end");
        }
 
+       /* Complete any T.38 session before exiting the bridge. */
+       if (ast_channel_is_t38_active(bridge_channel->chan)) {
+               struct ast_control_t38_parameters t38_parameters = {
+                       .request_response = AST_T38_TERMINATED,
+               };
+
+               ast_debug(1, "Channel %s simulating T.38 terminate for bridge end.\n",
+                       ast_channel_name(bridge_channel->chan));
+               ast_indicate_data(bridge_channel->chan, AST_CONTROL_T38_PARAMETERS,
+                       &t38_parameters, sizeof(t38_parameters));
+       }
+
        /* Indicate a source change since this channel is leaving the bridge system. */
        ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE);
 
index de7c19cc5f8d5cbf2ed25ba2313ac50ba21a0194..4ed1f8b8a262189d8cdcee55a578aeb5eddae683 100644 (file)
@@ -4479,6 +4479,7 @@ static int indicate_data_internal(struct ast_channel *chan, int _condition, cons
         * in switch statements. */
        enum ast_control_frame_type condition = _condition;
        struct ast_tone_zone_sound *ts = NULL;
+       const struct ast_control_t38_parameters *t38_parameters;
        int res;
 
        switch (condition) {
@@ -4498,6 +4499,22 @@ static int indicate_data_internal(struct ast_channel *chan, int _condition, cons
        case AST_CONTROL_UNHOLD:
                ast_channel_hold_state_set(chan, _condition);
                break;
+       case AST_CONTROL_T38_PARAMETERS:
+               t38_parameters = data;
+               switch (t38_parameters->request_response) {
+               case AST_T38_REQUEST_NEGOTIATE:
+               case AST_T38_NEGOTIATED:
+                       ast_channel_set_is_t38_active_nolock(chan, 1);
+                       break;
+               case AST_T38_REQUEST_TERMINATE:
+               case AST_T38_TERMINATED:
+               case AST_T38_REFUSED:
+                       ast_channel_set_is_t38_active_nolock(chan, 0);
+                       break;
+               default:
+                       break;
+               }
+               break;
        default:
                break;
        }