fix application bug
This commit is contained in:
395
vendor/github.com/lucas-clemente/quic-go/server.go
generated
vendored
395
vendor/github.com/lucas-clemente/quic-go/server.go
generated
vendored
@@ -1,17 +1,19 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/crypto"
|
||||
"github.com/lucas-clemente/quic-go/internal/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
)
|
||||
@@ -21,8 +23,7 @@ type packetHandler interface {
|
||||
handlePacket(*receivedPacket)
|
||||
io.Closer
|
||||
destroy(error)
|
||||
GetVersion() protocol.VersionNumber
|
||||
GetPerspective() protocol.Perspective
|
||||
getPerspective() protocol.Perspective
|
||||
}
|
||||
|
||||
type unknownPacketHandler interface {
|
||||
@@ -31,9 +32,14 @@ type unknownPacketHandler interface {
|
||||
}
|
||||
|
||||
type packetHandlerManager interface {
|
||||
io.Closer
|
||||
Add(protocol.ConnectionID, packetHandler)
|
||||
SetServer(unknownPacketHandler)
|
||||
Retire(protocol.ConnectionID)
|
||||
Remove(protocol.ConnectionID)
|
||||
AddResetToken([16]byte, packetHandler)
|
||||
RemoveResetToken([16]byte)
|
||||
GetStatelessResetToken(protocol.ConnectionID) [16]byte
|
||||
SetServer(unknownPacketHandler)
|
||||
CloseServer()
|
||||
}
|
||||
|
||||
@@ -41,23 +47,28 @@ type quicSession interface {
|
||||
Session
|
||||
handlePacket(*receivedPacket)
|
||||
GetVersion() protocol.VersionNumber
|
||||
getPerspective() protocol.Perspective
|
||||
run() error
|
||||
destroy(error)
|
||||
closeForRecreating() protocol.PacketNumber
|
||||
closeRemote(error)
|
||||
}
|
||||
|
||||
type sessionRunner interface {
|
||||
onHandshakeComplete(Session)
|
||||
removeConnectionID(protocol.ConnectionID)
|
||||
OnHandshakeComplete(Session)
|
||||
Retire(protocol.ConnectionID)
|
||||
Remove(protocol.ConnectionID)
|
||||
AddResetToken([16]byte, packetHandler)
|
||||
RemoveResetToken([16]byte)
|
||||
}
|
||||
|
||||
type runner struct {
|
||||
packetHandlerManager
|
||||
|
||||
onHandshakeCompleteImpl func(Session)
|
||||
removeConnectionIDImpl func(protocol.ConnectionID)
|
||||
}
|
||||
|
||||
func (r *runner) onHandshakeComplete(s Session) { r.onHandshakeCompleteImpl(s) }
|
||||
func (r *runner) removeConnectionID(c protocol.ConnectionID) { r.removeConnectionIDImpl(c) }
|
||||
func (r *runner) OnHandshakeComplete(s Session) { r.onHandshakeCompleteImpl(s) }
|
||||
|
||||
var _ sessionRunner = &runner{}
|
||||
|
||||
@@ -73,23 +84,21 @@ type server struct {
|
||||
// If it is started with Listen, we take a packet conn as a parameter.
|
||||
createdPacketConn bool
|
||||
|
||||
supportsTLS bool
|
||||
serverTLS *serverTLS
|
||||
|
||||
certChain crypto.CertChain
|
||||
scfg *handshake.ServerConfig
|
||||
cookieGenerator *handshake.CookieGenerator
|
||||
|
||||
sessionHandler packetHandlerManager
|
||||
|
||||
// set as a member, so they can be set in the tests
|
||||
newSession func(connection, sessionRunner, protocol.ConnectionID /* original connection ID */, protocol.ConnectionID /* destination connection ID */, protocol.ConnectionID /* source connection ID */, *Config, *tls.Config, *handshake.TransportParameters, utils.Logger, protocol.VersionNumber) (quicSession, error)
|
||||
|
||||
serverError error
|
||||
errorChan chan struct{}
|
||||
closed bool
|
||||
|
||||
sessionQueue chan Session
|
||||
sessionQueue chan Session
|
||||
sessionQueueLen int32 // to be used as an atomic
|
||||
|
||||
sessionRunner sessionRunner
|
||||
// set as a member, so they can be set in the tests
|
||||
newSession func(connection, sessionRunner, protocol.VersionNumber, protocol.ConnectionID, protocol.ConnectionID, *handshake.ServerConfig, *tls.Config, *Config, utils.Logger) (quicSession, error)
|
||||
|
||||
logger utils.Logger
|
||||
}
|
||||
@@ -98,7 +107,8 @@ var _ Listener = &server{}
|
||||
var _ unknownPacketHandler = &server{}
|
||||
|
||||
// ListenAddr creates a QUIC server listening on a given address.
|
||||
// The tls.Config must not be nil, the quic.Config may be nil.
|
||||
// The tls.Config must not be nil and must contain a certificate configuration.
|
||||
// The quic.Config may be nil, in that case the default values will be used.
|
||||
func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (Listener, error) {
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
@@ -117,39 +127,28 @@ func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (Listener, err
|
||||
}
|
||||
|
||||
// Listen listens for QUIC connections on a given net.PacketConn.
|
||||
// The tls.Config must not be nil, the quic.Config may be nil.
|
||||
// A single PacketConn only be used for a single call to Listen.
|
||||
// The PacketConn can be used for simultaneous calls to Dial.
|
||||
// QUIC connection IDs are used for demultiplexing the different connections.
|
||||
// The tls.Config must not be nil and must contain a certificate configuration.
|
||||
// The quic.Config may be nil, in that case the default values will be used.
|
||||
func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, error) {
|
||||
return listen(conn, tlsConf, config)
|
||||
}
|
||||
|
||||
func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*server, error) {
|
||||
if tlsConf == nil || (len(tlsConf.Certificates) == 0 && tlsConf.GetCertificate == nil) {
|
||||
return nil, errors.New("quic: neither Certificates nor GetCertificate set in tls.Config")
|
||||
}
|
||||
certChain := crypto.NewCertChain(tlsConf)
|
||||
kex, err := crypto.NewCurve25519KEX()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scfg, err := handshake.NewServerConfig(kex, certChain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// TODO(#1655): only require that tls.Config.Certificates or tls.Config.GetCertificate is set
|
||||
if tlsConf == nil || len(tlsConf.Certificates) == 0 {
|
||||
return nil, errors.New("quic: Certificates not set in tls.Config")
|
||||
}
|
||||
config = populateServerConfig(config)
|
||||
|
||||
var supportsTLS bool
|
||||
for _, v := range config.Versions {
|
||||
if !protocol.IsValidVersion(v) {
|
||||
return nil, fmt.Errorf("%s is not a valid QUIC version", v)
|
||||
}
|
||||
// check if any of the supported versions supports TLS
|
||||
if v.UsesTLS() {
|
||||
supportsTLS = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
sessionHandler, err := getMultiplexer().AddConn(conn, config.ConnectionIDLength)
|
||||
sessionHandler, err := getMultiplexer().AddConn(conn, config.ConnectionIDLength, config.StatelessResetKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -157,53 +156,41 @@ func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*server,
|
||||
conn: conn,
|
||||
tlsConf: tlsConf,
|
||||
config: config,
|
||||
certChain: certChain,
|
||||
scfg: scfg,
|
||||
newSession: newSession,
|
||||
sessionHandler: sessionHandler,
|
||||
sessionQueue: make(chan Session, 5),
|
||||
sessionQueue: make(chan Session),
|
||||
errorChan: make(chan struct{}),
|
||||
supportsTLS: supportsTLS,
|
||||
newSession: newSession,
|
||||
logger: utils.DefaultLogger.WithPrefix("server"),
|
||||
}
|
||||
s.setup()
|
||||
if supportsTLS {
|
||||
if err := s.setupTLS(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.setup(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessionHandler.SetServer(s)
|
||||
s.logger.Debugf("Listening for %s connections on %s", conn.LocalAddr().Network(), conn.LocalAddr().String())
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *server) setup() {
|
||||
func (s *server) setup() error {
|
||||
s.sessionRunner = &runner{
|
||||
onHandshakeCompleteImpl: func(sess Session) { s.sessionQueue <- sess },
|
||||
removeConnectionIDImpl: s.sessionHandler.Remove,
|
||||
packetHandlerManager: s.sessionHandler,
|
||||
onHandshakeCompleteImpl: func(sess Session) {
|
||||
go func() {
|
||||
atomic.AddInt32(&s.sessionQueueLen, 1)
|
||||
defer atomic.AddInt32(&s.sessionQueueLen, -1)
|
||||
select {
|
||||
case s.sessionQueue <- sess:
|
||||
// blocks until the session is accepted
|
||||
case <-sess.Context().Done():
|
||||
// don't pass sessions that were already closed to Accept()
|
||||
}
|
||||
}()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) setupTLS() error {
|
||||
serverTLS, sessionChan, err := newServerTLS(s.conn, s.config, s.sessionRunner, s.tlsConf, s.logger)
|
||||
cookieGenerator, err := handshake.NewCookieGenerator()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.serverTLS = serverTLS
|
||||
// handle TLS connection establishment statelessly
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-s.errorChan:
|
||||
return
|
||||
case tlsSession := <-sessionChan:
|
||||
// The connection ID is a randomly chosen value.
|
||||
// It is safe to assume that it doesn't collide with other randomly chosen values.
|
||||
serverSession := newServerSession(tlsSession.sess, s.config, s.logger)
|
||||
s.sessionHandler.Add(tlsSession.connID, serverSession)
|
||||
}
|
||||
}
|
||||
}()
|
||||
s.cookieGenerator = cookieGenerator
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -250,11 +237,11 @@ func populateServerConfig(config *Config) *Config {
|
||||
|
||||
maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
|
||||
if maxReceiveStreamFlowControlWindow == 0 {
|
||||
maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowServer
|
||||
maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindow
|
||||
}
|
||||
maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
|
||||
if maxReceiveConnectionFlowControlWindow == 0 {
|
||||
maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowServer
|
||||
maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindow
|
||||
}
|
||||
maxIncomingStreams := config.MaxIncomingStreams
|
||||
if maxIncomingStreams == 0 {
|
||||
@@ -272,11 +259,6 @@ func populateServerConfig(config *Config) *Config {
|
||||
if connIDLen == 0 {
|
||||
connIDLen = protocol.DefaultConnectionIDLength
|
||||
}
|
||||
for _, v := range versions {
|
||||
if v == protocol.Version44 {
|
||||
connIDLen = protocol.ConnectionIDLenGQUIC
|
||||
}
|
||||
}
|
||||
|
||||
return &Config{
|
||||
Versions: versions,
|
||||
@@ -289,6 +271,7 @@ func populateServerConfig(config *Config) *Config {
|
||||
MaxIncomingStreams: maxIncomingStreams,
|
||||
MaxIncomingUniStreams: maxIncomingUniStreams,
|
||||
ConnectionIDLength: connIDLen,
|
||||
StatelessResetKey: config.StatelessResetKey,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +305,7 @@ func (s *server) closeWithMutex() error {
|
||||
// If the server was started with ListenAddr, we created the packet conn.
|
||||
// We need to close it in order to make the go routine reading from that conn return.
|
||||
if s.createdPacketConn {
|
||||
err = s.conn.Close()
|
||||
err = s.sessionHandler.Close()
|
||||
}
|
||||
s.closed = true
|
||||
close(s.errorChan)
|
||||
@@ -345,79 +328,231 @@ func (s *server) Addr() net.Addr {
|
||||
}
|
||||
|
||||
func (s *server) handlePacket(p *receivedPacket) {
|
||||
if err := s.handlePacketImpl(p); err != nil {
|
||||
s.logger.Debugf("error handling packet from %s: %s", p.remoteAddr, err)
|
||||
}
|
||||
go func() {
|
||||
if shouldReleaseBuffer := s.handlePacketImpl(p); !shouldReleaseBuffer {
|
||||
p.buffer.Release()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *server) handlePacketImpl(p *receivedPacket) error {
|
||||
hdr := p.header
|
||||
func (s *server) handlePacketImpl(p *receivedPacket) bool /* was the packet passed on to a session */ {
|
||||
if len(p.data) < protocol.MinInitialPacketSize {
|
||||
s.logger.Debugf("Dropping a packet that is too small to be a valid Initial (%d bytes)", len(p.data))
|
||||
return false
|
||||
}
|
||||
// If we're creating a new session, the packet will be passed to the session.
|
||||
// The header will then be parsed again.
|
||||
hdr, _, _, err := wire.ParsePacket(p.data, s.config.ConnectionIDLength)
|
||||
if err != nil {
|
||||
s.logger.Debugf("Error parsing packet: %s", err)
|
||||
return false
|
||||
}
|
||||
// Short header packets should never end up here in the first place
|
||||
if !hdr.IsLongHeader {
|
||||
return false
|
||||
}
|
||||
// send a Version Negotiation Packet if the client is speaking a different protocol version
|
||||
if !protocol.IsSupportedVersion(s.config.Versions, hdr.Version) {
|
||||
s.sendVersionNegotiationPacket(p, hdr)
|
||||
return false
|
||||
}
|
||||
if hdr.IsLongHeader && hdr.Type != protocol.PacketTypeInitial {
|
||||
// Drop long header packets.
|
||||
// There's litte point in sending a Stateless Reset, since the client
|
||||
// might not have received the token yet.
|
||||
return false
|
||||
}
|
||||
|
||||
if hdr.VersionFlag || hdr.IsLongHeader {
|
||||
// send a Version Negotiation Packet if the client is speaking a different protocol version
|
||||
if !protocol.IsSupportedVersion(s.config.Versions, hdr.Version) {
|
||||
return s.sendVersionNegotiationPacket(p)
|
||||
s.logger.Debugf("<- Received Initial packet.")
|
||||
|
||||
sess, connID, err := s.handleInitialImpl(p, hdr)
|
||||
if err != nil {
|
||||
s.logger.Errorf("Error occurred handling initial packet: %s", err)
|
||||
return false
|
||||
}
|
||||
if sess == nil { // a retry was done, or the connection attempt was rejected
|
||||
return false
|
||||
}
|
||||
// Don't put the packet buffer back if a new session was created.
|
||||
// The session will handle the packet and take of that.
|
||||
s.sessionHandler.Add(connID, sess)
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *server) handleInitialImpl(p *receivedPacket, hdr *wire.Header) (quicSession, protocol.ConnectionID, error) {
|
||||
if len(hdr.Token) == 0 && hdr.DestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
|
||||
return nil, nil, errors.New("too short connection ID")
|
||||
}
|
||||
|
||||
var cookie *Cookie
|
||||
var origDestConnectionID protocol.ConnectionID
|
||||
if len(hdr.Token) > 0 {
|
||||
c, err := s.cookieGenerator.DecodeToken(hdr.Token)
|
||||
if err == nil {
|
||||
cookie = &Cookie{
|
||||
RemoteAddr: c.RemoteAddr,
|
||||
SentTime: c.SentTime,
|
||||
}
|
||||
origDestConnectionID = c.OriginalDestConnectionID
|
||||
}
|
||||
}
|
||||
if hdr.Type == protocol.PacketTypeInitial && hdr.Version.UsesTLS() {
|
||||
go s.serverTLS.HandleInitial(p)
|
||||
return nil
|
||||
if !s.config.AcceptCookie(p.remoteAddr, cookie) {
|
||||
// Log the Initial packet now.
|
||||
// If no Retry is sent, the packet will be logged by the session.
|
||||
(&wire.ExtendedHeader{Header: *hdr}).Log(s.logger)
|
||||
return nil, nil, s.sendRetry(p.remoteAddr, hdr)
|
||||
}
|
||||
|
||||
// TODO(#943): send Stateless Reset, if this an IETF QUIC packet
|
||||
if !hdr.VersionFlag && !hdr.Version.UsesIETFHeaderFormat() {
|
||||
_, err := s.conn.WriteTo(wire.WritePublicReset(hdr.DestConnectionID, 0, 0), p.remoteAddr)
|
||||
return err
|
||||
if queueLen := atomic.LoadInt32(&s.sessionQueueLen); queueLen >= protocol.MaxAcceptQueueSize {
|
||||
s.logger.Debugf("Rejecting new connection. Server currently busy. Accept queue length: %d (max %d)", queueLen, protocol.MaxAcceptQueueSize)
|
||||
return nil, nil, s.sendServerBusy(p.remoteAddr, hdr)
|
||||
}
|
||||
|
||||
// This is (potentially) a Client Hello.
|
||||
// Make sure it has the minimum required size before spending any more ressources on it.
|
||||
if len(p.data) < protocol.MinClientHelloSize {
|
||||
return errors.New("dropping small packet for unknown connection")
|
||||
connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var destConnID, srcConnID protocol.ConnectionID
|
||||
if hdr.Version.UsesIETFHeaderFormat() {
|
||||
srcConnID = hdr.DestConnectionID
|
||||
} else {
|
||||
destConnID = hdr.DestConnectionID
|
||||
srcConnID = hdr.DestConnectionID
|
||||
}
|
||||
s.logger.Infof("Serving new connection: %s, version %s from %v", hdr.DestConnectionID, hdr.Version, p.remoteAddr)
|
||||
sess, err := s.newSession(
|
||||
&conn{pconn: s.conn, currentAddr: p.remoteAddr},
|
||||
s.sessionRunner,
|
||||
s.logger.Debugf("Changing connection ID to %s.", connID)
|
||||
sess, err := s.createNewSession(
|
||||
p.remoteAddr,
|
||||
origDestConnectionID,
|
||||
hdr.DestConnectionID,
|
||||
hdr.SrcConnectionID,
|
||||
connID,
|
||||
hdr.Version,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sess.handlePacket(p)
|
||||
return sess, connID, nil
|
||||
}
|
||||
|
||||
func (s *server) createNewSession(
|
||||
remoteAddr net.Addr,
|
||||
origDestConnID protocol.ConnectionID,
|
||||
clientDestConnID protocol.ConnectionID,
|
||||
destConnID protocol.ConnectionID,
|
||||
srcConnID protocol.ConnectionID,
|
||||
version protocol.VersionNumber,
|
||||
) (quicSession, error) {
|
||||
token := s.sessionHandler.GetStatelessResetToken(srcConnID)
|
||||
params := &handshake.TransportParameters{
|
||||
InitialMaxStreamDataBidiLocal: protocol.InitialMaxStreamData,
|
||||
InitialMaxStreamDataBidiRemote: protocol.InitialMaxStreamData,
|
||||
InitialMaxStreamDataUni: protocol.InitialMaxStreamData,
|
||||
InitialMaxData: protocol.InitialMaxData,
|
||||
IdleTimeout: s.config.IdleTimeout,
|
||||
MaxBidiStreams: uint64(s.config.MaxIncomingStreams),
|
||||
MaxUniStreams: uint64(s.config.MaxIncomingUniStreams),
|
||||
AckDelayExponent: protocol.AckDelayExponent,
|
||||
DisableMigration: true,
|
||||
StatelessResetToken: &token,
|
||||
OriginalConnectionID: origDestConnID,
|
||||
}
|
||||
sess, err := s.newSession(
|
||||
&conn{pconn: s.conn, currentAddr: remoteAddr},
|
||||
s.sessionRunner,
|
||||
clientDestConnID,
|
||||
destConnID,
|
||||
srcConnID,
|
||||
s.scfg,
|
||||
s.tlsConf,
|
||||
s.config,
|
||||
s.tlsConf,
|
||||
params,
|
||||
s.logger,
|
||||
version,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go sess.run()
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
func (s *server) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error {
|
||||
token, err := s.cookieGenerator.NewToken(remoteAddr, hdr.DestConnectionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.sessionHandler.Add(hdr.DestConnectionID, newServerSession(sess, s.config, s.logger))
|
||||
go sess.run()
|
||||
sess.handlePacket(p)
|
||||
connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
replyHdr := &wire.ExtendedHeader{}
|
||||
replyHdr.IsLongHeader = true
|
||||
replyHdr.Type = protocol.PacketTypeRetry
|
||||
replyHdr.Version = hdr.Version
|
||||
replyHdr.SrcConnectionID = connID
|
||||
replyHdr.DestConnectionID = hdr.SrcConnectionID
|
||||
replyHdr.OrigDestConnectionID = hdr.DestConnectionID
|
||||
replyHdr.Token = token
|
||||
s.logger.Debugf("Changing connection ID to %s.\n-> Sending Retry", connID)
|
||||
replyHdr.Log(s.logger)
|
||||
buf := &bytes.Buffer{}
|
||||
if err := replyHdr.Write(buf, hdr.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := s.conn.WriteTo(buf.Bytes(), remoteAddr); err != nil {
|
||||
s.logger.Debugf("Error sending Retry: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) sendVersionNegotiationPacket(p *receivedPacket) error {
|
||||
hdr := p.header
|
||||
s.logger.Debugf("Client offered version %s, sending VersionNegotiationPacket", hdr.Version)
|
||||
|
||||
var data []byte
|
||||
if hdr.IsPublicHeader {
|
||||
data = wire.ComposeGQUICVersionNegotiation(hdr.DestConnectionID, s.config.Versions)
|
||||
} else {
|
||||
var err error
|
||||
data, err = wire.ComposeVersionNegotiation(hdr.SrcConnectionID, hdr.DestConnectionID, s.config.Versions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (s *server) sendServerBusy(remoteAddr net.Addr, hdr *wire.Header) error {
|
||||
sealer, _, err := handshake.NewInitialAEAD(hdr.DestConnectionID, protocol.PerspectiveServer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
packetBuffer := getPacketBuffer()
|
||||
defer packetBuffer.Release()
|
||||
buf := bytes.NewBuffer(packetBuffer.Slice[:0])
|
||||
|
||||
ccf := &wire.ConnectionCloseFrame{ErrorCode: qerr.ServerBusy}
|
||||
|
||||
replyHdr := &wire.ExtendedHeader{}
|
||||
replyHdr.IsLongHeader = true
|
||||
replyHdr.Type = protocol.PacketTypeInitial
|
||||
replyHdr.Version = hdr.Version
|
||||
replyHdr.SrcConnectionID = hdr.DestConnectionID
|
||||
replyHdr.DestConnectionID = hdr.SrcConnectionID
|
||||
replyHdr.PacketNumberLen = protocol.PacketNumberLen4
|
||||
replyHdr.Length = 4 /* packet number len */ + ccf.Length(hdr.Version) + protocol.ByteCount(sealer.Overhead())
|
||||
if err := replyHdr.Write(buf, hdr.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
payloadOffset := buf.Len()
|
||||
|
||||
if err := ccf.Write(buf, hdr.Version); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
raw := buf.Bytes()
|
||||
_ = sealer.Seal(raw[payloadOffset:payloadOffset], raw[payloadOffset:], replyHdr.PacketNumber, raw[:payloadOffset])
|
||||
raw = raw[0 : buf.Len()+sealer.Overhead()]
|
||||
|
||||
pnOffset := payloadOffset - int(replyHdr.PacketNumberLen)
|
||||
sealer.EncryptHeader(
|
||||
raw[pnOffset+4:pnOffset+4+16],
|
||||
&raw[0],
|
||||
raw[pnOffset:payloadOffset],
|
||||
)
|
||||
|
||||
replyHdr.Log(s.logger)
|
||||
wire.LogFrame(s.logger, ccf, true)
|
||||
if _, err := s.conn.WriteTo(raw, remoteAddr); err != nil {
|
||||
s.logger.Debugf("Error rejecting connection: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) sendVersionNegotiationPacket(p *receivedPacket, hdr *wire.Header) {
|
||||
s.logger.Debugf("Client offered version %s, sending Version Negotiation", hdr.Version)
|
||||
data, err := wire.ComposeVersionNegotiation(hdr.SrcConnectionID, hdr.DestConnectionID, s.config.Versions)
|
||||
if err != nil {
|
||||
s.logger.Debugf("Error composing Version Negotiation: %s", err)
|
||||
return
|
||||
}
|
||||
if _, err := s.conn.WriteTo(data, p.remoteAddr); err != nil {
|
||||
s.logger.Debugf("Error sending Version Negotiation: %s", err)
|
||||
}
|
||||
_, err := s.conn.WriteTo(data, p.remoteAddr)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user