]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
chan_sip.c: Fix T.38 issues caused by leaving a bridge. 03/2303/2
authorRichard Mudgett <rmudgett@digium.com>
Mon, 22 Feb 2016 22:59:40 +0000 (16:59 -0600)
committerRichard Mudgett <rmudgett@digium.com>
Mon, 29 Feb 2016 18:58:48 +0000 (12:58 -0600)
chan_sip could not handle AST_T38_TERMINATED frames being sent to it when
the channel left the bridge.  The action resulted in overlapping outgoing
reINVITEs.  The testsuite tests/fax/sip/directmedia_reinvite_t38 was not
happy.

* Force T.38 to be remembered as locally bridged.  Now when the channel
leaves the native RTP bridge after T.38, the channel remembers that it has
already reINVITEed the media back to Asterisk.  It just needs to terminate
T.38 when the AST_T38_TERMINATED arrives.

* Prevent redundant AST_T38_TERMINATED from causing problems.  Redundant
AST_T38_TERMINATED frames could cause overlapping outgoing reINVITEs if
they happen before the T.38 state changes to disabled.  Now the T.38 state
is set to disabled before the reINVITE is sent.

ASTERISK-25582 #close

Change-Id: I53f5c6ce7d90b3f322a942af1a9bcab6d967b7ce

channels/chan_sip.c

index 3b6c00513b5651cfb9b5464a73ff0bda648c2f86..4e0d811591048bacb9e8198af455b5e2b692014d 100644 (file)
@@ -7517,8 +7517,10 @@ static int interpret_t38_parameters(struct sip_pvt *p, const struct ast_control_
                        AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr"));
                        change_t38_state(p, T38_REJECTED);
                        transmit_response_reliable(p, "488 Not acceptable here", &p->initreq);
-               } else if (p->t38.state == T38_ENABLED)
+               } else if (p->t38.state == T38_ENABLED) {
+                       change_t38_state(p, T38_DISABLED);
                        transmit_reinvite_with_sdp(p, FALSE, FALSE);
+               }
                break;
        case AST_T38_REQUEST_PARMS: {           /* Application wants remote's parameters re-sent */
                struct ast_control_t38_parameters parameters = p->t38.their_parms;
@@ -10676,6 +10678,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
                } else if (udptlportno > 0) {
                        if (debug)
                                ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session.\n");
+
+                       /* Force media to go through us for T.38. */
+                       memset(&p->redirip, 0, sizeof(p->redirip));
+
                        /* Prevent audio RTCP reads */
                        if (p->owner) {
                                ast_channel_set_fd(p->owner, 1, -1);
@@ -13787,6 +13793,29 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old
 {
        struct sip_request req;
 
+       if (t38version) {
+               /* Force media to go through us for T.38. */
+               memset(&p->redirip, 0, sizeof(p->redirip));
+       }
+       if (p->rtp) {
+               if (t38version) {
+                       /* Silence RTCP while audio RTP is inactive */
+                       ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 0);
+                       if (p->owner) {
+                               /* Prevent audio RTCP reads */
+                               ast_channel_set_fd(p->owner, 1, -1);
+                       }
+               } else if (ast_sockaddr_isnull(&p->redirip)) {
+                       /* Enable RTCP since it will be inactive if we're coming back
+                        * with this reinvite */
+                       ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1);
+                       if (p->owner) {
+                               /* Enable audio RTCP reads */
+                               ast_channel_set_fd(p->owner, 1, ast_rtp_instance_fd(p->rtp, 1));
+                       }
+               }
+       }
+
        reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ?  SIP_UPDATE : SIP_INVITE, 0, 1);
 
        add_header(&req, "Allow", ALLOWED_METHODS);
@@ -32683,14 +32712,6 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i
        } else if (!ast_sockaddr_isnull(&p->redirip)) {
                memset(&p->redirip, 0, sizeof(p->redirip));
                changed = 1;
-
-               if (p->rtp) {
-                       /* Enable RTCP since it will be inactive if we're coming back
-                        * from a reinvite */
-                       ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1);
-                       /* Enable audio RTCP reads */
-                       ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(p->rtp, 1));
-               }
        }
 
        if (vinstance) {