Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

precalculating and encoding offer/answer in username/cred for stun/turn server #22

Open
unicomp21 opened this issue Oct 23, 2024 · 23 comments

Comments

@unicomp21
Copy link

I realize offer/answer for a datachannel can be handled via simple http request/response, but I'm hitting scenarios where this is cumbersome.

When only using datachannels, could it be possible to precompute the offer/answer in browser/javascript, and send this serded/encoded payload to violet via/piggbacked on the stun|turn login message? And then violet uses the browser/precalculated answer as it's own? I'm thinking a text encoding w/ length/prefixed delimiters would allow putting multiple fields in the username? (ie uname, password, offer sdp, answer sdp)

The goal is a quick/easy datachannel connection w/ the backend server which is running nodejs.

Have a good one! @paullouisageneau

@paullouisageneau
Copy link
Owner

I realize offer/answer for a datachannel can be handled via simple http request/response, but I'm hitting scenarios where this is cumbersome.

Yes indeed, actually the WHIP/WHEP protocols do this.

When only using datachannels, could it be possible to precompute the offer/answer in browser/javascript, and send this serded/encoded payload to violet via/piggbacked on the stun|turn login message? And then violet uses the browser/precalculated answer as it's own? I'm thinking a text encoding w/ length/prefixed delimiters would allow putting multiple fields in the username? (ie uname, password, offer sdp, answer sdp)

I don't really understand why you would do that, as the STUN/TURN server is distinct from your signaling server and remote WebRTC endpoint.

In practice it is not possible: to generate the full offer/answer description, you need local candidates, which are obtained from STUN and TURN servers. Therefore, you can't generate the description before sending a request to the STUN and TURN servers.

@unicomp21
Copy link
Author

STUN/TURN server is distinct from your signaling server and remote WebRTC endpoint.

What I'm suggesting is they all reside in the same app/process, specifically to achieve the goal described above.

@unicomp21
Copy link
Author

Does anything prevent building violet via emscripten? And running in the browser?

@paullouisageneau
Copy link
Owner

paullouisageneau commented Nov 6, 2024

Does anything prevent building violet via emscripten? And running in the browser?

It is not possible since there is no socket API access in the browser. Even if there was, the server would not be on the public Internet so it would be useless.

@unicomp21
Copy link
Author

Yes, true, but w/ the goal of calculating both offer/answer in the browser, serde'ing them into the logon message, and using the same offer/answer pair on the remote end (turn/stun/libdatachannel), might be a possible approach?

@paullouisageneau
Copy link
Owner

The only way to "precalculate" the remote answer is to know everything in advance, certificates, credentials, and ports (Note that it necessarily breaks security). Therefore, the transmission via the TURN username is useless, it is simpler to hack the server so it accepts any incoming peer connection with an approach similar to WebRTC direct.

@unicomp21
Copy link
Author

sorry, I'm confused, webrtc-direct works in browsers?

anyhow, think I've found a way? using a homegrown turn: server w/ short circuit built-in? server side issues the offer and disables fingerprint check for returned answer? then browser can establish datachannel/turn: to backend by simply providing a unique/uuid sessionid in the logon message? rest of sdp is a simple template for offer/answer?

@paullouisageneau
Copy link
Owner

sorry, I'm confused, webrtc-direct works in browsers?

Yes it does. You don't need exactly WebRTC direct for your use case, anything implementing the same principle would work, but my point is that the TURN server is useless.

@unicomp21
Copy link
Author

What about scenarios where browser is running behind symmetric nat? turn: server is still useless?

@paullouisageneau
Copy link
Owner

What about scenarios where browser is running behind symmetric nat? turn: server is still useless?

Yes it is useless. The server is open, so the client can always reach it (like it could reach the TURN server).

@unicomp21
Copy link
Author

Meaning udp can hole punch thru a symmetric nat?

---claude---
A TURN server is needed for symmetric NAT scenarios. In symmetric NAT, each outbound connection from the same internal IP:port gets mapped to a different external IP:port. This makes it impossible for peer-to-peer connections to work directly, requiring a TURN server to relay the traffic.

For asymmetric NAT (including full-cone, restricted-cone, and port-restricted cone NAT), STUN servers are usually sufficient since the NAT mapping remains consistent and predictable.

