refactor packet handling functions in the client

This commit is contained in:
Marten Seemann 2018-05-21 12:01:55 +08:00
parent b3fd768a61
commit 97e734e973
2 changed files with 109 additions and 93 deletions

View file

@ -324,70 +324,84 @@ func (c *client) listen() {
} }
break break
} }
if err := c.handlePacket(addr, data[:n]); err != nil { c.handleRead(addr, data[:n])
c.logger.Errorf("error handling packet: %s", err.Error())
}
} }
} }
func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) error { func (c *client) handleRead(remoteAddr net.Addr, packet []byte) {
rcvTime := time.Now() rcvTime := time.Now()
r := bytes.NewReader(packet) r := bytes.NewReader(packet)
hdr, err := wire.ParseHeaderSentByServer(r) hdr, err := wire.ParseHeaderSentByServer(r)
// drop the packet if we can't parse the header // drop the packet if we can't parse the header
if err != nil { if err != nil {
return fmt.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error()) c.logger.Errorf("error handling packet: %s", err)
} return
// reject packets with truncated connection id if we didn't request truncation
if hdr.OmitConnectionID && !c.config.RequestConnectionIDOmission {
return errors.New("received packet with truncated connection ID, but didn't request truncation")
} }
hdr.Raw = packet[:len(packet)-r.Len()] hdr.Raw = packet[:len(packet)-r.Len()]
packetData := packet[len(packet)-r.Len():] packetData := packet[len(packet)-r.Len():]
c.handlePacket(&receivedPacket{
remoteAddr: remoteAddr,
header: hdr,
data: packetData,
rcvTime: rcvTime,
})
}
func (c *client) handlePacket(p *receivedPacket) {
if err := c.handlePacketImpl(p); err != nil {
c.logger.Errorf("error handling packet: %s", err)
}
}
func (c *client) handlePacketImpl(p *receivedPacket) error {
// reject packets with truncated connection id if we didn't request truncation
if p.header.OmitConnectionID && !c.config.RequestConnectionIDOmission {
return errors.New("received packet with truncated connection ID, but didn't request truncation")
}
c.mutex.Lock() c.mutex.Lock()
defer c.mutex.Unlock() defer c.mutex.Unlock()
// handle Version Negotiation Packets // handle Version Negotiation Packets
if hdr.IsVersionNegotiation { if p.header.IsVersionNegotiation {
// ignore delayed / duplicated version negotiation packets // ignore delayed / duplicated version negotiation packets
if c.receivedVersionNegotiationPacket || c.versionNegotiated { if c.receivedVersionNegotiationPacket || c.versionNegotiated {
return errors.New("received a delayed Version Negotiation Packet") return errors.New("received a delayed Version Negotiation Packet")
} }
// version negotiation packets have no payload // version negotiation packets have no payload
if err := c.handleVersionNegotiationPacket(hdr); err != nil { if err := c.handleVersionNegotiationPacket(p.header); err != nil {
c.session.Close(err) c.session.Close(err)
} }
return nil return nil
} }
if hdr.IsPublicHeader { if p.header.IsPublicHeader {
return c.handleGQUICPacket(hdr, r, packetData, remoteAddr, rcvTime) return c.handleGQUICPacket(p)
} }
return c.handleIETFQUICPacket(hdr, packetData, remoteAddr, rcvTime) return c.handleIETFQUICPacket(p)
} }
func (c *client) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error { func (c *client) handleIETFQUICPacket(p *receivedPacket) error {
// reject packets with the wrong connection ID // reject packets with the wrong connection ID
if !hdr.DestConnectionID.Equal(c.srcConnID) { if !p.header.DestConnectionID.Equal(c.srcConnID) {
return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", hdr.DestConnectionID, c.srcConnID) return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", p.header.DestConnectionID, c.srcConnID)
} }
if hdr.IsLongHeader { if p.header.IsLongHeader {
switch hdr.Type { switch p.header.Type {
case protocol.PacketTypeRetry: case protocol.PacketTypeRetry:
if c.receivedRetry { if c.receivedRetry {
return nil return nil
} }
case protocol.PacketTypeHandshake: case protocol.PacketTypeHandshake:
default: default:
return fmt.Errorf("Received unsupported packet type: %s", hdr.Type) return fmt.Errorf("Received unsupported packet type: %s", p.header.Type)
} }
if protocol.ByteCount(len(packetData)) < hdr.PayloadLen { if protocol.ByteCount(len(p.data)) < p.header.PayloadLen {
return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(packetData), hdr.PayloadLen) return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(p.data), p.header.PayloadLen)
} }
packetData = packetData[:int(hdr.PayloadLen)] p.data = p.data[:int(p.header.PayloadLen)]
// TODO(#1312): implement parsing of compound packets // TODO(#1312): implement parsing of compound packets
} }
@ -397,29 +411,24 @@ func (c *client) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remot
c.versionNegotiated = true c.versionNegotiated = true
} }
c.session.handlePacket(&receivedPacket{ c.session.handlePacket(p)
remoteAddr: remoteAddr,
header: hdr,
data: packetData,
rcvTime: rcvTime,
})
return nil return nil
} }
func (c *client) handleGQUICPacket(hdr *wire.Header, r *bytes.Reader, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error { func (c *client) handleGQUICPacket(p *receivedPacket) error {
// reject packets with the wrong connection ID // reject packets with the wrong connection ID
if !hdr.OmitConnectionID && !hdr.DestConnectionID.Equal(c.srcConnID) { if !p.header.OmitConnectionID && !p.header.DestConnectionID.Equal(c.srcConnID) {
return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", hdr.DestConnectionID, c.srcConnID) return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", p.header.DestConnectionID, c.srcConnID)
} }
if hdr.ResetFlag { if p.header.ResetFlag {
cr := c.conn.RemoteAddr() cr := c.conn.RemoteAddr()
// check if the remote address and the connection ID match // check if the remote address and the connection ID match
// otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection // otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || !hdr.DestConnectionID.Equal(c.srcConnID) { if cr.Network() != p.remoteAddr.Network() || cr.String() != p.remoteAddr.String() || !p.header.DestConnectionID.Equal(c.srcConnID) {
return errors.New("Received a spoofed Public Reset") return errors.New("Received a spoofed Public Reset")
} }
pr, err := wire.ParsePublicReset(r) pr, err := wire.ParsePublicReset(bytes.NewReader(p.data))
if err != nil { if err != nil {
return fmt.Errorf("Received a Public Reset. An error occurred parsing the packet: %s", err) return fmt.Errorf("Received a Public Reset. An error occurred parsing the packet: %s", err)
} }
@ -434,12 +443,7 @@ func (c *client) handleGQUICPacket(hdr *wire.Header, r *bytes.Reader, packetData
c.versionNegotiated = true c.versionNegotiated = true
} }
c.session.handlePacket(&receivedPacket{ c.session.handlePacket(p)
remoteAddr: remoteAddr,
header: hdr,
data: packetData,
rcvTime: rcvTime,
})
return nil return nil
} }

