paullouisageneau / libdatachannel

C/C++ WebRTC network library featuring Data Channels, Media Transport, and WebSockets
https://libdatachannel.org/
Mozilla Public License 2.0
1.75k stars 357 forks source link

TURN Ice Candidates not found #495

Closed glynj-bsquare closed 2 years ago

glynj-bsquare commented 2 years ago

I'm not sure if this is a bug or me not using the library correctly.

I am trying to create a datachannel using a TURN server, but no Ice Candidates are found for it, so I am unable to send the relay candidate to the other end. I need to have both STUN and TURN candidates, as some devices are behind unusual firewall configurations so STUN doesn't work.

My code to create the peer connection is

bool PipeConnector::CreatePeerConnection()
{
    rtc::Configuration config;

    // const std::string stunServer = FREE_PUBLIC_STUN_SERVER;
    // config.iceServers.emplace_back( stunServer );

    // Temporary public TURN server used for testing
    const rtc::IceServer turnServer( "turn:numb.viagenie.ca", 3478,
                                     "webrtc@live.com",
                                     "muazkh" );

    config.iceServers.emplace_back( turnServer );

    config.portRangeBegin = START_WEBRTC_PORT;
    config.portRangeEnd = END_WEBRTC_PORT;

    pc = std::make_shared<rtc::PeerConnection>( config );
<snip>
    pc->onLocalCandidate( [this]( rtc::Candidate c ) {
        SendIceCandidate( c.candidate(), c.mid(), 0, userFragment );
    } );

The only Ice Candidate found is the local UDP host

candidate:1 1 UDP 2122317823 10.150.224.178 45600 typ host

(which works if I'm on the same local network).

I have verified that the turn server is working using https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/. I have verified I can connect to the TURN server from the device using nc -zvuw10 158.69.221.198 3478

I have tried setting config.iceTransportPolicy = rtc::TransportPolicy::Relay after which no Ice Candidates are produced at all, but the ICE Gathering state still moved to Complete.

In case it is relevant, I have compiled the libdatachannel-0.14.3 sources with the following options: +option(NO_WEBSOCKET "Disable WebSocket support" ON) +option(NO_MEDIA "Disable media transport support" ON) +option(NO_EXAMPLES "Disable examples" ON) +option(NO_TESTS "Disable tests build" ON)

paullouisageneau commented 2 years ago

I think the issue is with:

const rtc::IceServer turnServer( "turn:numb.viagenie.ca", 3478,
                                      "webrtc@live.com",
                                      "muazkh" );

Contrary to the constructor from an URL, the rtc::IceServer overloaded constructor expects the hostname as first parameter, it automatically creates TURN server entry if you specify a username and password. Replace turn:numb.viagenie.ca with numb.viagenie.ca and it should work.

glynj-bsquare commented 2 years ago

Thanks for the quick response and suggestion. I replaced it, and it still didn't find any turn ice candidates. I printed the turn server details before creating the PeerConnection to check the configuration, and the local ice candidates found. Is there internal debug I can turn on that might help?

2021-10-05T12:59:03Z [RemoteAccess] [Dbg ]  Server:numb.viagenie.ca
2021-10-05T12:59:03Z [RemoteAccess] [Dbg ]  Port:3478
2021-10-05T12:59:03Z [RemoteAccess] [Dbg ]  Type:1
2021-10-05T12:59:03Z [RemoteAccess] [Dbg ]  Username:webrtc@live.com
2021-10-05T12:59:03Z [RemoteAccess] [Dbg ]  Password:muazkh
2021-10-05T12:59:03Z [RemoteAccess] [Dbg ]  RelayType:0
2021-10-05T12:59:03Z [RemoteAccess] [Info] WebRTC session 31348: ICE GatheringState -> In Progress
2021-10-05T12:59:03Z [RemoteAccess] [Dbg ] candidate:1 1 UDP 2122317823 10.150.224.178 45604 typ host
paullouisageneau commented 2 years ago

Yes, you should enable the log with rtc::InitLogger(rtc::LogLevel::Debug) (or even rtc::InitLogger(rtc::LogLevel::Verbose)) to see what's wrong. Feel free to post it here.

glynj-bsquare commented 2 years ago

The log shows that the turn server returns something unexpected for one of the attributes.

2021-10-06 08:34:03.039 DEBUG [14974] [rtc::Init::Init@129] Global initialization
2021-10-06 08:34:03.045 DEBUG [14977] [rtc::impl::Certificate::Generate@223] Generating certificate (OpenSSL)
2021-10-06 08:34:03.047 DEBUG [14974] [rtc::impl::IceTransport::IceTransport@58] Initializing ICE transport (libjuice)
2021-10-06 08:34:03.048 INFO  [14974] [rtc::impl::IceTransport::IceTransport@122] Using TURN server "numb.viagenie.ca:3478"
2021-10-06 08:34:03.050 INFO  [14974] [rtc::impl::PeerConnection::changeSignalingState@1079] Changed signaling state to new
2021-10-06 08:34:03.050 DEBUG [14974] [rtc::impl::PeerConnection::processLocalDescription@779] Reciprocating application in local description, mid="0"
2021-10-06 08:34:03.054 INFO  [14974] [rtc::impl::PeerConnection::changeSignalingState@1079] Changed signaling state to new
2021-10-06 08:34:03.055 INFO  [14974] [rtc::impl::PeerConnection::changeGatheringState@1068] Changed gathering state to in-progress
2021-10-06 08:34:03.055 INFO  [14974] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:782: Changing state to gathering
2021-10-06 08:34:03.056 INFO  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:782: Changing state to connecting
2021-10-06 08:34:03.057 INFO  [14985] [rtc::impl::PeerConnection::changeState@1051] Changed state to connecting
2021-10-06 08:34:03.121 INFO  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:536: Using TURN server numb.viagenie.ca:3478
2021-10-06 08:34:03.208 INFO  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:695: Got unknown attribute response for attribute 0x1A
2021-10-06 08:34:03.209 INFO  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:686: Got STUN error code 420, reason "Unknown Attribute"
2021-10-06 08:34:03.209 WARN  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:1719: Got TURN Allocate error response, code=420
2021-10-06 08:34:03.209 INFO  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:1721: TURN allocation failed
2021-10-06 08:34:03.209 INFO  [14985] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:2313: Candidate gathering done
2021-10-06 08:34:03.209 INFO  [14985] [rtc::impl::PeerConnection::changeGatheringState@1068] Changed gathering state to complete

I will try a different turn server to see if the same thing happens.

paullouisageneau commented 2 years ago

The problem is indeed that server does not support the DONT-FRAGMENT TURN attribute. What is the server?

I'll add a client retry without the attribute to get around this kind of issue, as it is not strictly necessary.

glynj-bsquare commented 2 years ago

The server is

define FREE_PUBLIC_TURN_SERVER "numb.viagenie.ca"

define FREE_PUBLIC_TURN_PASSWORD "webrtc@live.com"

define FREE_PUBLIC_TURN_USERNAME "muazkh"

paullouisageneau commented 2 years ago

Sure, but I meant what software does it run.

glynj-bsquare commented 2 years ago

I'm sorry I don't know. This is a free service on the web I'm currently using for test purposes while our devops team organise one we control. Their website https://numb.viagenie.ca/ says it conforms to the various specs. Once I have an internal server I can let you know what we are using.

glynj-bsquare commented 2 years ago

I have temporarily hacked the library to remove the don't fragment option from the messages, and found further information showing that the server behind viagenie doesn't support the RFC level of the datachannel library. This is reported in a couple of places. I expect I need to wait for a turn server we can control.


2021-10-06 13:07:33.345 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:625: Reading attribute 0x15, length=40
2021-10-06 13:07:33.346 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:763: Reading nonce
2021-10-06 13:07:33.346 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:770: Got nonce: hZFdYQAAAAA=iajvFmeFn7eOZdNQ0JhKqEOnh0c=
2021-10-06 13:07:33.346 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:795: Remote agent does not support RFC 8489
2021-10-06 13:07:33.347 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: stun.c:549: Finished reading STUN attributes
2021-10-06 13:07:33.347 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:1170: STUN message is a response, looking for transaction ID
2021-10-06 13:07:33.347 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:1174: STUN entry 0 matching incoming transaction ID
2021-10-06 13:07:33.348 VERB  [26356] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:1646: Got TURN Allocate Unauthorized response
2021-10-06 13:07:33.348 ERROR [26356] [rtc::impl::IceTransport::LogCallback@344] juice: agent.c:1648: TURN authentication failed```
paullouisageneau commented 2 years ago

That's not a problem, mainly an information that RFC 8489 features (for instance more secure cryptography) will be disabled because the server does not support them. It should still work.

Here the problem is actually that the authentication failed, are you sure the username and password are correct?

glynj-bsquare commented 2 years ago

Thanks for letting me know. I had tweaked the password in an earlier test and missed reverting the change. It now connects to that server using TURN with the "don't fragment" part of the message removed.

paullouisageneau commented 2 years ago

I'm removing the attribute in https://github.com/paullouisageneau/libjuice/pull/129, as the agent actually leverages TURN Channel Data to reduce overhead on user data, a method on which DONT-FRAGMENT has not impact. The attribute is therefore quite useless.

paullouisageneau commented 2 years ago

Great, the issue should now be fixed in https://github.com/paullouisageneau/libdatachannel/commit/600bf41eebf2583892427682b8cb9a1f434fdc9b. Thank you for reporting!