Closed marten-seemann closed 5 years ago
Is this for the case when the server and client switch roles for a subsequent connection?
Is this for the case when the server and client switch roles for a subsequent connection?
Yes, exactly.
The handshake is asymmetric in QUIC, and tokens are sent only by a client during the handshake. At the moment, there's no mechanism by which a token sent by a client can be used by a server.
The handshake is asymmetric in QUIC, and tokens are sent only by a client during the handshake. At the moment, there's no mechanism by which a token sent by a client can be used by a server.
I don't want to change any of that. I'm just talking about the case where the two peers reconnect, this time with switched roles. In a p2p setting, this frequently occurs, and the terms "client" and "server" have little meaning beyond identifying who initiated the connection.
While I can understand the desire, I am wary of the complexity that it might introduce. I am not sure if we could consider (and continue to consider) the use-case during the development and the maintenance of the protocol.
Hence the question: how important is it? The only case you'd benefit a round trip from using a NEW_TOKEN token is when you can do 0-RTT. However, 0-RTT can only be used when a connection in the same direction has been established before. Considering that, I wonder what the benefit is.
While I can understand the desire, I am wary of the complexity that it might introduce. I am not sure if we could consider (and continue to consider) the use-case during the development and the maintenance of the protocol.
I don't think there's a lot of complexity here. The token is literally just an opaque blob which is transferred on one connection and reused on another connection. All the complexity of issuing, encrypting, validating and using the tokens is born by the implementations, and if p2p isn't your use case, you don't need to do anything.
The only case you'd benefit a round trip from using a NEW_TOKEN token is when you can do 0-RTT. However, 0-RTT can only be used when a connection in the same direction has been established before.
There are two benefits here, that apply even if you don't do 0-RTT:
I believe the server p2p case is important and a lot of work has been put into making QUIC symmetric.
Background: Symmetry breaks down naturally in the handshake where one is the initiator, and later in migration where only the client can migrate. The handshake is natural, and migration is simply cost-benefit. There are use cases for server migration in ICE client p2p configuration. For server p2p migration is not important which is probably why it was easily agreed to move that to v2.
Conclusion: symmetry is desirable when feasible, but not at all cost.
So, is the token symmetry worthwhile? In the sense that server p2p is, then maybe. In this configuration peers are expected to be fairly static, so an initial extra roundtrip is probably not that big of a deal when roles reverse. But for v2 it certainly makes sense to include.
There are other case like mesh networking where configuration is much more dynamic and is neither cilent p2p nor server p2p. Here saving a roundtrip could be valuable but it might not matter because when it becomes relevant to use such a token, the configuration might have moved on to new pairs of peers.
@marten-seemann
The token is literally just an opaque blob which is transferred on one connection and reused on another connection. All the complexity of issuing, encrypting, validating and using the tokens is born by the implementations, and if p2p isn't your use case, you don't need to do anything.
While I agree that tokens are just blobs, there are bunch of text explaining how a token is expected to be (or to not be) used, assuming that the roles between the endpoints do not change.
There are two benefits here, that apply even if you don't do 0-RTT:
- You save one round-trip for address validation.
The only difference will be the amount of 0.5-RTT data that the server can send. It's either 3 packets (without token) or more (with token, like 10 packets or the CWND remembered by the token). Regardless of the availability of the token, the server cannot send data that cannot be replayed, because until it cannot be certain that the Initial packets that it received came from a legitimate client until it receives a response from the client.
So it seems to me that there'd be some difference, the benefit depending on if P2P application protocols require the server to send several packets worth of data before receiving anything from the client, before validating the client's authenticity.
- You can encode additional information into the token. For example, an implementation could encode the RTT of the old connection into the token, and use that as an initial estimate when establishing a new connection.
I am not sure how much that is important, because in this scenario, the endpoint that is now acting as the client (i.e. the endpoint that offered the token) should have the knowledge of the RTT. Then, it would retransmit it's Initial at the correct moment, which would trigger the server to retransmit packets.
PS. At the moment, I do not have a reason to argue against symmetric NEW_TOKEN frames being proposed as a v1 extension.
I'm skeptical of the value of this change.
Any P2P application where the peers are end-user machines is unlikely to need NEW_TOKEN because it will need ICE or something similar for NAT hole punching and that already gives you a liveness check (as well as an RTT estimate) so you don't need NEW_TOKEN. So, this is then limited to P2P protocols where the peers are actually Internet servers that can adopt either role (e.g., SMTP). Those protocols generally don't seem to have super-high latency concerns, so this doesn't seem like it's going to add a lot of value.
I agree with Kazuho that it would be better to not do this in v1.
Chairs, my assessment is that this is design for sure and maybe quicv2 (on the basis that this isn't needed for h3).
When establishing a new connection, how a token was obtained doesn't play any role. Endpoints can distribute tokens by any way they want. NEW_TOKEN frames are just one way to do so, but tokens might as well be distributed out-of-band.
We made a lot of effort to make QUIC as symmetric as possible. The only exceptions are the 0-RTT feature of the handshake (we inherited this from TLS), and connection migration (which would cause a lot of corner cases). I don't understand why the NEW_TOKEN mechanism fits any of these criteria. Conceptionally, if at all, it seems to be less complexity to allow this frame in both directions.
@marten-seemann while I mostly agree, history suggests that there are subtle details to understand for even the most benign features so adding this not very important feature at this stage for the sake of symmetry may not be the best option. I'd like to see it in v2 though.
Here's how you might start to think about the problem:
Client: if I were a server, you could use this token (NEW_TOKEN) Server: if you were which server?
Proposal: quicv2.
Although we don't explicitly prohibit the client from sending NEW_TOKEN frames, the text strongly suggests that this frame is only sent by the server.
For the p2p use case, it would be valuable if the client could provide the server with tokens for future connections.