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

make it possible to run Dialer and Listener on the same UDP socket #561

Closed
marten-seemann opened this issue Apr 23, 2017 · 12 comments
Closed

Comments

@marten-seemann
Copy link
Member

Not sure yet how we can make this work, but it'd be a nice feature.

@lucas-clemente
Copy link
Member

I don't understand what you want to do here and why ^^

@AudriusButkevicius
Copy link
Contributor

AudriusButkevicius commented May 19, 2017

This would be useful for protocols that rely on stun for NAT punchthrough.

It would be awesome if this existed, yet it can be done outside of the library if quic framing is deterministic and sessions are easily identifiable with each Write() call.

We already do something simillar in syncthing and kcp where we have a single UDP connection and then filter incoming stun and KCP traffic based on the signatures into virtual connections using something like https://github.com/AudriusButkevicius/pfilter.

@marten-seemann
Copy link
Member Author

This will not be supported by QUIC v1, see quicwg/base-drafts#714 (comment).

@marten-seemann
Copy link
Member Author

Good news. It looks like with the current new QUIC header format, this will be possible.

@AudriusButkevicius
Copy link
Contributor

Superb! Are there plans to suppprt this feature in this implementation?

@marten-seemann
Copy link
Member Author

Sure, that's what this issue is there for ;)
I don't have a timeline yet though.

@AudriusButkevicius
Copy link
Contributor

Do you have an idea of what needs to be done to support this? Asking in case this is a low hanging fruit that I could contribute myself without having to refactor everything and learn quic spec by heart.

@marten-seemann
Copy link
Member Author

It's probably the most complicated issues we currently have.
I've been working on #1324, which is a subset of this issue, and I already spent two complete days refactoring stuff, and it's still a long way to go...

@AudriusButkevicius
Copy link
Contributor

AudriusButkevicius commented Jun 23, 2018

Given the multiplexer is now merged, would it be possible to reuse the multiplexer for mixing server and client sockets?

My idea is have a type exposed:

type Multiplexer interface {
     Accept() (Session, error)
     Dial(...) (Session, error)
     ReadFrom([]byte) (int, net.Addr, error)
     WriteTo([]byte, net.Addr) (int, error)
}

You'd pass in net.PacketConn to construct one of these.

It would work as follows:

  1. Dial normally registers the connection with the mux, and forward connections to the right session.
  2. Any valid quic packets sent for sessions the mux is not aware of, would go onto an Accept queue, which can be consumer by calling Accept(), at which point they would get registered with the mux. Not sure that everything that is needed for newsession is available at that point.
  3. Any non-quic packets would go on to the backlog channel, which can then be consumer by calling ReadFrom(), this way we can piggyback stun on the same net.PacketConn.

@marten-seemann
Copy link
Member Author

Header parsing is currently a mess, which is blocking this issue. There are just too many different header formats at the moment...
The cool thing is, we won't need any new API for this: You'll just pass the same packet conn to Dial and to Listen, and things will work automatically.

Regarding the additional ReadFrom call you're suggesting, I'm not sure if that's necessary. The IETF QUIC packet header was designed to allow demultiplexing of commonly used UDP based protocols, so in the most cases you can decide just by looking at the first byte of a packet if this is a QUIC packet or not. If you use a preallocated buffer for reading from the connection, this should be very cheap both in terms of allocations as well as packet processing. Or am I missing something?

@AudriusButkevicius
Copy link
Contributor

will work

I am trying to understand what is left to do to support this, as I suspect currently Listen part of the socket might read a packet which is meant to be delivered to a session that was acquired by Dial, essentially causing the packet to be dropped (or being interpreted as a new SYN)

@marten-seemann
Copy link
Member Author

Yes, that's the problem. We currently have a wire.ParseHeaderSentByServer and wire.ParseHeaderSentByClient, and these are required for parsing the gQUIC Public Header. If you want to have a server and a client on a packet conn, obviously you won't know who sent the packet in advance.

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

No branches or pull requests

3 participants