ipfs-rust / ipfs-embed

A small embeddable ipfs implementation
352 stars 48 forks source link

nat traversal #5

Open dvc94ch opened 4 years ago

dvc94ch commented 4 years ago
mxinden commented 3 years ago

Probably best to follow https://github.com/libp2p/rust-libp2p/issues/2052 combining all efforts needed to bring hole punching to rust-libp2p.

dvc94ch commented 3 years ago

this issue is about implementing it in ipfs-embed. even once the components are in libp2p, they need to be hooked up and tested.

not really that bothered about upnp and sim-open is required when enabling port reuse anyway and since it's enabled unconditionally in ipfs-embed it's really a bug fix from the perspective of ipfs-embed.

dvc94ch commented 3 years ago

fyi the main reason we haven't enabled the relay yet is because it is incompatible with quic, it only supports tcp over tcp. does go-ipfs support using the relay for relaying quic connections? is that quic over tcp or quic over quic?

the problem with quic is that it implements a muxer, not a transport. so the relay would have to support relaying over a muxer to support quic as the transport.

when trying to relay quic over tcp the issue is that libp2p-quic binds to a udp socket. we'd need to support using relay stream instead of a socket.

dvc94ch commented 3 years ago

the other question is if the relay isn't too complicated. tcp and quic both handle retransmission at the endpoints, so the relay could loose packets and reduce the overhead of relaying. maybe the relay should support a lossy protocol over udp with less overhead. (and ideally this would be implemented in bpf completely bypassing the relay networking stack and libp2p)

mxinden commented 3 years ago

fyi the main reason we haven't enabled the relay yet is because it is incompatible with quic, it only supports tcp over tcp. does go-ipfs support using the relay for relaying quic connections? is that quic over tcp or quic over quic?

the problem with quic is that it implements a muxer, not a transport. so the relay would have to support relaying over a muxer to support quic as the transport.

when trying to relay quic over tcp the issue is that libp2p-quic binds to a udp socket. we'd need to support using relay stream instead of a socket.

True. One can not easily inject a relayed connection via QUIC. go-libp2p uses Noise and Yamux to upgrade the relayed connection detached from whether the transport of the actual connection is TCP or QUIC. In my eyes, rust-libp2p should do the same.

the other question is if the relay isn't too complicated. tcp and quic both handle retransmission at the endpoints, so the relay could loose packets and reduce the overhead of relaying. maybe the relay should support a lossy protocol over udp with less overhead. (and ideally this would be implemented in bpf completely bypassing the relay networking stack and libp2p)

Note: The circuit relay v1 and v2 never emulate TCP on top of TCP (or QUIC). The relayed stream is upgraded via the security and muxer protocol directly. Thus retransmission and flow control is only happening once, on the actual connection's transport protocol.

dvc94ch commented 3 years ago

well by tcp I sometimes mean tcp/noise/yamux when speaking in the libp2p context as those are generally expected to be used together and other than using tcp/noise/mplex there really aren't that many supported options. which is a great thing actually, this means we don't really need a transport trait for example and could fold them together. (let's face it tcp is here to stay and any new protocols on the horizon tend to handle these things for better efficiency. although in practice that is a bit less than tcp/noise/yamux due to context switches, lack of hardware offloading, unoptimized udp stack, etc.)

Thus retransmission and flow control is only happening once, on the actual connection's transport protocol.

well the relay reads from one tcp connection and writes it into another. so the relay does do those things. it may or may not be a bad thing, it certainly means that relaying a connection can't be implemented in bpf and will require more resources, and it means that dropping packets due to being overloaded or bandwidth limiting is quite expensive as it has to be handled in libp2p instead of directly in the kernel.