View file

@ -388,16 +388,13 @@ var _ = Describe("Client", func() {
sess := NewMockQuicSession(mockCtrl) sess := NewMockQuicSession(mockCtrl)
sess.EXPECT().handlePacket(gomock.Any()) sess.EXPECT().handlePacket(gomock.Any())
cl.session = sess cl.session = sess
ph := wire.Header{ ph := &wire.Header{
PacketNumber: 1, PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen2, PacketNumberLen: protocol.PacketNumberLen2,
DestConnectionID: connID, DestConnectionID: connID,
SrcConnectionID: connID, SrcConnectionID: connID,
} }
b := &bytes.Buffer{} err := cl.handlePacketImpl(&receivedPacket{header: ph})
err := ph.Write(b, protocol.PerspectiveServer, protocol.VersionWhatever)
Expect(err).ToNot(HaveOccurred())
err = cl.handlePacket(nil, b.Bytes())
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(cl.versionNegotiated).To(BeTrue()) Expect(cl.versionNegotiated).To(BeTrue())
}) })
@ -439,8 +436,7 @@ var _ = Describe("Client", func() {
close(dialed) close(dialed)
}() }()
Eventually(sessionChan).Should(HaveLen(1)) Eventually(sessionChan).Should(HaveLen(1))
err := cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{version2})) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{version2}))
Expect(err).ToNot(HaveOccurred())
Eventually(sessionChan).Should(BeEmpty()) Eventually(sessionChan).Should(BeEmpty())
}) })
@ -474,7 +470,7 @@ var _ = Describe("Client", func() {
return <-sessionChan, nil return <-sessionChan, nil
} }
cl.config = &Config{Versions: []protocol.VersionNumber{version1, version2}} cl.config = &Config{Versions: []protocol.VersionNumber{version1, version2, version3}}
dialed := make(chan struct{}) dialed := make(chan struct{})
go func() { go func() {
defer GinkgoRecover() defer GinkgoRecover()
@ -483,12 +479,12 @@ var _ = Describe("Client", func() {
close(dialed) close(dialed)
}() }()
Eventually(sessionChan).Should(HaveLen(1)) Eventually(sessionChan).Should(HaveLen(1))
err := cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{version2})) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{version2}))
Expect(err).ToNot(HaveOccurred())
Eventually(sessionChan).Should(BeEmpty()) Eventually(sessionChan).Should(BeEmpty())
err = cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{version3})) Expect(cl.version).To(Equal(version2))
Expect(err).To(MatchError("received a delayed Version Negotiation Packet")) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{version3}))
Eventually(dialed).Should(BeClosed()) Eventually(dialed).Should(BeClosed())
Expect(cl.version).To(Equal(version2))
}) })
It("errors if no matching version is found", func() { It("errors if no matching version is found", func() {
@ -496,8 +492,7 @@ var _ = Describe("Client", func() {
sess.EXPECT().Close(gomock.Any()) sess.EXPECT().Close(gomock.Any())
cl.session = sess cl.session = sess
cl.config = &Config{Versions: protocol.SupportedVersions} cl.config = &Config{Versions: protocol.SupportedVersions}
err := cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{1})) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{1}))
Expect(err).ToNot(HaveOccurred())
}) })
It("errors if the version is supported by quic-go, but disabled by the quic.Config", func() { It("errors if the version is supported by quic-go, but disabled by the quic.Config", func() {
@ -507,8 +502,7 @@ var _ = Describe("Client", func() {
v := protocol.VersionNumber(1234) v := protocol.VersionNumber(1234)
Expect(v).ToNot(Equal(cl.version)) Expect(v).ToNot(Equal(cl.version))
cl.config = &Config{Versions: protocol.SupportedVersions} cl.config = &Config{Versions: protocol.SupportedVersions}
err := cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{v})) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{v}))
Expect(err).ToNot(HaveOccurred())
}) })
It("changes to the version preferred by the quic.Config", func() { It("changes to the version preferred by the quic.Config", func() {
@ -517,15 +511,13 @@ var _ = Describe("Client", func() {
cl.session = sess cl.session = sess
config := &Config{Versions: []protocol.VersionNumber{1234, 4321}} config := &Config{Versions: []protocol.VersionNumber{1234, 4321}}
cl.config = config cl.config = config
err := cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{4321, 1234})) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{4321, 1234}))
Expect(err).ToNot(HaveOccurred())
Expect(cl.version).To(Equal(protocol.VersionNumber(1234))) Expect(cl.version).To(Equal(protocol.VersionNumber(1234)))
}) })
It("drops version negotiation packets that contain the offered version", func() { It("drops version negotiation packets that contain the offered version", func() {
ver := cl.version ver := cl.version
err := cl.handlePacket(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{ver})) cl.handleRead(nil, wire.ComposeGQUICVersionNegotiation(connID, []protocol.VersionNumber{ver}))
Expect(err).ToNot(HaveOccurred())
Expect(cl.version).To(Equal(ver)) Expect(cl.version).To(Equal(ver))
}) })
}) })
@ -533,14 +525,11 @@ var _ = Describe("Client", func() {
It("ignores packets with an invalid public header", func() { It("ignores packets with an invalid public header", func() {
cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls
err := cl.handlePacket(addr, []byte("invalid packet")) cl.handleRead(addr, []byte("invalid packet"))
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("error parsing packet from"))
}) })
It("errors on packets that are smaller than the Payload Length in the packet header", func() { It("errors on packets that are smaller than the Payload Length in the packet header", func() {
cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls
b := &bytes.Buffer{}
hdr := &wire.Header{ hdr := &wire.Header{
IsLongHeader: true, IsLongHeader: true,
Type: protocol.PacketTypeHandshake, Type: protocol.PacketTypeHandshake,
@ -550,8 +539,12 @@ var _ = Describe("Client", func() {
PacketNumberLen: protocol.PacketNumberLen1, PacketNumberLen: protocol.PacketNumberLen1,
Version: versionIETFFrames, Version: versionIETFFrames,
} }
Expect(hdr.Write(b, protocol.PerspectiveClient, versionIETFFrames)).To(Succeed()) err := cl.handlePacketImpl(&receivedPacket{
cl.handlePacket(addr, append(b.Bytes(), make([]byte, 456)...)) remoteAddr: addr,
header: hdr,
data: make([]byte, 456),
})
Expect(err).To(MatchError("received a packet with an unexpected connection ID (0x0102030405060708, expected 0x0000000000001337)"))
}) })
It("cuts packets at the payload length", func() { It("cuts packets at the payload length", func() {
@ -560,7 +553,6 @@ var _ = Describe("Client", func() {
Expect(packet.data).To(HaveLen(123)) Expect(packet.data).To(HaveLen(123))
}) })
cl.session = sess cl.session = sess
b := &bytes.Buffer{}
hdr := &wire.Header{ hdr := &wire.Header{
IsLongHeader: true, IsLongHeader: true,
Type: protocol.PacketTypeHandshake, Type: protocol.PacketTypeHandshake,
@ -570,13 +562,15 @@ var _ = Describe("Client", func() {
PacketNumberLen: protocol.PacketNumberLen1, PacketNumberLen: protocol.PacketNumberLen1,
Version: versionIETFFrames, Version: versionIETFFrames,
} }
Expect(hdr.Write(b, protocol.PerspectiveClient, versionIETFFrames)).To(Succeed()) err := cl.handlePacketImpl(&receivedPacket{
err := cl.handlePacket(addr, append(b.Bytes(), make([]byte, 456)...)) remoteAddr: addr,
header: hdr,
data: make([]byte, 456),
})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
}) })
It("ignores packets with the wrong Long Header Type", func() { It("ignores packets with the wrong Long Header Type", func() {
b := &bytes.Buffer{}
hdr := &wire.Header{ hdr := &wire.Header{
IsLongHeader: true, IsLongHeader: true,
Type: protocol.PacketTypeInitial, Type: protocol.PacketTypeInitial,
@ -586,43 +580,48 @@ var _ = Describe("Client", func() {
PacketNumberLen: protocol.PacketNumberLen1, PacketNumberLen: protocol.PacketNumberLen1,
Version: versionIETFFrames, Version: versionIETFFrames,
} }
Expect(hdr.Write(b, protocol.PerspectiveServer, versionIETFFrames)).To(Succeed()) err := cl.handlePacketImpl(&receivedPacket{
err := cl.handlePacket(addr, append(b.Bytes(), make([]byte, 456)...)) remoteAddr: addr,
header: hdr,
data: make([]byte, 456),
})
Expect(err).To(MatchError("Received unsupported packet type: Initial")) Expect(err).To(MatchError("Received unsupported packet type: Initial"))
}) })
It("ignores packets without connection id, if it didn't request connection id trunctation", func() { It("ignores packets without connection id, if it didn't request connection id trunctation", func() {
cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls
cl.config = &Config{RequestConnectionIDOmission: false} cl.config = &Config{RequestConnectionIDOmission: false}
buf := &bytes.Buffer{} hdr := &wire.Header{
err := (&wire.Header{
OmitConnectionID: true, OmitConnectionID: true,
SrcConnectionID: connID, SrcConnectionID: connID,
DestConnectionID: connID, DestConnectionID: connID,
PacketNumber: 1, PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen1, PacketNumberLen: 1,
}).Write(buf, protocol.PerspectiveServer, versionGQUICFrames) }
Expect(err).ToNot(HaveOccurred()) err := cl.handlePacketImpl(&receivedPacket{
err = cl.handlePacket(addr, buf.Bytes()) remoteAddr: addr,
header: hdr,
})
Expect(err).To(MatchError("received packet with truncated connection ID, but didn't request truncation")) Expect(err).To(MatchError("received packet with truncated connection ID, but didn't request truncation"))
}) })
It("ignores packets with the wrong destination connection ID", func() { It("ignores packets with the wrong destination connection ID", func() {
cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any handlePacket calls
buf := &bytes.Buffer{}
cl.version = versionIETFFrames cl.version = versionIETFFrames
cl.config = &Config{RequestConnectionIDOmission: false} cl.config = &Config{RequestConnectionIDOmission: false}
connID2 := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1} connID2 := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
Expect(connID).ToNot(Equal(connID2)) Expect(connID).ToNot(Equal(connID2))
err := (&wire.Header{ hdr := &wire.Header{
DestConnectionID: connID2, DestConnectionID: connID2,
SrcConnectionID: connID, SrcConnectionID: connID,
PacketNumber: 1, PacketNumber: 1,
PacketNumberLen: protocol.PacketNumberLen1, PacketNumberLen: protocol.PacketNumberLen1,
Version: versionIETFFrames, Version: versionIETFFrames,
}).Write(buf, protocol.PerspectiveServer, versionIETFFrames) }
Expect(err).ToNot(HaveOccurred()) err := cl.handlePacketImpl(&receivedPacket{
err = cl.handlePacket(addr, buf.Bytes()) remoteAddr: addr,
header: hdr,
})
Expect(err).To(MatchError(fmt.Sprintf("received a packet with an unexpected connection ID (0x0807060504030201, expected %s)", connID))) Expect(err).To(MatchError(fmt.Sprintf("received a packet with an unexpected connection ID (0x0807060504030201, expected %s)", connID)))
}) })
@ -695,13 +694,13 @@ var _ = Describe("Client", func() {
It("only accepts one Retry packet", func() { It("only accepts one Retry packet", func() {
config := &Config{Versions: []protocol.VersionNumber{protocol.VersionTLS}} config := &Config{Versions: []protocol.VersionNumber{protocol.VersionTLS}}
sess1 := NewMockPacketHandler(mockCtrl) sess1 := NewMockQuicSession(mockCtrl)
sess1.EXPECT().run().Return(handshake.ErrCloseSessionForRetry) sess1.EXPECT().run().Return(handshake.ErrCloseSessionForRetry)
// don't EXPECT any call to handlePacket() // don't EXPECT any call to handlePacket()
sess2 := NewMockPacketHandler(mockCtrl) sess2 := NewMockQuicSession(mockCtrl)
run := make(chan struct{}) run := make(chan struct{})
sess2.EXPECT().run().Do(func() { <-run }) sess2.EXPECT().run().Do(func() { <-run })
sessions := make(chan *MockPacketHandler, 2) sessions := make(chan *MockQuicSession, 2)
sessions <- sess1 sessions <- sess1
sessions <- sess2 sessions <- sess2
newTLSClientSession = func( newTLSClientSession = func(
@ -716,7 +715,7 @@ var _ = Describe("Client", func() {
paramsChan <-chan handshake.TransportParameters, paramsChan <-chan handshake.TransportParameters,
_ protocol.PacketNumber, _ protocol.PacketNumber,
_ utils.Logger, _ utils.Logger,
) (packetHandler, error) { ) (quicSession, error) {
return <-sessions, nil return <-sessions, nil
} }
@ -795,22 +794,35 @@ var _ = Describe("Client", func() {
Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.PublicReset)) Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.PublicReset))
}) })
cl.session = sess cl.session = sess
err := cl.handlePacket(addr, wire.WritePublicReset(cl.destConnID, 1, 0)) cl.handleRead(addr, wire.WritePublicReset(cl.destConnID, 1, 0))
Expect(err).ToNot(HaveOccurred())
}) })
It("ignores Public Resets from the wrong remote address", func() { It("ignores Public Resets from the wrong remote address", func() {
cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any calls cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any calls
spoofedAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 5678} spoofedAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 5678}
err := cl.handlePacket(spoofedAddr, wire.WritePublicReset(cl.destConnID, 1, 0)) pr := wire.WritePublicReset(cl.destConnID, 1, 0)
r := bytes.NewReader(pr)
hdr, err := wire.ParseHeaderSentByServer(r)
Expect(err).ToNot(HaveOccurred())
err = cl.handlePacketImpl(&receivedPacket{
remoteAddr: spoofedAddr,
header: hdr,
data: pr[len(pr)-r.Len():],
})
Expect(err).To(MatchError("Received a spoofed Public Reset")) Expect(err).To(MatchError("Received a spoofed Public Reset"))
}) })
It("ignores unparseable Public Resets", func() { It("ignores unparseable Public Resets", func() {
cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any calls cl.session = NewMockQuicSession(mockCtrl) // don't EXPECT any calls
pr := wire.WritePublicReset(cl.destConnID, 1, 0) pr := wire.WritePublicReset(cl.destConnID, 1, 0)
err := cl.handlePacket(addr, pr[:len(pr)-5]) r := bytes.NewReader(pr)
Expect(err).To(HaveOccurred()) hdr, err := wire.ParseHeaderSentByServer(r)
Expect(err).ToNot(HaveOccurred())
err = cl.handlePacketImpl(&receivedPacket{
remoteAddr: addr,
header: hdr,
data: pr[len(pr)-r.Len() : len(pr)-5], // cut off the last 5 bytes
})
Expect(err.Error()).To(ContainSubstring("Received a Public Reset. An error occurred parsing the packet")) Expect(err.Error()).To(ContainSubstring("Received a Public Reset. An error occurred parsing the packet"))
}) })
}) })