Closed GerbenHettinga closed 2 years ago
I think the issue comes from the way you handle candidates: each side outputs one description but multiple candidates. It seems your code will override each candidate by the next in the candidate box and as a result only display the last one.
There is a semantic subtlety in the API: the methods are called setRemoteDescription
(as there is only one so it will replace the remote description) and addRemoteCandidate
(as it will add one more candidate to the list, not replace existing candidates).
This seems to be because the ICE candidates are already enumerated in the localdescription SDP. When I call WEBRTC.peerConnection[1].localDescription.sdp from the console I also get this version of the answer. However, I am unable to obtain the same localdescription using this library. Is there a way this is easily achieved?
This can be done. You just need to wait for GatheringState
to be Complete
, then you can retrieve the local description with all candidates by calling pc->localDescription()
. This method, called non-trickle ICE, allows for an simpler signaling as it does not require exchanging candidates, only the descriptions, but it could introduce delays if a STUN/TURN server is unreachable.
Indeed by appending the candidates to the textbox I was able to set up a working datachannel.
I also now check the GatheringState
if it is complete after which the description is automatically put in the textbox.
pc->onGatheringStateChange([](rtc::PeerConnection::GatheringState state) {
std::cout << "[Gathering State: " << toString(state) << "]" << std::endl;
if(state == rtc::PeerConnection::GatheringState::Complete) {
std::optional<rtc::Description> desc = pc->localDescription();
if(desc.has_value()) {
putDescriptionInOfferBox(rtc::string(desc.value()).c_str());
}
}
});
Did you publish the working example?
@paullouisageneau could you explain that into a little more detail?
The original issue was that only the last candidate was displayed in the candidate textbox, other candidates were dropped. This is unrelated to what you experience here as your example is not copy paste, and you don't trickle candidates, you wait for gathering complete to send descriptions with candidates.
I tried to make a similar connection establishment based on your copy-paste example, with the only difference that I use a WebSocket server and no copy/paste. My connection works on Firefox, but not on Chrome (same issue as above).
My code in a simplified version: [...]
The code has a bunch of issues but I don't know if it's because it's "simplified" or not: pc
is a local object so it will be destroyed as soon as you leave the init_peer_connection()
function, the type is not sent over the websocket but it is received it somehow, anser
is written instead of anwser
, a callback is set on dc
instead of _dc
...
You have to debug your code and check you transmit the descriptions back and forth correctly. Note it is not good practice to assume and hardcode description type, instead you should get it from description.typeString()
and transmit it.
Hi, I am doing it in a very similar way (also tried the exact same program) and it works perfectly fine in Firefox. However in Chrome, it does not output any Candidates and also if setting a candidate from firefox it says: OperationError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
.
Is this an error on my side? I found a Stackoverflow discussion saying, that you need to call setLocalDescription()
, but this isn't implemented afaik
Does Chrome generate a description? The error indeed means setLocalDescription()
was not called so you can't add candidates. The wrapper calls it on both createDataChannel()
and setRemoteDescription()
, you should check they are indeed called and don't fail.
Interesting, didn't see that. Yes, it seems to be working, as if i log in the function handleDescription
the variable peerConnection.localDescription.sdp
it outputs 116600
Yes, it seems to be working, as if i log in the function
handleDescription
the variablepeerConnection.localDescription.sdp
it outputs116600
This doesn't look right. If localDescription
is set, sdp
should contain the SDP description.
You are right, it contains the SDP description - this was just me looking at the wrong value. But I now found out that the function peerConnection.onicecandidate
get called, however, the candidates of if(evt.candidate && evt.candidate.candidate)
equal null and therefore the function handleCandidate
doesn't get called
@tbuchs FWIW here are a few ways I have implemented "copy/paste"/"signaling server" programmatically, and programmatically with user action
and the last time I did this with libdatachannel
libdatachannel-wasm
, yet.You are right, it contains the SDP description - this was just me looking at the wrong value. But I now found out that the function
peerConnection.onicecandidate
get called, however, the candidates ofif(evt.candidate && evt.candidate.candidate)
equal null and therefore the functionhandleCandidate
doesn't get called
Null candidate means all candidates have been gathered. This would mean that the browser fails to gather any candidates, not even host ones. Does WebRTC work as expected in the browser? There could be a privacy extension interfering with it.
also if setting a candidate from firefox it says:
OperationError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
.
Actually there are two different issues as this means the remote description is not set. Is setRemoteDescription()
called before attempting to add candidates?
You are right, it contains the SDP description - this was just me looking at the wrong value. But I now found out that the function
peerConnection.onicecandidate
get called, however, the candidates ofif(evt.candidate && evt.candidate.candidate)
equal null and therefore the functionhandleCandidate
doesn't get calledNull candidate means all candidates have been gathered. This would mean that the browser fails to gather any candidates, not even host ones. Does WebRTC work as expected in the browser? There could be a privacy extension interfering with it.
That was a very good hint, thanks. It is indeed working with chrome in incognito mode - even though, I don't know the problem, since I have disabled all extensions and it is still not working
also if setting a candidate from firefox it says:
OperationError: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
.Actually there are two different issues as this means the remote description is not set. Is
setRemoteDescription()
called before attempting to add candidates?
Yes, it gets called before
I'm trying to use this library in a simple copy-paste situation such as set out in the example of https://github.com/paullouisageneau/libdatachannel/tree/master/examples/copy-paste
Instead of reading from std::cin I copy paste offers and answers into html text boxes. However I'm unable to setup a connection in this manner. I always get a "WebRTC: ICE failed, add a TURN server and see about:webrtc for more details" on Firefox or Chrome never seems to progress further than the [State: Connecting] state.
Here is the main code adapted from the libdatachannel example:
and the html front end
I use it in the following manner. I have two tabs. The 'offerer' tab creates the initial data connection and offer, which are copy pasted to the 'answerer'. Which in turn generates an answer that gets pasted to the offerer. The same thing for the candidates. I built and ran the libdatachannel offerer and answerer example and it seems to be the exact same process and in that case I was able to set up a connection.
One thing that does allow me to make a connection is when I copy the answer from the "about:webrtc" page after pasting in the offer from the offerer. This immediately allows me to setup a connection and creates a functioning datachannel between the tabs without having to specify the candidates manually. This seems to be because the ICE candidates are already enumerated in the localdescription SDP. When I call WEBRTC.peerConnection[1].localDescription.sdp from the console I also get this version of the answer. However, I am unable to obtain the same localdescription using this library. Is there a way this is easily achieved? Why is the call to WEBRTC.peerConnection[1].localDescription.sdp in the javascript portion of the library giving a different result as when doing it in the console?
Any assistance would be appreciated.