@paullouisageneau
Copy link
Owner

Meaning udp can hole punch thru a symmetric nat?

It is not even hole-punching in that case. The server is not behind a NAT. If the client can reach the server on its address and port, the server can reach the client following the reverse path. All client-server protocols rely on this, for instance DNS over UDP. NAT mapping type on client side has nothing to do with it.

@unicomp21
Copy link
Author

unicomp21 commented Nov 19, 2024

It is not even hole-punching in that case.

got it, thanks for setting me straight.

@unicomp21
Copy link
Author

is there a working impl somewhere for webrtc-direct w/ browser integ tests?

@paullouisageneau
Copy link
Owner

libp2p has different implementations with tests: libp2p/specs#412 Again, you don't need exactly WebRTC direct, only the same principle.

@unicomp21
Copy link
Author

unicomp21 commented Nov 19, 2024

if we are looking for IP support from browser (ie no www,https,turns etc.)

libp2p require webtransport? which is not available on ios/safari?

is this related?
murat-dogan/node-datachannel#256

@paullouisageneau
Copy link
Owner

if we are looking for IP support from browser (ie no www,https,turns etc.)

There is no socket API access in the browser.

libp2p require webtransport? which is not available on ios/safari?

No, libp2p uses WebRTC in browsers. That's the whole point of WebRTC direct.

is this related? murat-dogan/node-datachannel#256

This PR indeed exposes overrides that are needed to implement peer connections without signaling, for instance WebRTC direct.

@unicomp21
Copy link
Author

This PR indeed exposes overrides that are needed to implement peer connections without signaling, for instance WebRTC direct.

Which means there is not an existing impl yet? Which can do peer connections w/o signaling (ie browser -> server)?

@paullouisageneau
Copy link
Owner

Which means there is not an existing impl yet? Which can do peer connections w/o signaling (ie browser -> server)?

There is one in libp2p. For libdatachannel, you need to either hack it by yourself (hardcode what you need to be able to precalculate descriptions, ignore certificate validation, allow the server to receive connections, etc) or wait for the necessary overrides to be merged. Peer connections without signaling is not a use case WebRTC supports by default, you need to break a few things for it to work.

@unicomp21
Copy link
Author

unicomp21 commented Nov 20, 2024

Got it, thx! Does this look about right for the precalculated descriptions? When using libdatachannel w/ browser on other end?

const minimalOffer = {
  type: 'offer',
  sdp: 'v=0\r\n' +
    'o=- 0 0 IN IP4 127.0.0.1\r\n' +
    's=-\r\n' +
    't=0 0\r\n' +
    'a=ice-lite\r\n' +
    'm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n' +
    'c=IN IP4 0.0.0.0\r\n' +
    'a=ice-ufrag:lite\r\n' +
    'a=ice-pwd:lite\r\n' +
    'a=fingerprint:sha-256 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00\r\n' +
    'a=setup:actpass\r\n' +
    'a=mid:data\r\n' +
    'a=sctp-port:5000\r\n'
};

const minimalAnswer = {
  type: 'answer',
  sdp: 'v=0\r\n' +
    'o=- 0 0 IN IP4 127.0.0.1\r\n' +
    's=-\r\n' +
    't=0 0\r\n' +
    'm=application 9 UDP/DTLS/SCTP webrtc-datachannel\r\n' +
    'c=IN IP4 0.0.0.0\r\n' +
    'a=ice-ufrag:lite\r\n' +
    'a=ice-pwd:lite\r\n' +
    'a=fingerprint:sha-256 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00\r\n' +
    'a=setup:passive\r\n' +
    'a=mid:data\r\n' +
    'a=sctp-port:5000\r\n'
};

// need to support ios/safari and android/chrome

@paullouisageneau
Copy link
Owner

You can't set entirely dummy descriptions. You need at least a candidate on browser side so it can connect to the server. Also, you can't set an invalid fingerprint in the browser remote description because it will check the remote certificate.

@unicomp21
Copy link
Author

On a tangent, does libdatachannel use same cert/fingerprint across all peerconnections? Or does each pc get a new cert?

@paullouisageneau
Copy link
Owner

On a tangent, does libdatachannel use same cert/fingerprint across all peerconnections? Or does each pc get a new cert?

Peer connections with the same certificate type share the same certificate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants