conncheck: fix try-alternate on tcp turn sockets
authorFabrice Bellet <fabrice@bellet.info>
Sun, 3 May 2020 15:39:09 +0000 (17:39 +0200)
committerOlivier CrĂȘte <olivier.crete@ocrete.ca>
Fri, 8 May 2020 19:34:12 +0000 (19:34 +0000)
In OC2007R2 compatibility mode, we observed the behaviour of a skype
turn server, when returning code 300 (try-alternate) stun error on its
tls connections. This value is returned apparently when the turn server
is overloaded already.

We noticed that the actual code in priv_handle_turn_alternate_server()
cannot handle a non-udp turn server, because a tcp one would require
to create a new socket.

But, even when creating such a new socket stack (tcp-bsd socket +
pseudossl socket), libnice still fails to establish a new connection to
the alternate server on port 443, in a very systematic way. I'm not sure
whether this problem is specific to this skype server infrastructure
(the skype client fails in a similar way). Anyway, this code path works
as expected with a non-microsoft turn server (tested with coturn).

agent/conncheck.c

index d58ec3b..40aca7f 100644 (file)
@@ -3859,11 +3859,30 @@ static void priv_handle_turn_alternate_server (NiceAgent *agent,
 
       nice_address_to_string (&server, ip);
       nice_debug ("Agent %p : Cancelling and setting alternate server %s for "
-          "CandidateDiscovery %p", agent, ip, d);
+          "CandidateDiscovery %p on s%d/c%d", agent, ip, d,
+          d->stream_id, d->component_id);
       d->server = alternate;
       d->turn->server = alternate;
       d->pending = FALSE;
       agent->discovery_unsched_items++;
+
+      if (d->turn->type == NICE_RELAY_TYPE_TURN_TCP ||
+          d->turn->type == NICE_RELAY_TYPE_TURN_TLS) {
+        NiceStream *stream;
+        NiceComponent *component;
+
+        if (!agent_find_component (agent, d->stream_id, d->component_id,
+            &stream, &component)) {
+          nice_debug ("Could not find stream or component in "
+              "priv_handle_turn_alternate_server");
+          continue;
+        }
+        d->nicesock = agent_create_tcp_turn_socket (agent, stream, component,
+            d->nicesock, &d->server, d->turn->type,
+            nice_socket_is_reliable (d->nicesock));
+
+        nice_component_attach_socket (component, d->nicesock);
+      }
     }
   }
 }
@@ -4089,7 +4108,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
               d->stun_message.buffer_len = 0;
               d->done = TRUE;
             }
-          } else {
+          } else if (d->pending) {
             /* case: STUN error, the check STUN context was freed */
             d->stun_message.buffer = NULL;
             d->stun_message.buffer_len = 0;