Skip to content

Commit

Permalink
only check for stateless resets if packet doesn't belong to a connect…
Browse files Browse the repository at this point in the history
…ion (#4322)

This technically violates the stateless reset handling logic described
in RFC 9000 section 10.3.1 (see comment), but it saves one map lookup in
the hot path.
  • Loading branch information
marten-seemann committed Feb 9, 2024
1 parent 02e4506 commit 4790797
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 6 deletions.
14 changes: 11 additions & 3 deletions transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,13 +426,21 @@ func (t *Transport) handlePacket(p receivedPacket) {
return
}

if isStatelessReset := t.maybeHandleStatelessReset(p.data); isStatelessReset {
return
}
// If there's a connection associated with the connection ID, pass the packet there.
if handler, ok := t.handlerMap.Get(connID); ok {
handler.handlePacket(p)
return
}
// RFC 9000 section 10.3.1 requires that the stateless reset detection logic is run for both
// packets that cannot be associated with any connections, and for packets that can't be decrypted.
// We deviate from the RFC and ignore the latter: If a packet's connection ID is associated with an
// existing connection, it is dropped there if if it can't be decrypted.
// Stateless resets use random connection IDs, and at reasonable connection ID lengths collisions are
// exceedingly rare. In the unlikely event that a stateless reset is misrouted to an existing connection,
// it is to be expected that the next stateless reset will be correctly detected.
if isStatelessReset := t.maybeHandleStatelessReset(p.data); isStatelessReset {
return
}
if !wire.IsLongHeaderPacket(p.data[0]) {
t.maybeSendStatelessReset(p)
return
Expand Down
9 changes: 6 additions & 3 deletions transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ var _ = Describe("Transport", func() {
b = append(b, token[:]...)
conn := NewMockPacketHandler(mockCtrl)
gomock.InOrder(
phm.EXPECT().GetByResetToken(token),
phm.EXPECT().Get(connID).Return(conn, true),
conn.EXPECT().handlePacket(gomock.Any()).Do(func(p receivedPacket) {
Expect(p.data).To(Equal(b))
Expand All @@ -223,7 +222,10 @@ var _ = Describe("Transport", func() {
It("handles stateless resets", func() {
connID := protocol.ParseConnectionID([]byte{2, 3, 4, 5})
packetChan := make(chan packetToRead)
tr := Transport{Conn: newMockPacketConn(packetChan)}
tr := Transport{
Conn: newMockPacketConn(packetChan),
ConnectionIDLength: connID.Len(),
}
tr.init(true)
defer tr.Close()
phm := NewMockPacketHandlerManager(mockCtrl)
Expand All @@ -239,6 +241,7 @@ var _ = Describe("Transport", func() {
conn := NewMockPacketHandler(mockCtrl)
destroyed := make(chan struct{})
gomock.InOrder(
phm.EXPECT().Get(connID),
phm.EXPECT().GetByResetToken(token).Return(conn, true),
conn.EXPECT().destroy(gomock.Any()).Do(func(err error) {
Expect(err).To(MatchError(&StatelessResetError{Token: token}))
Expand Down Expand Up @@ -277,8 +280,8 @@ var _ = Describe("Transport", func() {
rand.Read(token[:])
written := make(chan struct{})
gomock.InOrder(
phm.EXPECT().GetByResetToken(gomock.Any()),
phm.EXPECT().Get(connID),
phm.EXPECT().GetByResetToken(gomock.Any()),
phm.EXPECT().GetStatelessResetToken(connID).Return(token),
conn.EXPECT().WriteTo(gomock.Any(), gomock.Any()).Do(func(b []byte, _ net.Addr) (int, error) {
defer close(written)
Expand Down

0 comments on commit 4790797

Please sign in to comment.