forked from quic-go/quic-go
Merge pull request #1350 from lucas-clemente/split-packet-handling
split packet handling for gQUIC and IETF QUIC packets
This commit is contained in:
71
server.go
71
server.go
@@ -245,7 +245,7 @@ func (s *server) serve() {
|
||||
return
|
||||
}
|
||||
data = data[:n]
|
||||
if err := s.handlePacket(s.conn, remoteAddr, data); err != nil {
|
||||
if err := s.handlePacket(remoteAddr, data); err != nil {
|
||||
s.logger.Errorf("error handling packet: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -295,7 +295,7 @@ func (s *server) Addr() net.Addr {
|
||||
return s.conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet []byte) error {
|
||||
func (s *server) handlePacket(remoteAddr net.Addr, packet []byte) error {
|
||||
rcvTime := time.Now()
|
||||
|
||||
r := bytes.NewReader(packet)
|
||||
@@ -306,6 +306,13 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
|
||||
hdr.Raw = packet[:len(packet)-r.Len()]
|
||||
packetData := packet[len(packet)-r.Len():]
|
||||
|
||||
if hdr.IsPublicHeader {
|
||||
return s.handleGQUICPacket(hdr, packetData, remoteAddr, rcvTime)
|
||||
}
|
||||
return s.handleIETFQUICPacket(hdr, packetData, remoteAddr, rcvTime)
|
||||
}
|
||||
|
||||
func (s *server) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error {
|
||||
if hdr.IsLongHeader {
|
||||
if protocol.ByteCount(len(packetData)) < hdr.PayloadLen {
|
||||
return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(packetData), hdr.PayloadLen)
|
||||
@@ -325,6 +332,29 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
|
||||
session, sessionKnown := s.sessions[string(hdr.DestConnectionID)]
|
||||
s.sessionsMutex.RUnlock()
|
||||
|
||||
if sessionKnown && session == nil {
|
||||
// Late packet for closed session
|
||||
return nil
|
||||
}
|
||||
if !sessionKnown {
|
||||
s.logger.Debugf("Received %s packet for unknown connection %s.", hdr.Type, hdr.DestConnectionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
session.handlePacket(&receivedPacket{
|
||||
remoteAddr: remoteAddr,
|
||||
header: hdr,
|
||||
data: packetData,
|
||||
rcvTime: rcvTime,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) handleGQUICPacket(hdr *wire.Header, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error {
|
||||
s.sessionsMutex.RLock()
|
||||
session, sessionKnown := s.sessions[string(hdr.DestConnectionID)]
|
||||
s.sessionsMutex.RUnlock()
|
||||
|
||||
if sessionKnown && session == nil {
|
||||
// Late packet for closed session
|
||||
return nil
|
||||
@@ -332,25 +362,14 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
|
||||
|
||||
// ignore all Public Reset packets
|
||||
if hdr.ResetFlag {
|
||||
if sessionKnown {
|
||||
var pr *wire.PublicReset
|
||||
pr, err = wire.ParsePublicReset(r)
|
||||
if err != nil {
|
||||
s.logger.Infof("Received a Public Reset for connection %s. An error occurred parsing the packet.", hdr.DestConnectionID)
|
||||
} else {
|
||||
s.logger.Infof("Received a Public Reset for connection %s, rejected packet number: 0x%x.", hdr.DestConnectionID, pr.RejectedPacketNumber)
|
||||
}
|
||||
} else {
|
||||
s.logger.Infof("Received Public Reset for unknown connection %s.", hdr.DestConnectionID)
|
||||
}
|
||||
s.logger.Infof("Received unexpected Public Reset for connection %s.", hdr.DestConnectionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we don't have a session for this connection, and this packet cannot open a new connection, send a Public Reset
|
||||
// This should only happen after a server restart, when we still receive packets for connections that we lost the state for.
|
||||
// TODO(#943): implement sending of IETF draft style stateless resets
|
||||
if !sessionKnown && (!hdr.VersionFlag && hdr.Type != protocol.PacketTypeInitial) {
|
||||
_, err = pconn.WriteTo(wire.WritePublicReset(hdr.DestConnectionID, 0, 0), remoteAddr)
|
||||
if !sessionKnown && !hdr.VersionFlag {
|
||||
_, err := s.conn.WriteTo(wire.WritePublicReset(hdr.DestConnectionID, 0, 0), remoteAddr)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -365,29 +384,30 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
|
||||
// since the client send a Public Header (only gQUIC has a Version Flag), we need to send a gQUIC Version Negotiation Packet
|
||||
if hdr.VersionFlag && !protocol.IsSupportedVersion(s.config.Versions, hdr.Version) {
|
||||
// drop packets that are too small to be valid first packets
|
||||
if len(packet) < protocol.MinClientHelloSize+len(hdr.Raw) {
|
||||
if len(packetData) < protocol.MinClientHelloSize {
|
||||
return errors.New("dropping small packet with unknown version")
|
||||
}
|
||||
s.logger.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version)
|
||||
_, err := pconn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.SrcConnectionID, s.config.Versions), remoteAddr)
|
||||
_, err := s.conn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.SrcConnectionID, s.config.Versions), remoteAddr)
|
||||
return err
|
||||
}
|
||||
|
||||
// This is (potentially) a Client Hello.
|
||||
// Make sure it has the minimum required size before spending any more ressources on it.
|
||||
if !sessionKnown && len(packet) < protocol.MinClientHelloSize+len(hdr.Raw) {
|
||||
return errors.New("dropping small packet for unknown connection")
|
||||
}
|
||||
|
||||
if !sessionKnown {
|
||||
// This is (potentially) a Client Hello.
|
||||
// Make sure it has the minimum required size before spending any more ressources on it.
|
||||
if len(packetData) < protocol.MinClientHelloSize {
|
||||
return errors.New("dropping small packet for unknown connection")
|
||||
}
|
||||
|
||||
version := hdr.Version
|
||||
if !protocol.IsSupportedVersion(s.config.Versions, version) {
|
||||
return errors.New("Server BUG: negotiated version not supported")
|
||||
}
|
||||
|
||||
s.logger.Infof("Serving new connection: %s, version %s from %v", hdr.DestConnectionID, version, remoteAddr)
|
||||
var err error
|
||||
session, err = s.newSession(
|
||||
&conn{pconn: pconn, currentAddr: remoteAddr},
|
||||
&conn{pconn: s.conn, currentAddr: remoteAddr},
|
||||
version,
|
||||
hdr.DestConnectionID,
|
||||
s.scfg,
|
||||
@@ -404,6 +424,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
|
||||
|
||||
s.runHandshakeAndSession(session, hdr.DestConnectionID)
|
||||
}
|
||||
|
||||
session.handlePacket(&receivedPacket{
|
||||
remoteAddr: remoteAddr,
|
||||
header: hdr,
|
||||
|
||||
Reference in New Issue
Block a user