diff --git a/internal/quic/cmd/interop/main.go b/internal/quic/cmd/interop/main.go index 682cc772..6cc8e96a 100644 --- a/internal/quic/cmd/interop/main.go +++ b/internal/quic/cmd/interop/main.go @@ -114,7 +114,11 @@ func main() { case "resumption": // TODO case "retry": - // TODO + if *listen != "" && len(urls) == 0 { + config.RequireAddressValidation = true + } + basicTest(ctx, config, urls) + return case "versionnegotiation": // "The client should start a connection using // an unsupported version number [...]" diff --git a/quic/conn.go b/quic/conn.go index b9ec0e40..40bdddc2 100644 --- a/quic/conn.go +++ b/quic/conn.go @@ -67,7 +67,7 @@ type Conn struct { // connTestHooks override conn behavior in tests. type connTestHooks interface { // init is called after a conn is created. - init() + init(first bool) // nextMessage is called to request the next event from msgc. // Used to give tests control of the connection event loop. @@ -177,7 +177,7 @@ func newConn(now time.Time, side connSide, cids newServerConnIDs, peerHostname s } if c.testHooks != nil { - c.testHooks.init() + c.testHooks.init(true) } go c.loop(now) return c, nil diff --git a/quic/conn_recv.go b/quic/conn_recv.go index 2a7204c8..2bf127a4 100644 --- a/quic/conn_recv.go +++ b/quic/conn_recv.go @@ -208,10 +208,14 @@ func (c *Conn) handleRetry(now time.Time, pkt []byte) { } c.retryToken = cloneBytes(p.token) c.connIDState.handleRetryPacket(p.srcConnID) + c.keysInitial = initialKeys(p.srcConnID, c.side) // We need to resend any data we've already sent in Initial packets. // We must not reuse already sent packet numbers. c.loss.discardPackets(initialSpace, c.log, c.handleAckOrLoss) // TODO: Discard 0-RTT packets as well, once we support 0-RTT. + if c.testHooks != nil { + c.testHooks.init(false) + } } var errVersionNegotiation = errors.New("server does not support QUIC version 1") diff --git a/quic/conn_test.go b/quic/conn_test.go index 24af38ac..a5f2f611 100644 --- a/quic/conn_test.go +++ b/quic/conn_test.go @@ -1001,11 +1001,11 @@ func spaceForPacketType(ptype packetType) numberSpace { // testConnHooks implements connTestHooks. type testConnHooks testConn -func (tc *testConnHooks) init() { +func (tc *testConnHooks) init(first bool) { tc.conn.keysAppData.updateAfter = maxPacketNumber // disable key updates tc.keysInitial.r = tc.conn.keysInitial.w tc.keysInitial.w = tc.conn.keysInitial.r - if tc.conn.side == serverSide { + if first && tc.conn.side == serverSide { tc.endpoint.acceptQueue = append(tc.endpoint.acceptQueue, (*testConn)(tc)) } } diff --git a/quic/endpoint_test.go b/quic/endpoint_test.go index 98b8756d..7ec81395 100644 --- a/quic/endpoint_test.go +++ b/quic/endpoint_test.go @@ -22,6 +22,10 @@ func TestConnect(t *testing.T) { newLocalConnPair(t, &Config{}, &Config{}) } +func TestConnectRetry(t *testing.T) { + newLocalConnPair(t, &Config{RequireAddressValidation: true}, &Config{}) +} + func TestConnectDefaultTLSConfig(t *testing.T) { serverConfig := newTestTLSConfigWithMoreDefaults(serverSide) clientConfig := newTestTLSConfigWithMoreDefaults(clientSide)