Second RTCPeerConnection stuck in "connecting" state, while first connection successfully connects - webrtc

So I'm trying to set up a 3-way video call with WebRTC.
The first two connections connect fine. I have it set up so that the third person to join the room sends an offer to the first 2 sockets in the room (I'm using Node.js socket.io as a signalling server). The offer successfully sends to both sockets, and both sockets send back their answers. Both answers contain 1 audio track and 1 video track, however, for some reason, the connection only works with one of them.
The result is that with 3 users, the first user (usually) ends up seeing both peers, and then the second and third people only see one other person. When I look at the connectionState for each peer connection, one of them is stuck in "connecting", while everything else looks fine.
Any ideas?

Are you creating a new PeerConnection for the first two people in the room? When you say first 2 sockets it sounds like you are trying to use the same PeerConnection for multiple connections.
Each PeerConnection is only for a 1:1 connection. What you are trying to create is a Mesh Topology I believe.

Related

How to know what device to pass SDP to across signaling server when establishing WebRTC connection

Let's say I have an application that has a list of live streamers who are currently broadcasting via WebRTC. In order for a device to plug into a particular broadcaster, they need to send their SDP to the specific broadcaster that they click on.
So I gather my local SDP information, and send that to the Signaling server to be transferred to the broadcaster and await the answer.
My question is, how does the signaling server know which broadcaster to send this SDP to? And where do you store this identifier?
My first thought was use the ip address as the unique identifier but that can change as I move around and change connections.
And is it normal to store this identifier on the web socket itself as a property? I don't know how else you would know which web socket to send along the SDP?
Sorry if this is a n00b question, very new to WebRTC.
I also faced same situation like you.
In my case, I used Socket.IO for bidirectional communication.
So what I did is using member's id and socket.io's room.
When socket.io client connected to server, this client joined specific room automatically.
That room's name is client's socket ID. You can check this doc.
For example, your service is broadcasting. right?
And maybe broadcasters in your service have unique id (in Database).
So when client is connected to server, escape from default room immediately, and join new room that name is client's unique id.
Then, now you can send some messages like sdp to specific client with client's unique id.

An issue to share streams with multiple peers in WebRTC?

Using latest Chrome. As far as I can tell, everything sets up correctly. Offer/Answer..Candidates..I expected...
However, one strange issue I noticed..and I googled...found that exactly same issue I am currently noticing...
https://stackoverflow.com/questions/44157738/webrtc-sharing-one-stream-with-multiple-peers
I also have three peers. What I want is that A sees B and C, B sees A and C, and C sees A and B.
Only one peer can see the other two peers, but the other two peers only see one...
BTW, I confirmed that each peer got notified onaddstream event two times, which is correct.
Here is what I did..
Once I get the stream, I stored this to my window.localStream...
Whenever a peer connection(since I support multiple peers, I managed this with dictionary) comes in, I added this localStream by peerConnection.addStream(window.localStream)
I set up the stream in video tag in peerConnection.onaddstream ...
Once the MediaStream is active and being transmitted then, this same stream cannot be transmitted to another peer at the same time?
Any help would be greatly appreciated.
Thanks,
Sending the same stream to multiple peers should work. Compare your code to https://webrtc.github.io/samples/src/content/peerconnection/multiple/ which shows how to achieve this. Your issue sounds like you might not set the answer on the right peerconnection. Inspecting eachs connection signalingState and iceConnectionState may provide further insight.
I meet the same problem, finally find out that It's because the sdp and ice candidate of the third client always be covered, only remain single peer of third client work.

How to validate WebRTC connection signals when peers can't trust each other?

I am building a WebRTC app where two users are selected at random and then connect to each other to chat. Both clients keep an open WebSocket connection and I am planning to use this to exchange their offers/answers to signal a connection. The case I am trying to account for is when there is a peer that intentionally sends bad configuration information, and also when the peer might spontaneously disconnect in the middle of the signaling exchange.
My solution to the first case is have the server keep state of the exchange, so when the connection is first established I would expect that user A provide an offer and user B have an answer. Is this appropriate? or should this be implemented exclusively client side?
My solution to the second problem feels to me like a hack. What I am trying to do is notify the user that a match has been made and then the user will set a timeout say 20 seconds, if a connection hasn't been made in that amount of time then it should move on...
Are these appropriate solutions? How do you reliably establish a WebRTC when either peer can't be trusted? Should the signaling server be concerned with the state of the exchange?
Sounds like you're more concerned about call set up errors rather than being able to trust the identity of the remote peer. They are two very different problems.
Assuming it is the call set up errors you are concerned about you shouldn't be trying to avoid them you should be trying to make sure your application can handle them. Network connection issues are something that will always crop up and need to be handled.
Setting a timer for the establishment of a WebRTC call to complete is a logical solution. Displaying a warning to the user that the time limit is approaching also seems like a good idea. SIP is a signalling protocol and it has a defined timeout for the completion of a transaction and if it doesn't complete within that time it will generate an error response. You could use the same approach.

python twisted: enforcing a single connection per id

I have a twisted server using SSL sockets and using certificates to identify the different clients that connect to the server. I'd like to enforce the state where there is only one connection by each possible id. The two ways I can think of is to keep track of connected ids and then not allow a second connection by the same id or allow the second connection and immediately terminate the first. I'm trying to do the later but am having some issues (I'll explain my choice at the end)
I'm storing a list of connections in the factory class and then after the SSL handshake I compare the client's id with that list. If it's already in that list I try to call .transport.abortConnection() on it. I then want to do the normal things I do to record the new connection in my database. However, the call to abortConnection() doesn't seem to call connectionLost() directly which is where I do my cleanup and calls to the database to say that a connection was lost. So, my code then records that the id connected but later a call is made to connectionLost() resulting in the database appearing to have that id disconnected.
Is there some sort of way to block the incoming second connection from further processing until the first connection has finished processing the disconnection?
Choice explanation: The whole reason I'm doing this is I have clients behind NATs that appear to be changing their IP address on a fairly regular basis (once a every 1-3 days). The devices connecting will just have their connections uncleanly severed and then they try to reconnect with the new IP. However, my server isn't notified about the disconnect and usually has to timeout the connection. Before the server times out the connection, though, the client sometimes manages to reconnect and the server then is in a state with two apparent connections by the same client. So, typically the first connection is the one I really want to terminate.
Once you have determined the ID of the connection, you can call self.transport.pauseProducing() on the "new" connection's transport, which will prevent any notifications until you call self.transport.resumeProducing(). You can then call newConnection.transport.resumeProducing() from oldConnection.connectionLost(), if a new connection exists.

How do you handle newcomers efficiently in WebRTC signaling?

Signaling is not addressed by WebRTC (even if we do have JSEP as a starting point), but from what I understand, it works that way :
client tells the server it's available at X
server holds that information and maps it to an identifier
other client comes and sends an identifier to get connection information from the first client
other client uses it to create it's one connection information and sends it to the server
server sends this to first client
both client can now talk
This is all nice and well, but what happends if a 3rd client arrives ?
You have to redo the whole things. Which suppose the first two clients are STILL connected to the server, waiting for a 3rd client to signal itself, and start the exchanging process again so they can get the 3rd client connection information.
So does it mean you are required to have to sort of permanent link to the server for each client (long polling, websocket, etc) ? If yes, is there a way to do that efficiently ?
Cause I don't see the point of having webRTC if I have to setup nodejs or tornado and make it scales to the number of my users. It doesn't sound very p2pish to me.
Please tell me I missed something.
What about a chat system? Do you really need to keep a permanent link to the server for each client? Of course, because otherwise you have no way of keeping track of a user's status. This "permanent" link can be done different ways: you mentioned WebSocket and long polling, but simple periodic XHR polling works too (although this will affect the UX, depending on the interval).
So view it like a chat system, except that the media stream is P2P for reduced latency. Once a P2P WebRTC connection is established, the server may die and, of course, the P2P connection will be kept between the two clients. What I mean is: both users may always block your server once the P2P connection is established and still be connected together in the wild Internets.
Understand me well: once the P2P connection is established, your server will not be doing any more WebRTC signalling. The connection is only needed to keep track of the statuses.
So it depends on your application. If you want to keep the statuses of users and make them visible to others, then you're in the same situation as a chat system: you need to keep a certain link, somehow, to make sure their statuses are synced. Otherwise, your server exists to connect them together and is not needed afterwards. An example of the latter situation is: a user goes to a webpage, the webpage provides him with a new room URL, the user shares this URL to another peer by another mean, the other peer joins the room, server connects them together (manages WebRTC signalling) and then forgets them. They are now connected until one of them breaks the link. Just like this reference app.
Instead of a central server keeping one connection per client, a mesh network could also be considered, albeit difficult to implement.