golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/version_test.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 7 package quic 8 9 import ( 10 "bytes" 11 "context" 12 "crypto/tls" 13 "testing" 14 ) 15 16 func TestVersionNegotiationServerReceivesUnknownVersion(t *testing.T) { 17 config := &Config{ 18 TLSConfig: newTestTLSConfig(serverSide), 19 } 20 te := newTestEndpoint(t, config) 21 22 // Packet of unknown contents for some unrecognized QUIC version. 23 dstConnID := []byte{1, 2, 3, 4} 24 srcConnID := []byte{5, 6, 7, 8} 25 pkt := []byte{ 26 0b1000_0000, 27 0x00, 0x00, 0x00, 0x0f, 28 } 29 pkt = append(pkt, byte(len(dstConnID))) 30 pkt = append(pkt, dstConnID...) 31 pkt = append(pkt, byte(len(srcConnID))) 32 pkt = append(pkt, srcConnID...) 33 for len(pkt) < paddedInitialDatagramSize { 34 pkt = append(pkt, 0) 35 } 36 37 te.write(&datagram{ 38 b: pkt, 39 }) 40 gotPkt := te.read() 41 if gotPkt == nil { 42 t.Fatalf("got no response; want Version Negotiation") 43 } 44 if got := getPacketType(gotPkt); got != packetTypeVersionNegotiation { 45 t.Fatalf("got packet type %v; want Version Negotiation", got) 46 } 47 gotDst, gotSrc, versions := parseVersionNegotiation(gotPkt) 48 if got, want := gotDst, srcConnID; !bytes.Equal(got, want) { 49 t.Errorf("got Destination Connection ID %x, want %x", got, want) 50 } 51 if got, want := gotSrc, dstConnID; !bytes.Equal(got, want) { 52 t.Errorf("got Source Connection ID %x, want %x", got, want) 53 } 54 if got, want := versions, []byte{0, 0, 0, 1}; !bytes.Equal(got, want) { 55 t.Errorf("got Supported Version %x, want %x", got, want) 56 } 57 } 58 59 func TestVersionNegotiationClientAborts(t *testing.T) { 60 tc := newTestConn(t, clientSide) 61 p := tc.readPacket() // client Initial packet 62 tc.endpoint.write(&datagram{ 63 b: appendVersionNegotiation(nil, p.srcConnID, p.dstConnID, 10), 64 }) 65 tc.wantIdle("connection does not send a CONNECTION_CLOSE") 66 if err := tc.conn.waitReady(canceledContext()); err != errVersionNegotiation { 67 t.Errorf("conn.waitReady() = %v, want errVersionNegotiation", err) 68 } 69 } 70 71 func TestVersionNegotiationClientIgnoresAfterProcessingPacket(t *testing.T) { 72 tc := newTestConn(t, clientSide) 73 tc.ignoreFrame(frameTypeAck) 74 p := tc.readPacket() // client Initial packet 75 tc.writeFrames(packetTypeInitial, 76 debugFrameCrypto{ 77 data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial], 78 }) 79 tc.endpoint.write(&datagram{ 80 b: appendVersionNegotiation(nil, p.srcConnID, p.dstConnID, 10), 81 }) 82 if err := tc.conn.waitReady(canceledContext()); err != context.Canceled { 83 t.Errorf("conn.waitReady() = %v, want context.Canceled", err) 84 } 85 tc.writeFrames(packetTypeHandshake, 86 debugFrameCrypto{ 87 data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake], 88 }) 89 tc.wantFrameType("conn ignores Version Negotiation and continues with handshake", 90 packetTypeHandshake, debugFrameCrypto{}) 91 } 92 93 func TestVersionNegotiationClientIgnoresMismatchingSourceConnID(t *testing.T) { 94 tc := newTestConn(t, clientSide) 95 tc.ignoreFrame(frameTypeAck) 96 p := tc.readPacket() // client Initial packet 97 tc.endpoint.write(&datagram{ 98 b: appendVersionNegotiation(nil, p.srcConnID, []byte("mismatch"), 10), 99 }) 100 tc.writeFrames(packetTypeInitial, 101 debugFrameCrypto{ 102 data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial], 103 }) 104 tc.writeFrames(packetTypeHandshake, 105 debugFrameCrypto{ 106 data: tc.cryptoDataIn[tls.QUICEncryptionLevelHandshake], 107 }) 108 tc.wantFrameType("conn ignores Version Negotiation and continues with handshake", 109 packetTypeHandshake, debugFrameCrypto{}) 110 }