From a674c0051a62615c9c1bba60719ba35d91de1852 Mon Sep 17 00:00:00 2001 From: Matthew Holt <mholt@users.noreply.github.com> Date: Wed, 18 Apr 2018 15:48:08 -0600 Subject: [PATCH] vendor: Update quic and lego/acme dependencies --- caddytls/client.go | 22 +- .../lucas-clemente/aes12/cipher_generic.go | 2 +- .../lucas-clemente/quic-go/client.go | 25 +- .../quic-go/example/client/main.go | 16 +- .../lucas-clemente/quic-go/example/main.go | 10 +- .../lucas-clemente/quic-go/h2quic/client.go | 7 +- .../quic-go/h2quic/request_writer.go | 7 +- .../quic-go/h2quic/response_writer.go | 15 +- .../lucas-clemente/quic-go/h2quic/server.go | 17 +- .../integrationtests/tools/proxy/proxy.go | 29 ++- .../integrationtests/tools/testlog/testlog.go | 2 +- .../lucas-clemente/quic-go/interface.go | 5 + .../quic-go/internal/ackhandler/gen.go | 3 + .../quic-go/internal/ackhandler/packet.go | 23 +- .../internal/ackhandler/packet_linkedlist.go | 45 ++-- .../quic-go/internal/ackhandler/send_mode.go | 4 + .../ackhandler/sent_packet_handler.go | 209 +++++++++------- .../ackhandler/sent_packet_history.go | 13 +- .../internal/congestion/cubic_sender.go | 8 - .../quic-go/internal/congestion/interface.go | 1 - .../quic-go/internal/congestion/rtt_stats.go | 1 - .../quic-go/internal/crypto/curve_25519.go | 4 - .../quic-go/internal/crypto/key_derivation.go | 4 +- .../internal/crypto/null_aead_aesgcm.go | 2 +- .../internal/crypto/null_aead_fnv128a.go | 36 +-- .../flowcontrol/base_flow_controller.go | 2 + .../flowcontrol/connection_flow_controller.go | 4 +- .../flowcontrol/stream_flow_controller.go | 4 +- .../internal/handshake/cookie_handler.go | 10 +- .../internal/handshake/crypto_setup_client.go | 36 ++- .../internal/handshake/crypto_setup_server.go | 63 +++-- .../internal/handshake/crypto_setup_tls.go | 34 +-- .../internal/handshake/ephermal_cache.go | 14 +- .../quic-go/internal/handshake/interface.go | 22 +- .../handshake/tls_extension_handler_client.go | 8 +- .../handshake/tls_extension_handler_server.go | 8 +- .../quic-go/internal/mocks/congestion.go | 12 - .../internal/utils/byteinterval_linkedlist.go | 45 ++-- .../quic-go/internal/utils/gen.go | 4 + .../internal/utils/linkedlist/linkedlist.go | 218 ++++++++++++++++ .../quic-go/internal/utils/log.go | 78 +++--- .../quic-go/internal/utils/packet_interval.go | 1 - .../utils/packetinterval_linkedlist.go | 45 ++-- .../internal/utils/streamframe_interval.go | 1 - .../quic-go/internal/wire/ack_frame.go | 4 +- .../quic-go/internal/wire/blocked_frame.go | 4 +- .../internal/wire/blocked_frame_legacy.go | 4 +- .../internal/wire/connection_close_frame.go | 4 +- .../quic-go/internal/wire/frame_parser.go | 152 ++++++++++++ .../quic-go/internal/wire/goaway_frame.go | 4 +- .../quic-go/internal/wire/header.go | 7 +- .../quic-go/internal/wire/ietf_header.go | 6 +- .../quic-go/internal/wire/log.go | 14 +- .../quic-go/internal/wire/max_data_frame.go | 4 +- .../internal/wire/max_stream_data_frame.go | 4 +- .../internal/wire/max_stream_id_frame.go | 4 +- .../quic-go/internal/wire/ping_frame.go | 4 +- .../quic-go/internal/wire/public_header.go | 7 +- .../quic-go/internal/wire/rst_stream_frame.go | 4 +- .../internal/wire/stop_sending_frame.go | 4 +- .../internal/wire/stop_waiting_frame.go | 4 +- .../internal/wire/stream_blocked_frame.go | 4 +- .../quic-go/internal/wire/stream_frame.go | 7 +- .../internal/wire/stream_id_blocked_frame.go | 4 +- .../internal/wire/version_negotiation.go | 14 +- .../internal/wire/window_update_frame.go | 4 +- .../lucas-clemente/quic-go/mint_utils.go | 38 +-- .../lucas-clemente/quic-go/mockgen.go | 4 + .../lucas-clemente/quic-go/packet_packer.go | 17 +- .../lucas-clemente/quic-go/packet_unpacker.go | 232 ++++++------------ .../lucas-clemente/quic-go/qerr/quic_error.go | 3 - .../lucas-clemente/quic-go/server.go | 24 +- .../lucas-clemente/quic-go/server_tls.go | 32 ++- .../lucas-clemente/quic-go/session.go | 231 +++++++++++------ .../quic-go/streams_map_generic_helper.go | 11 + .../quic-go/streams_map_incoming_bidi.go | 3 + .../quic-go/streams_map_incoming_generic.go | 3 + .../quic-go/streams_map_incoming_uni.go | 3 + .../quic-go/streams_map_outgoing_bidi.go | 3 + .../quic-go/streams_map_outgoing_generic.go | 6 +- .../quic-go/streams_map_outgoing_uni.go | 3 + .../github.com/xenolf/lego/acmev2/client.go | 43 ++-- vendor/github.com/xenolf/lego/acmev2/error.go | 13 + .../github.com/xenolf/lego/acmev2/messages.go | 3 +- vendor/manifest | 6 +- 85 files changed, 1298 insertions(+), 766 deletions(-) create mode 100644 vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go create mode 100644 vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go create mode 100644 vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go create mode 100644 vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go create mode 100644 vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go diff --git a/caddytls/client.go b/caddytls/client.go index b67a2928d..7c747194e 100644 --- a/caddytls/client.go +++ b/caddytls/client.go @@ -240,26 +240,30 @@ func (c *ACMEClient) Obtain(name string) error { for attempts := 0; attempts < 2; attempts++ { namesObtaining.Add([]string{name}) acmeMu.Lock() - certificate, failures := c.acmeClient.ObtainCertificate([]string{name}, true, nil, c.config.MustStaple) + certificate, err := c.acmeClient.ObtainCertificate([]string{name}, true, nil, c.config.MustStaple) acmeMu.Unlock() namesObtaining.Remove([]string{name}) - if len(failures) > 0 { + if err != nil { // Error - try to fix it or report it to the user and abort - var errMsg string // combine all the failures into a single error message - for errDomain, obtainErr := range failures { - if obtainErr == nil { - continue + if failures, ok := err.(acme.ObtainError); ok && len(failures) > 0 { + // in this case, we can enumerate the error per-domain + var errMsg string // combine all the failures into a single error message + for errDomain, obtainErr := range failures { + if obtainErr == nil { + continue + } + errMsg += fmt.Sprintf("[%s] failed to get certificate: %v\n", errDomain, obtainErr) } - errMsg += fmt.Sprintf("[%s] failed to get certificate: %v\n", errDomain, obtainErr) + return errors.New(errMsg) } - return errors.New(errMsg) + return fmt.Errorf("[%s] failed to obtain certificate: %v", name, err) } // double-check that we actually got a certificate; check a couple fields // TODO: This is a temporary workaround for what I think is a bug in the acmev2 package (March 2018) - // but it might not hurt to keep this extra check in place + // but it might not hurt to keep this extra check in place (April 18, 2018: might be fixed now.) if certificate.Domain == "" || certificate.Certificate == nil { return errors.New("returned certificate was empty; probably an unchecked error obtaining it") } diff --git a/vendor/github.com/lucas-clemente/aes12/cipher_generic.go b/vendor/github.com/lucas-clemente/aes12/cipher_generic.go index a9a6abd55..6861677f8 100644 --- a/vendor/github.com/lucas-clemente/aes12/cipher_generic.go +++ b/vendor/github.com/lucas-clemente/aes12/cipher_generic.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!s390x +// +build !amd64 package aes12 diff --git a/vendor/github.com/lucas-clemente/quic-go/client.go b/vendor/github.com/lucas-clemente/quic-go/client.go index 02deb6804..1906abdf9 100644 --- a/vendor/github.com/lucas-clemente/quic-go/client.go +++ b/vendor/github.com/lucas-clemente/quic-go/client.go @@ -38,6 +38,8 @@ type client struct { version protocol.VersionNumber session packetHandler + + logger utils.Logger } var ( @@ -102,9 +104,10 @@ func Dial( config: clientConfig, version: clientConfig.Versions[0], versionNegotiationChan: make(chan struct{}), + logger: utils.DefaultLogger, } - utils.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %s", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version) + c.logger.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %s", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version) if err := c.dial(); err != nil { return nil, err @@ -197,7 +200,7 @@ func (c *client) dialTLS() error { MaxUniStreams: uint16(c.config.MaxIncomingUniStreams), } csc := handshake.NewCryptoStreamConn(nil) - extHandler := handshake.NewExtensionHandlerClient(params, c.initialVersion, c.config.Versions, c.version) + extHandler := handshake.NewExtensionHandlerClient(params, c.initialVersion, c.config.Versions, c.version, c.logger) mintConf, err := tlsToMintConfig(c.tlsConf, protocol.PerspectiveClient) if err != nil { return err @@ -214,7 +217,7 @@ func (c *client) dialTLS() error { if err != handshake.ErrCloseSessionForRetry { return err } - utils.Infof("Received a Retry packet. Recreating session.") + c.logger.Infof("Received a Retry packet. Recreating session.") if err := c.createNewTLSSession(extHandler.GetPeerParams(), c.version); err != nil { return err } @@ -237,7 +240,7 @@ func (c *client) establishSecureConnection() error { go func() { runErr = c.session.run() // returns as soon as the session is closed close(errorChan) - utils.Infof("Connection %x closed.", c.connectionID) + c.logger.Infof("Connection %x closed.", c.connectionID) if runErr != handshake.ErrCloseSessionForRetry && runErr != errCloseSessionForNewVersion { c.conn.Close() } @@ -291,7 +294,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) { r := bytes.NewReader(packet) hdr, err := wire.ParseHeaderSentByServer(r, c.version) if err != nil { - utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error()) + c.logger.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error()) // drop this packet if we can't parse the header return } @@ -314,15 +317,15 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) { // 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 if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || hdr.ConnectionID != c.connectionID { - utils.Infof("Received a spoofed Public Reset. Ignoring.") + c.logger.Infof("Received a spoofed Public Reset. Ignoring.") return } pr, err := wire.ParsePublicReset(r) if err != nil { - utils.Infof("Received a Public Reset. An error occurred parsing the packet: %s", err) + c.logger.Infof("Received a Public Reset. An error occurred parsing the packet: %s", err) return } - utils.Infof("Received Public Reset, rejected packet number: %#x.", pr.RejectedPacketNumber) + c.logger.Infof("Received Public Reset, rejected packet number: %#x.", pr.RejectedPacketNumber) c.session.closeRemote(qerr.Error(qerr.PublicReset, fmt.Sprintf("Received a Public Reset for packet number %#x", pr.RejectedPacketNumber))) return } @@ -368,7 +371,7 @@ func (c *client) handleVersionNegotiationPacket(hdr *wire.Header) error { } } - utils.Infof("Received a Version Negotiation Packet. Supported Versions: %s", hdr.SupportedVersions) + c.logger.Infof("Received a Version Negotiation Packet. Supported Versions: %s", hdr.SupportedVersions) newVersion, ok := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions) if !ok { @@ -385,7 +388,7 @@ func (c *client) handleVersionNegotiationPacket(hdr *wire.Header) error { if err != nil { return err } - utils.Infof("Switching to QUIC version %s. New connection ID: %x", newVersion, c.connectionID) + c.logger.Infof("Switching to QUIC version %s. New connection ID: %x", newVersion, c.connectionID) c.session.Close(errCloseSessionForNewVersion) return nil } @@ -402,6 +405,7 @@ func (c *client) createNewGQUICSession() (err error) { c.config, c.initialVersion, c.negotiatedVersions, + c.logger, ) return err } @@ -421,6 +425,7 @@ func (c *client) createNewTLSSession( c.tls, paramsChan, 1, + c.logger, ) return err } diff --git a/vendor/github.com/lucas-clemente/quic-go/example/client/main.go b/vendor/github.com/lucas-clemente/quic-go/example/client/main.go index 2a28c1612..23f045c84 100644 --- a/vendor/github.com/lucas-clemente/quic-go/example/client/main.go +++ b/vendor/github.com/lucas-clemente/quic-go/example/client/main.go @@ -19,12 +19,14 @@ func main() { flag.Parse() urls := flag.Args() + logger := utils.DefaultLogger + if *verbose { - utils.SetLogLevel(utils.LogLevelDebug) + logger.SetLogLevel(utils.LogLevelDebug) } else { - utils.SetLogLevel(utils.LogLevelInfo) + logger.SetLogLevel(utils.LogLevelInfo) } - utils.SetLogTimeFormat("") + logger.SetLogTimeFormat("") versions := protocol.SupportedVersions if *tls { @@ -42,21 +44,21 @@ func main() { var wg sync.WaitGroup wg.Add(len(urls)) for _, addr := range urls { - utils.Infof("GET %s", addr) + logger.Infof("GET %s", addr) go func(addr string) { rsp, err := hclient.Get(addr) if err != nil { panic(err) } - utils.Infof("Got response for %s: %#v", addr, rsp) + logger.Infof("Got response for %s: %#v", addr, rsp) body := &bytes.Buffer{} _, err = io.Copy(body, rsp.Body) if err != nil { panic(err) } - utils.Infof("Request Body:") - utils.Infof("%s", body.Bytes()) + logger.Infof("Request Body:") + logger.Infof("%s", body.Bytes()) wg.Done() }(addr) } diff --git a/vendor/github.com/lucas-clemente/quic-go/example/main.go b/vendor/github.com/lucas-clemente/quic-go/example/main.go index 35aaa85c6..e83fb8703 100644 --- a/vendor/github.com/lucas-clemente/quic-go/example/main.go +++ b/vendor/github.com/lucas-clemente/quic-go/example/main.go @@ -91,7 +91,7 @@ func init() { } } if err != nil { - utils.Infof("Error receiving upload: %#v", err) + utils.DefaultLogger.Infof("Error receiving upload: %#v", err) } } io.WriteString(w, `<html><body><form action="/demo/upload" method="post" enctype="multipart/form-data"> @@ -126,12 +126,14 @@ func main() { tls := flag.Bool("tls", false, "activate support for IETF QUIC (work in progress)") flag.Parse() + logger := utils.DefaultLogger + if *verbose { - utils.SetLogLevel(utils.LogLevelDebug) + logger.SetLogLevel(utils.LogLevelDebug) } else { - utils.SetLogLevel(utils.LogLevelInfo) + logger.SetLogLevel(utils.LogLevelInfo) } - utils.SetLogTimeFormat("") + logger.SetLogTimeFormat("") versions := protocol.SupportedVersions if *tls { diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go index 53e667cd1..409808827 100644 --- a/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go +++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go @@ -46,6 +46,8 @@ type client struct { requestWriter *requestWriter responses map[protocol.StreamID]chan *http.Response + + logger utils.Logger } var _ http.RoundTripper = &client{} @@ -75,6 +77,7 @@ func newClient( opts: opts, headerErrored: make(chan struct{}), dialer: dialer, + logger: utils.DefaultLogger, } } @@ -95,7 +98,7 @@ func (c *client) dial() error { if err != nil { return err } - c.requestWriter = newRequestWriter(c.headerStream) + c.requestWriter = newRequestWriter(c.headerStream, c.logger) go c.handleHeaderStream() return nil } @@ -109,7 +112,7 @@ func (c *client) handleHeaderStream() { err = c.readResponse(h2framer, decoder) } if quicErr, ok := err.(*qerr.QuicError); !ok || quicErr.ErrorCode != qerr.PeerGoingAway { - utils.Debugf("Error handling header stream: %s", err) + c.logger.Debugf("Error handling header stream: %s", err) } c.headerErr = qerr.Error(qerr.InvalidHeadersStreamData, err.Error()) // stop all running request diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go index fdd7ad20a..ddaaa741d 100644 --- a/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go +++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go @@ -23,13 +23,16 @@ type requestWriter struct { henc *hpack.Encoder hbuf bytes.Buffer // HPACK encoder writes into this + + logger utils.Logger } const defaultUserAgent = "quic-go" -func newRequestWriter(headerStream quic.Stream) *requestWriter { +func newRequestWriter(headerStream quic.Stream, logger utils.Logger) *requestWriter { rw := &requestWriter{ headerStream: headerStream, + logger: logger, } rw.henc = hpack.NewEncoder(&rw.hbuf) return rw @@ -156,7 +159,7 @@ func (w *requestWriter) encodeHeaders(req *http.Request, addGzipHeader bool, tra } func (w *requestWriter) writeHeader(name, value string) { - utils.Debugf("http2: Transport encoding header %q = %q", name, value) + w.logger.Debugf("http2: Transport encoding header %q = %q", name, value) w.henc.WriteField(hpack.HeaderField{Name: name, Value: value}) } diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go index 1dd4e928a..25b77a54c 100644 --- a/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go +++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go @@ -24,15 +24,24 @@ type responseWriter struct { header http.Header status int // status code passed to WriteHeader headerWritten bool + + logger utils.Logger } -func newResponseWriter(headerStream quic.Stream, headerStreamMutex *sync.Mutex, dataStream quic.Stream, dataStreamID protocol.StreamID) *responseWriter { +func newResponseWriter( + headerStream quic.Stream, + headerStreamMutex *sync.Mutex, + dataStream quic.Stream, + dataStreamID protocol.StreamID, + logger utils.Logger, +) *responseWriter { return &responseWriter{ header: http.Header{}, headerStream: headerStream, headerStreamMutex: headerStreamMutex, dataStream: dataStream, dataStreamID: dataStreamID, + logger: logger, } } @@ -57,7 +66,7 @@ func (w *responseWriter) WriteHeader(status int) { } } - utils.Infof("Responding with %d", status) + w.logger.Infof("Responding with %d", status) w.headerStreamMutex.Lock() defer w.headerStreamMutex.Unlock() h2framer := http2.NewFramer(w.headerStream, nil) @@ -67,7 +76,7 @@ func (w *responseWriter) WriteHeader(status int) { BlockFragment: headers.Bytes(), }) if err != nil { - utils.Errorf("could not write h2 header: %s", err.Error()) + w.logger.Errorf("could not write h2 header: %s", err.Error()) } } diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go index 329edfd0d..a2412bd16 100644 --- a/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go +++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go @@ -53,6 +53,8 @@ type Server struct { closed bool supportedVersionsAsString string + + logger utils.Logger // will be set by Server.serveImpl() } // ListenAndServe listens on the UDP address s.Addr and calls s.Handler to handle HTTP/2 requests on incoming connections. @@ -88,6 +90,7 @@ func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error { if s.Server == nil { return errors.New("use of h2quic.Server without http.Server") } + s.logger = utils.DefaultLogger s.listenerMutex.Lock() if s.closed { s.listenerMutex.Unlock() @@ -138,7 +141,7 @@ func (s *Server) handleHeaderStream(session streamCreator) { // In this case, the session has already logged the error, so we don't // need to log it again. if _, ok := err.(*qerr.QuicError); !ok { - utils.Errorf("error handling h2 request: %s", err.Error()) + s.logger.Errorf("error handling h2 request: %s", err.Error()) } session.Close(err) return @@ -160,7 +163,7 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream, } headers, err := hpackDecoder.DecodeFull(h2headersFrame.HeaderBlockFragment()) if err != nil { - utils.Errorf("invalid http2 headers encoding: %s", err.Error()) + s.logger.Errorf("invalid http2 headers encoding: %s", err.Error()) return err } @@ -169,10 +172,10 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream, return err } - if utils.Debug() { - utils.Infof("%s %s%s, on data stream %d", req.Method, req.Host, req.RequestURI, h2headersFrame.StreamID) + if s.logger.Debug() { + s.logger.Infof("%s %s%s, on data stream %d", req.Method, req.Host, req.RequestURI, h2headersFrame.StreamID) } else { - utils.Infof("%s %s%s", req.Method, req.Host, req.RequestURI) + s.logger.Infof("%s %s%s", req.Method, req.Host, req.RequestURI) } dataStream, err := session.GetOrOpenStream(protocol.StreamID(h2headersFrame.StreamID)) @@ -201,7 +204,7 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream, req.RemoteAddr = session.RemoteAddr().String() - responseWriter := newResponseWriter(headerStream, headerStreamMutex, dataStream, protocol.StreamID(h2headersFrame.StreamID)) + responseWriter := newResponseWriter(headerStream, headerStreamMutex, dataStream, protocol.StreamID(h2headersFrame.StreamID), s.logger) handler := s.Handler if handler == nil { @@ -215,7 +218,7 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream, const size = 64 << 10 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] - utils.Errorf("http: panic serving: %v\n%s", p, buf) + s.logger.Errorf("http: panic serving: %v\n%s", p, buf) panicked = true } }() diff --git a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go index 423aec019..d12a3baea 100644 --- a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go +++ b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go @@ -95,6 +95,8 @@ type QuicProxy struct { // Mapping from client addresses (as host:port) to connection clientDict map[string]*connection + + logger utils.Logger } // NewQuicProxy creates a new UDP proxy @@ -132,9 +134,10 @@ func NewQuicProxy(local string, version protocol.VersionNumber, opts *Opts) (*Qu dropPacket: packetDropper, delayPacket: packetDelayer, version: version, + logger: utils.DefaultLogger, } - utils.Debugf("Starting UDP Proxy %s <-> %s", conn.LocalAddr(), raddr) + p.logger.Debugf("Starting UDP Proxy %s <-> %s", conn.LocalAddr(), raddr) go p.runProxy() return &p, nil } @@ -200,8 +203,8 @@ func (p *QuicProxy) runProxy() error { packetCount := atomic.AddUint64(&conn.incomingPacketCounter, 1) if p.dropPacket(DirectionIncoming, packetCount) { - if utils.Debug() { - utils.Debugf("dropping incoming packet %d (%d bytes)", packetCount, n) + if p.logger.Debug() { + p.logger.Debugf("dropping incoming packet %d (%d bytes)", packetCount, n) } continue } @@ -209,16 +212,16 @@ func (p *QuicProxy) runProxy() error { // Send the packet to the server delay := p.delayPacket(DirectionIncoming, packetCount) if delay != 0 { - if utils.Debug() { - utils.Debugf("delaying incoming packet %d (%d bytes) to %s by %s", packetCount, n, conn.ServerConn.RemoteAddr(), delay) + if p.logger.Debug() { + p.logger.Debugf("delaying incoming packet %d (%d bytes) to %s by %s", packetCount, n, conn.ServerConn.RemoteAddr(), delay) } time.AfterFunc(delay, func() { // TODO: handle error _, _ = conn.ServerConn.Write(raw) }) } else { - if utils.Debug() { - utils.Debugf("forwarding incoming packet %d (%d bytes) to %s", packetCount, n, conn.ServerConn.RemoteAddr()) + if p.logger.Debug() { + p.logger.Debugf("forwarding incoming packet %d (%d bytes) to %s", packetCount, n, conn.ServerConn.RemoteAddr()) } if _, err := conn.ServerConn.Write(raw); err != nil { return err @@ -240,24 +243,24 @@ func (p *QuicProxy) runConnection(conn *connection) error { packetCount := atomic.AddUint64(&conn.outgoingPacketCounter, 1) if p.dropPacket(DirectionOutgoing, packetCount) { - if utils.Debug() { - utils.Debugf("dropping outgoing packet %d (%d bytes)", packetCount, n) + if p.logger.Debug() { + p.logger.Debugf("dropping outgoing packet %d (%d bytes)", packetCount, n) } continue } delay := p.delayPacket(DirectionOutgoing, packetCount) if delay != 0 { - if utils.Debug() { - utils.Debugf("delaying outgoing packet %d (%d bytes) to %s by %s", packetCount, n, conn.ClientAddr, delay) + if p.logger.Debug() { + p.logger.Debugf("delaying outgoing packet %d (%d bytes) to %s by %s", packetCount, n, conn.ClientAddr, delay) } time.AfterFunc(delay, func() { // TODO: handle error _, _ = p.conn.WriteToUDP(raw, conn.ClientAddr) }) } else { - if utils.Debug() { - utils.Debugf("forwarding outgoing packet %d (%d bytes) to %s", packetCount, n, conn.ClientAddr) + if p.logger.Debug() { + p.logger.Debugf("forwarding outgoing packet %d (%d bytes) to %s", packetCount, n, conn.ClientAddr) } if _, err := p.conn.WriteToUDP(raw, conn.ClientAddr); err != nil { return err diff --git a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go index 783531627..c987ddb73 100644 --- a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go +++ b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go @@ -30,7 +30,7 @@ var _ = BeforeEach(func() { logFile, err = os.Create(logFileName) Expect(err).ToNot(HaveOccurred()) log.SetOutput(logFile) - utils.SetLogLevel(utils.LogLevelDebug) + utils.DefaultLogger.SetLogLevel(utils.LogLevelDebug) } }) diff --git a/vendor/github.com/lucas-clemente/quic-go/interface.go b/vendor/github.com/lucas-clemente/quic-go/interface.go index bcbea1703..3ab64afdc 100644 --- a/vendor/github.com/lucas-clemente/quic-go/interface.go +++ b/vendor/github.com/lucas-clemente/quic-go/interface.go @@ -16,6 +16,9 @@ type StreamID = protocol.StreamID // A VersionNumber is a QUIC version number. type VersionNumber = protocol.VersionNumber +// VersionGQUIC39 is gQUIC version 39. +const VersionGQUIC39 = protocol.Version39 + // A Cookie can be used to verify the ownership of the client address. type Cookie = handshake.Cookie @@ -118,6 +121,8 @@ type Session interface { AcceptUniStream() (ReceiveStream, error) // OpenStream opens a new bidirectional QUIC stream. // It returns a special error when the peer's concurrent stream limit is reached. + // There is no signaling to the peer about new streams: + // The peer can only accept the stream after data has been sent on the stream. // TODO(#1152): Enable testing for the special error OpenStream() (Stream, error) // OpenStreamSync opens a new bidirectional QUIC stream. diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go new file mode 100644 index 000000000..32235f81a --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go @@ -0,0 +1,3 @@ +package ackhandler + +//go:generate genny -pkg ackhandler -in ../utils/linkedlist/linkedlist.go -out packet_linkedlist.go gen Item=Packet diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go index 3638b193e..9673a85c7 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go @@ -8,35 +8,22 @@ import ( ) // A Packet is a packet -// +gen linkedlist type Packet struct { PacketNumber protocol.PacketNumber PacketType protocol.PacketType Frames []wire.Frame Length protocol.ByteCount EncryptionLevel protocol.EncryptionLevel + SendTime time.Time largestAcked protocol.PacketNumber // if the packet contains an ACK, the LargestAcked value of that ACK - sendTime time.Time - queuedForRetransmission bool + // There are two reasons why a packet cannot be retransmitted: + // * it was already retransmitted + // * this packet is a retransmission, and we already received an ACK for the original packet + canBeRetransmitted bool includedInBytesInFlight bool retransmittedAs []protocol.PacketNumber isRetransmission bool // we need a separate bool here because 0 is a valid packet number retransmissionOf protocol.PacketNumber } - -// GetFramesForRetransmission gets all the frames for retransmission -func (p *Packet) GetFramesForRetransmission() []wire.Frame { - var fs []wire.Frame - for _, frame := range p.Frames { - switch frame.(type) { - case *wire.AckFrame: - continue - case *wire.StopWaitingFrame: - continue - } - fs = append(fs, frame) - } - return fs -} diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go index a827b214e..bb74f4ef9 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go @@ -1,13 +1,10 @@ -// Generated by: main -// TypeWriter: linkedlist -// Directive: +gen on Packet +// This file was automatically generated by genny. +// Any changes will be lost if this file is regenerated. +// see https://github.com/cheekybits/genny package ackhandler -// List is a modification of http://golang.org/pkg/container/list/ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Linked list implementation from the Go standard library. // PacketElement is an element of a linked list. type PacketElement struct { @@ -41,8 +38,7 @@ func (e *PacketElement) Prev() *PacketElement { return nil } -// PacketList represents a doubly linked list. -// The zero value for PacketList is an empty list ready to use. +// PacketList is a linked list of Packets. type PacketList struct { root PacketElement // sentinel list element, only &root, root.prev, and root.next are used len int // current list length excluding (this) sentinel element @@ -63,7 +59,7 @@ func NewPacketList() *PacketList { return new(PacketList).Init() } // The complexity is O(1). func (l *PacketList) Len() int { return l.len } -// Front returns the first element of list l or nil. +// Front returns the first element of list l or nil if the list is empty. func (l *PacketList) Front() *PacketElement { if l.len == 0 { return nil @@ -71,7 +67,7 @@ func (l *PacketList) Front() *PacketElement { return l.root.next } -// Back returns the last element of list l or nil. +// Back returns the last element of list l or nil if the list is empty. func (l *PacketList) Back() *PacketElement { if l.len == 0 { return nil @@ -79,7 +75,7 @@ func (l *PacketList) Back() *PacketElement { return l.root.prev } -// lazyInit lazily initializes a zero PacketList value. +// lazyInit lazily initializes a zero List value. func (l *PacketList) lazyInit() { if l.root.next == nil { l.Init() @@ -98,7 +94,7 @@ func (l *PacketList) insert(e, at *PacketElement) *PacketElement { return e } -// insertValue is a convenience wrapper for insert(&PacketElement{Value: v}, at). +// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). func (l *PacketList) insertValue(v Packet, at *PacketElement) *PacketElement { return l.insert(&PacketElement{Value: v}, at) } @@ -116,10 +112,11 @@ func (l *PacketList) remove(e *PacketElement) *PacketElement { // Remove removes e from l if e is an element of list l. // It returns the element value e.Value. +// The element must not be nil. func (l *PacketList) Remove(e *PacketElement) Packet { if e.list == l { // if e.list == l, l must have been initialized when e was inserted - // in l or l == nil (e is a zero PacketElement) and l.remove will crash + // in l or l == nil (e is a zero Element) and l.remove will crash l.remove(e) } return e.Value @@ -139,46 +136,51 @@ func (l *PacketList) PushBack(v Packet) *PacketElement { // InsertBefore inserts a new element e with value v immediately before mark and returns e. // If mark is not an element of l, the list is not modified. +// The mark must not be nil. func (l *PacketList) InsertBefore(v Packet, mark *PacketElement) *PacketElement { if mark.list != l { return nil } - // see comment in PacketList.Remove about initialization of l + // see comment in List.Remove about initialization of l return l.insertValue(v, mark.prev) } // InsertAfter inserts a new element e with value v immediately after mark and returns e. // If mark is not an element of l, the list is not modified. +// The mark must not be nil. func (l *PacketList) InsertAfter(v Packet, mark *PacketElement) *PacketElement { if mark.list != l { return nil } - // see comment in PacketList.Remove about initialization of l + // see comment in List.Remove about initialization of l return l.insertValue(v, mark) } // MoveToFront moves element e to the front of list l. // If e is not an element of l, the list is not modified. +// The element must not be nil. func (l *PacketList) MoveToFront(e *PacketElement) { if e.list != l || l.root.next == e { return } - // see comment in PacketList.Remove about initialization of l + // see comment in List.Remove about initialization of l l.insert(l.remove(e), &l.root) } // MoveToBack moves element e to the back of list l. // If e is not an element of l, the list is not modified. +// The element must not be nil. func (l *PacketList) MoveToBack(e *PacketElement) { if e.list != l || l.root.prev == e { return } - // see comment in PacketList.Remove about initialization of l + // see comment in List.Remove about initialization of l l.insert(l.remove(e), l.root.prev) } // MoveBefore moves element e to its new position before mark. // If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. func (l *PacketList) MoveBefore(e, mark *PacketElement) { if e.list != l || e == mark || mark.list != l { return @@ -187,7 +189,8 @@ func (l *PacketList) MoveBefore(e, mark *PacketElement) { } // MoveAfter moves element e to its new position after mark. -// If e is not an element of l, or e == mark, the list is not modified. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. func (l *PacketList) MoveAfter(e, mark *PacketElement) { if e.list != l || e == mark || mark.list != l { return @@ -196,7 +199,7 @@ func (l *PacketList) MoveAfter(e, mark *PacketElement) { } // PushBackList inserts a copy of an other list at the back of list l. -// The lists l and other may be the same. +// The lists l and other may be the same. They must not be nil. func (l *PacketList) PushBackList(other *PacketList) { l.lazyInit() for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { @@ -205,7 +208,7 @@ func (l *PacketList) PushBackList(other *PacketList) { } // PushFrontList inserts a copy of an other list at the front of list l. -// The lists l and other may be the same. +// The lists l and other may be the same. They must not be nil. func (l *PacketList) PushFrontList(other *PacketList) { l.lazyInit() for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go index 3ece73522..61573a478 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go @@ -12,6 +12,8 @@ const ( SendAck // SendRetransmission means that retransmissions should be sent SendRetransmission + // SendRTO means that an RTO probe packet should be sent + SendRTO // SendAny packet should be sent SendAny ) @@ -24,6 +26,8 @@ func (s SendMode) String() string { return "ack" case SendRetransmission: return "retransmission" + case SendRTO: + return "rto" case SendAny: return "any" default: diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go index bee194774..72ab4df8f 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go @@ -32,6 +32,7 @@ const ( type sentPacketHandler struct { lastSentPacketNumber protocol.PacketNumber lastSentRetransmittablePacketTime time.Time + lastSentHandshakePacketTime time.Time nextPacketSendTime time.Time skippedPackets []protocol.PacketNumber @@ -42,6 +43,7 @@ type sentPacketHandler struct { // example: we send an ACK for packets 90-100 with packet number 20 // once we receive an ACK from the peer for packet 20, the lowestPacketNotConfirmedAcked is 101 lowestPacketNotConfirmedAcked protocol.PacketNumber + largestSentBeforeRTO protocol.PacketNumber packetHistory *sentPacketHistory stopWaitingManager stopWaitingManager @@ -59,16 +61,20 @@ type sentPacketHandler struct { // The number of times an RTO has been sent without receiving an ack. rtoCount uint32 + // The number of RTO probe packets that should be sent. + numRTOs int // The time at which the next packet will be considered lost based on early transmit or exceeding the reordering window in time. lossTime time.Time // The alarm timeout alarm time.Time + + logger utils.Logger } // NewSentPacketHandler creates a new sentPacketHandler -func NewSentPacketHandler(rttStats *congestion.RTTStats) SentPacketHandler { +func NewSentPacketHandler(rttStats *congestion.RTTStats, logger utils.Logger) SentPacketHandler { congestion := congestion.NewCubicSender( congestion.DefaultClock{}, rttStats, @@ -82,6 +88,7 @@ func NewSentPacketHandler(rttStats *congestion.RTTStats) SentPacketHandler { stopWaitingManager: stopWaitingManager{}, rttStats: rttStats, congestion: congestion, + logger: logger, } } @@ -114,7 +121,6 @@ func (h *sentPacketHandler) SetHandshakeComplete() { } func (h *sentPacketHandler) SentPacket(packet *Packet) { - packet.sendTime = time.Now() if isRetransmittable := h.sentPacketImpl(packet); isRetransmittable { h.packetHistory.SentPacket(packet) h.updateLossDetectionAlarm() @@ -122,10 +128,8 @@ func (h *sentPacketHandler) SentPacket(packet *Packet) { } func (h *sentPacketHandler) SentPacketsAsRetransmission(packets []*Packet, retransmissionOf protocol.PacketNumber) { - now := time.Now() var p []*Packet for _, packet := range packets { - packet.sendTime = now if isRetransmittable := h.sentPacketImpl(packet); isRetransmittable { p = append(p, packet) } @@ -144,10 +148,9 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmitt h.lastSentPacketNumber = packet.PacketNumber - var largestAcked protocol.PacketNumber if len(packet.Frames) > 0 { if ackFrame, ok := packet.Frames[0].(*wire.AckFrame); ok { - largestAcked = ackFrame.LargestAcked + packet.largestAcked = ackFrame.LargestAcked } } @@ -155,14 +158,20 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmitt isRetransmittable := len(packet.Frames) != 0 if isRetransmittable { - packet.largestAcked = largestAcked - h.lastSentRetransmittablePacketTime = packet.sendTime + if packet.EncryptionLevel < protocol.EncryptionForwardSecure { + h.lastSentHandshakePacketTime = packet.SendTime + } + h.lastSentRetransmittablePacketTime = packet.SendTime packet.includedInBytesInFlight = true h.bytesInFlight += packet.Length + packet.canBeRetransmitted = true + if h.numRTOs > 0 { + h.numRTOs-- + } } - h.congestion.OnPacketSent(packet.sendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isRetransmittable) + h.congestion.OnPacketSent(packet.SendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isRetransmittable) - h.nextPacketSendTime = utils.MaxTime(h.nextPacketSendTime, packet.sendTime).Add(h.congestion.TimeUntilSend(h.bytesInFlight)) + h.nextPacketSendTime = utils.MaxTime(h.nextPacketSendTime, packet.SendTime).Add(h.congestion.TimeUntilSend(h.bytesInFlight)) return isRetransmittable } @@ -173,7 +182,7 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe // duplicate or out of order ACK if withPacketNumber != 0 && withPacketNumber <= h.largestReceivedPacketWithAck { - utils.Debugf("Ignoring ACK frame (duplicate or out of order).") + h.logger.Debugf("Ignoring ACK frame (duplicate or out of order).") return nil } h.largestReceivedPacketWithAck = withPacketNumber @@ -192,6 +201,7 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe return err } + priorInFlight := h.bytesInFlight for _, p := range ackedPackets { if encLevel < p.EncryptionLevel { return fmt.Errorf("Received ACK with encryption level %s that acks a packet %d (encryption level %s)", encLevel, p.PacketNumber, p.EncryptionLevel) @@ -205,12 +215,12 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe if err := h.onPacketAcked(p); err != nil { return err } - if len(p.retransmittedAs) == 0 { - h.congestion.OnPacketAcked(p.PacketNumber, p.Length, h.bytesInFlight) + if p.includedInBytesInFlight { + h.congestion.OnPacketAcked(p.PacketNumber, p.Length, priorInFlight) } } - if err := h.detectLostPackets(rcvTime); err != nil { + if err := h.detectLostPackets(rcvTime, priorInFlight); err != nil { return err } h.updateLossDetectionAlarm() @@ -262,7 +272,7 @@ func (h *sentPacketHandler) determineNewlyAckedPackets(ackFrame *wire.AckFrame) func (h *sentPacketHandler) maybeUpdateRTT(largestAcked protocol.PacketNumber, ackDelay time.Duration, rcvTime time.Time) bool { if p := h.packetHistory.GetPacket(largestAcked); p != nil { - h.rttStats.UpdateRTT(rcvTime.Sub(p.sendTime), ackDelay, rcvTime) + h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay, rcvTime) return true } return false @@ -277,7 +287,7 @@ func (h *sentPacketHandler) updateLossDetectionAlarm() { // TODO(#497): TLP if !h.handshakeComplete { - h.alarm = h.lastSentRetransmittablePacketTime.Add(h.computeHandshakeTimeout()) + h.alarm = h.lastSentHandshakePacketTime.Add(h.computeHandshakeTimeout()) } else if !h.lossTime.IsZero() { // Early retransmit timer or time loss detection. h.alarm = h.lossTime @@ -287,7 +297,7 @@ func (h *sentPacketHandler) updateLossDetectionAlarm() { } } -func (h *sentPacketHandler) detectLostPackets(now time.Time) error { +func (h *sentPacketHandler) detectLostPackets(now time.Time, priorInFlight protocol.ByteCount) error { h.lossTime = time.Time{} maxRTT := float64(utils.MaxDuration(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT())) @@ -298,11 +308,8 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time) error { if packet.PacketNumber > h.largestAcked { return false, nil } - if packet.queuedForRetransmission { // don't retransmit packets twice - return true, nil - } - timeSinceSent := now.Sub(packet.sendTime) + timeSinceSent := now.Sub(packet.SendTime) if timeSinceSent > delayUntilLost { lostPackets = append(lostPackets, packet) } else if h.lossTime.IsZero() { @@ -313,12 +320,19 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time) error { }) for _, p := range lostPackets { - if err := h.queuePacketForRetransmission(p); err != nil { - return err + // the bytes in flight need to be reduced no matter if this packet will be retransmitted + if p.includedInBytesInFlight { + h.bytesInFlight -= p.Length + h.congestion.OnPacketLost(p.PacketNumber, p.Length, priorInFlight) } - h.bytesInFlight -= p.Length - p.includedInBytesInFlight = false - h.congestion.OnPacketLost(p.PacketNumber, p.Length, h.bytesInFlight) + if p.canBeRetransmitted { + // queue the packet for retransmission, and report the loss to the congestion controller + h.logger.Debugf("\tQueueing packet %#x because it was detected lost", p.PacketNumber) + if err := h.queuePacketForRetransmission(p); err != nil { + return err + } + } + h.packetHistory.Remove(p.PacketNumber) } return nil } @@ -333,10 +347,11 @@ func (h *sentPacketHandler) OnAlarm() error { err = h.queueHandshakePacketsForRetransmission() } else if !h.lossTime.IsZero() { // Early retransmit or time loss detection - err = h.detectLostPackets(now) + err = h.detectLostPackets(now, h.bytesInFlight) } else { // RTO h.rtoCount++ + h.numRTOs += 2 err = h.queueRTOs() } if err != nil { @@ -357,57 +372,67 @@ func (h *sentPacketHandler) onPacketAcked(p *Packet) error { if packet := h.packetHistory.GetPacket(p.PacketNumber); packet == nil { return nil } + + // only report the acking of this packet to the congestion controller if: + // * it is a retransmittable packet + // * this packet wasn't retransmitted yet + if p.isRetransmission { + // that the parent doesn't exist is expected to happen every time the original packet was already acked + if parent := h.packetHistory.GetPacket(p.retransmissionOf); parent != nil { + if len(parent.retransmittedAs) == 1 { + parent.retransmittedAs = nil + } else { + // remove this packet from the slice of retransmission + retransmittedAs := make([]protocol.PacketNumber, 0, len(parent.retransmittedAs)-1) + for _, pn := range parent.retransmittedAs { + if pn != p.PacketNumber { + retransmittedAs = append(retransmittedAs, pn) + } + } + parent.retransmittedAs = retransmittedAs + } + } + } + // this also applies to packets that have been retransmitted as probe packets + if p.includedInBytesInFlight { + h.bytesInFlight -= p.Length + } + if h.rtoCount > 0 { + h.verifyRTO(p.PacketNumber) + } + if err := h.stopRetransmissionsFor(p); err != nil { + return err + } h.rtoCount = 0 h.handshakeCount = 0 // TODO(#497): h.tlpCount = 0 - - // find the first packet, from which on we can delete all retransmissions - // example: packet 10 was retransmitted as packet 11 and 12, and - // packet 12 was then retransmitted as 13. - // When receiving an ACK for packet 13, we can remove packets 12 and 13, - // but still need to keep 10 and 11. - first := p - for first.isRetransmission { - previous := h.packetHistory.GetPacket(first.retransmissionOf) - if previous == nil { - return fmt.Errorf("sent packet handler BUG: retransmitted packet for %d not found (should have been %d)", first.PacketNumber, first.retransmissionOf) - } - // if the retransmission of a packet was split, we can't remove it yet - if len(previous.retransmittedAs) > 1 { - break - } - first = previous - } - if first.isRetransmission { - root := h.packetHistory.GetPacket(first.retransmissionOf) - retransmittedAs := make([]protocol.PacketNumber, 0, len(root.retransmittedAs)-1) - for _, pn := range root.retransmittedAs { - if pn != first.PacketNumber { - retransmittedAs = append(retransmittedAs, pn) - } - } - root.retransmittedAs = retransmittedAs - } - return h.removeAllRetransmissions(first) + return h.packetHistory.Remove(p.PacketNumber) } -func (h *sentPacketHandler) removeAllRetransmissions(p *Packet) error { - if p.includedInBytesInFlight { - h.bytesInFlight -= p.Length - p.includedInBytesInFlight = false +func (h *sentPacketHandler) stopRetransmissionsFor(p *Packet) error { + if err := h.packetHistory.MarkCannotBeRetransmitted(p.PacketNumber); err != nil { + return err } - if p.queuedForRetransmission { - for _, r := range p.retransmittedAs { - packet := h.packetHistory.GetPacket(r) - if packet == nil { - return fmt.Errorf("sent packet handler BUG: removing packet %d (retransmission of %d) not found in history", r, p.PacketNumber) - } - if err := h.removeAllRetransmissions(packet); err != nil { - return err - } + for _, r := range p.retransmittedAs { + packet := h.packetHistory.GetPacket(r) + if packet == nil { + return fmt.Errorf("sent packet handler BUG: marking packet as not retransmittable %d (retransmission of %d) not found in history", r, p.PacketNumber) } + h.stopRetransmissionsFor(packet) } - return h.packetHistory.Remove(p.PacketNumber) + return nil +} + +func (h *sentPacketHandler) verifyRTO(pn protocol.PacketNumber) { + if pn <= h.largestSentBeforeRTO { + h.logger.Debugf("Spurious RTO detected. Received an ACK for %#x (largest sent before RTO: %#x)", pn, h.largestSentBeforeRTO) + // Replace SRTT with latest_rtt and increase the variance to prevent + // a spurious RTO from happening again. + h.rttStats.ExpireSmoothedMetrics() + return + } + h.logger.Debugf("RTO verified. Received an ACK for %#x (largest sent before RTO: %#x", pn, h.largestSentBeforeRTO) + h.congestion.OnRetransmissionTimeout(true) } func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet { @@ -438,20 +463,23 @@ func (h *sentPacketHandler) SendMode() SendMode { // we will stop sending out new data when reaching MaxOutstandingSentPackets, // but still allow sending of retransmissions and ACKs. if numTrackedPackets >= protocol.MaxTrackedSentPackets { - utils.Debugf("Limited by the number of tracked packets: tracking %d packets, maximum %d", numTrackedPackets, protocol.MaxTrackedSentPackets) + h.logger.Debugf("Limited by the number of tracked packets: tracking %d packets, maximum %d", numTrackedPackets, protocol.MaxTrackedSentPackets) return SendNone } + if h.numRTOs > 0 { + return SendRTO + } + // Only send ACKs if we're congestion limited. + if cwnd := h.congestion.GetCongestionWindow(); h.bytesInFlight > cwnd { + h.logger.Debugf("Congestion limited: bytes in flight %d, window %d", h.bytesInFlight, cwnd) + return SendAck + } // Send retransmissions first, if there are any. if len(h.retransmissionQueue) > 0 { return SendRetransmission } - // Only send ACKs if we're congestion limited. - if cwnd := h.congestion.GetCongestionWindow(); h.bytesInFlight > cwnd { - utils.Debugf("Congestion limited: bytes in flight %d, window %d", h.bytesInFlight, cwnd) - return SendAck - } if numTrackedPackets >= protocol.MaxOutstandingSentPackets { - utils.Debugf("Max outstanding limited: tracking %d packets, maximum: %d", numTrackedPackets, protocol.MaxOutstandingSentPackets) + h.logger.Debugf("Max outstanding limited: tracking %d packets, maximum: %d", numTrackedPackets, protocol.MaxOutstandingSentPackets) return SendAck } return SendAny @@ -462,6 +490,10 @@ func (h *sentPacketHandler) TimeUntilSend() time.Time { } func (h *sentPacketHandler) ShouldSendNumPackets() int { + if h.numRTOs > 0 { + // RTO probes should not be paced, but must be sent immediately. + return h.numRTOs + } delay := h.congestion.TimeUntilSend(h.bytesInFlight) if delay == 0 || delay > protocol.MinPacingDelay { return 1 @@ -471,14 +503,16 @@ func (h *sentPacketHandler) ShouldSendNumPackets() int { // retransmit the oldest two packets func (h *sentPacketHandler) queueRTOs() error { + h.largestSentBeforeRTO = h.lastSentPacketNumber + // Queue the first two outstanding packets for retransmission. + // This does NOT declare this packets as lost: + // They are still tracked in the packet history and count towards the bytes in flight. for i := 0; i < 2; i++ { if p := h.packetHistory.FirstOutstanding(); p != nil { - utils.Debugf("\tQueueing packet %#x for retransmission (RTO), %d outstanding", p.PacketNumber, h.packetHistory.Len()) + h.logger.Debugf("\tQueueing packet %#x for retransmission (RTO)", p.PacketNumber) if err := h.queuePacketForRetransmission(p); err != nil { return err } - h.congestion.OnPacketLost(p.PacketNumber, p.Length, h.bytesInFlight) - h.congestion.OnRetransmissionTimeout(true) } } return nil @@ -487,12 +521,13 @@ func (h *sentPacketHandler) queueRTOs() error { func (h *sentPacketHandler) queueHandshakePacketsForRetransmission() error { var handshakePackets []*Packet h.packetHistory.Iterate(func(p *Packet) (bool, error) { - if !p.queuedForRetransmission && p.EncryptionLevel < protocol.EncryptionForwardSecure { + if p.canBeRetransmitted && p.EncryptionLevel < protocol.EncryptionForwardSecure { handshakePackets = append(handshakePackets, p) } return true, nil }) for _, p := range handshakePackets { + h.logger.Debugf("\tQueueing packet %#x as a handshake retransmission", p.PacketNumber) if err := h.queuePacketForRetransmission(p); err != nil { return err } @@ -501,7 +536,10 @@ func (h *sentPacketHandler) queueHandshakePacketsForRetransmission() error { } func (h *sentPacketHandler) queuePacketForRetransmission(p *Packet) error { - if _, err := h.packetHistory.QueuePacketForRetransmission(p.PacketNumber); err != nil { + if !p.canBeRetransmitted { + return fmt.Errorf("sent packet handler BUG: packet %d already queued for retransmission", p.PacketNumber) + } + if err := h.packetHistory.MarkCannotBeRetransmitted(p.PacketNumber); err != nil { return err } h.retransmissionQueue = append(h.retransmissionQueue, p) @@ -521,9 +559,12 @@ func (h *sentPacketHandler) computeHandshakeTimeout() time.Duration { } func (h *sentPacketHandler) computeRTOTimeout() time.Duration { - rto := h.congestion.RetransmissionDelay() - if rto == 0 { + var rto time.Duration + rtt := h.rttStats.SmoothedRTT() + if rtt == 0 { rto = defaultRTOTimeout + } else { + rto = rtt + 4*h.rttStats.MeanDeviation() } rto = utils.MaxDuration(rto, minRTOTimeout) // Exponential backoff diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go index f815b8542..38a2a0e50 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go @@ -87,26 +87,23 @@ func (h *sentPacketHistory) FirstOutstanding() *Packet { // QueuePacketForRetransmission marks a packet for retransmission. // A packet can only be queued once. -func (h *sentPacketHistory) QueuePacketForRetransmission(pn protocol.PacketNumber) (*Packet, error) { +func (h *sentPacketHistory) MarkCannotBeRetransmitted(pn protocol.PacketNumber) error { el, ok := h.packetMap[pn] if !ok { - return nil, fmt.Errorf("sent packet history: packet %d not found", pn) + return fmt.Errorf("sent packet history: packet %d not found", pn) } - if el.Value.queuedForRetransmission { - return nil, fmt.Errorf("sent packet history BUG: packet %d already queued for retransmission", pn) - } - el.Value.queuedForRetransmission = true + el.Value.canBeRetransmitted = false if el == h.firstOutstanding { h.readjustFirstOutstanding() } - return &el.Value, nil + return nil } // readjustFirstOutstanding readjusts the pointer to the first outstanding packet. // This is necessary every time the first outstanding packet is deleted or retransmitted. func (h *sentPacketHistory) readjustFirstOutstanding() { el := h.firstOutstanding.Next() - for el != nil && el.Value.queuedForRetransmission { + for el != nil && !el.Value.canBeRetransmitted { el = el.Next() } h.firstOutstanding = el diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go index 1ab59535f..21f019424 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go @@ -292,11 +292,3 @@ func (c *cubicSender) OnConnectionMigration() { func (c *cubicSender) SetSlowStartLargeReduction(enabled bool) { c.slowStartLargeReduction = enabled } - -// RetransmissionDelay gives the time to retransmission -func (c *cubicSender) RetransmissionDelay() time.Duration { - if c.rttStats.SmoothedRTT() == 0 { - return 0 - } - return c.rttStats.SmoothedRTT() + c.rttStats.MeanDeviation()*4 -} diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go index 3c09428fd..28950dd0c 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go @@ -17,7 +17,6 @@ type SendAlgorithm interface { SetNumEmulatedConnections(n int) OnRetransmissionTimeout(packetsRetransmitted bool) OnConnectionMigration() - RetransmissionDelay() time.Duration // Experiments SetSlowStartLargeReduction(enabled bool) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go index 9e5e4541a..599e350fb 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go @@ -84,7 +84,6 @@ func (r *RTTStats) SetRecentMinRTTwindow(recentMinRTTwindow time.Duration) { // UpdateRTT updates the RTT based on a new sample. func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) { if sendDelta == utils.InfDuration || sendDelta <= 0 { - utils.Debugf("Ignoring measured sendDelta, because it's is either infinite, zero, or negative: %d", sendDelta/time.Microsecond) return } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go index a570d6b31..fd25b00fc 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go @@ -21,10 +21,6 @@ func NewCurve25519KEX() (KeyExchange, error) { if _, err := rand.Read(c.secret[:]); err != nil { return nil, errors.New("Curve25519: could not create private key") } - // See https://cr.yp.to/ecdh.html - c.secret[0] &= 248 - c.secret[31] &= 127 - c.secret[31] |= 64 curve25519.ScalarBaseMult(&c.public, &c.secret) return c, nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go index 5cffba590..89b9e1f12 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go @@ -20,9 +20,7 @@ type TLSExporter interface { } func qhkdfExpand(secret []byte, label string, length int) []byte { - // The last byte should be 0x0. - // Since Go initializes the slice to 0, we don't need to set it explicitly. - qlabel := make([]byte, 2+1+5+len(label)+1) + qlabel := make([]byte, 2+1+5+len(label)) binary.BigEndian.PutUint16(qlabel[0:2], uint16(length)) qlabel[2] = uint8(5 + len(label)) copy(qlabel[3:], []byte("QUIC "+label)) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go index 0b192b52b..92c6362f4 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go @@ -8,7 +8,7 @@ import ( "github.com/lucas-clemente/quic-go/internal/protocol" ) -var quicVersion1Salt = []byte{0xaf, 0xc8, 0x24, 0xec, 0x5f, 0xc7, 0x7e, 0xca, 0x1e, 0x9d, 0x36, 0xf3, 0x7f, 0xb2, 0xd4, 0x65, 0x18, 0xc3, 0x66, 0x39} +var quicVersion1Salt = []byte{0x9c, 0x10, 0x8f, 0x98, 0x52, 0x0a, 0x5c, 0x5c, 0x32, 0x96, 0x8e, 0x95, 0x0e, 0x8a, 0x2c, 0x5f, 0xe0, 0x6d, 0x6c, 0x38} func newNullAEADAESGCM(connectionID protocol.ConnectionID, pers protocol.Perspective) (AEAD, error) { clientSecret, serverSecret := computeSecrets(connectionID) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go index ecc4010bd..6c50ab908 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go @@ -1,10 +1,11 @@ package crypto import ( - "encoding/binary" + "bytes" "errors" + "fmt" + "hash/fnv" - "github.com/lucas-clemente/fnv128a" "github.com/lucas-clemente/quic-go/internal/protocol" ) @@ -21,7 +22,7 @@ func (n *nullAEADFNV128a) Open(dst, src []byte, packetNumber protocol.PacketNumb return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long") } - hash := fnv128a.New() + hash := fnv.New128a() hash.Write(associatedData) hash.Write(src[12:]) if n.perspective == protocol.PerspectiveServer { @@ -29,13 +30,13 @@ func (n *nullAEADFNV128a) Open(dst, src []byte, packetNumber protocol.PacketNumb } else { hash.Write([]byte("Server")) } - testHigh, testLow := hash.Sum128() + sum := make([]byte, 0, 16) + sum = hash.Sum(sum) + // The tag is written in little endian, so we need to reverse the slice. + reverse(sum) - low := binary.LittleEndian.Uint64(src) - high := binary.LittleEndian.Uint32(src[8:]) - - if uint32(testHigh&0xffffffff) != high || testLow != low { - return nil, errors.New("NullAEAD: failed to authenticate received data") + if !bytes.Equal(sum[:12], src[:12]) { + return nil, fmt.Errorf("NullAEAD: failed to authenticate received data (%#v vs %#v)", sum[:12], src[:12]) } return src[12:], nil } @@ -48,7 +49,7 @@ func (n *nullAEADFNV128a) Seal(dst, src []byte, packetNumber protocol.PacketNumb dst = dst[:12+len(src)] } - hash := fnv128a.New() + hash := fnv.New128a() hash.Write(associatedData) hash.Write(src) @@ -57,15 +58,22 @@ func (n *nullAEADFNV128a) Seal(dst, src []byte, packetNumber protocol.PacketNumb } else { hash.Write([]byte("Client")) } - - high, low := hash.Sum128() + sum := make([]byte, 0, 16) + sum = hash.Sum(sum) + // The tag is written in little endian, so we need to reverse the slice. + reverse(sum) copy(dst[12:], src) - binary.LittleEndian.PutUint64(dst, low) - binary.LittleEndian.PutUint32(dst[8:], uint32(high)) + copy(dst, sum[:12]) return dst } func (n *nullAEADFNV128a) Overhead() int { return 12 } + +func reverse(a []byte) { + for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 { + a[left], a[right] = a[right], a[left] + } +} diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go index 3a5c01615..fb92f0842 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go @@ -25,6 +25,8 @@ type baseFlowController struct { epochStartTime time.Time epochStartOffset protocol.ByteCount rttStats *congestion.RTTStats + + logger utils.Logger } func (c *baseFlowController) AddBytesSent(n protocol.ByteCount) { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go index 975cc5836..c4f6e125e 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go @@ -22,6 +22,7 @@ func NewConnectionFlowController( receiveWindow protocol.ByteCount, maxReceiveWindow protocol.ByteCount, rttStats *congestion.RTTStats, + logger utils.Logger, ) ConnectionFlowController { return &connectionFlowController{ baseFlowController: baseFlowController{ @@ -29,6 +30,7 @@ func NewConnectionFlowController( receiveWindow: receiveWindow, receiveWindowSize: receiveWindow, maxReceiveWindowSize: maxReceiveWindow, + logger: logger, }, } } @@ -65,7 +67,7 @@ func (c *connectionFlowController) GetWindowUpdate() protocol.ByteCount { oldWindowSize := c.receiveWindowSize offset := c.baseFlowController.getWindowUpdate() if oldWindowSize < c.receiveWindowSize { - utils.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10)) + c.logger.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10)) } c.mutex.Unlock() return offset diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go index 51ecfe7f0..16bef2613 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go @@ -31,6 +31,7 @@ func NewStreamFlowController( maxReceiveWindow protocol.ByteCount, initialSendWindow protocol.ByteCount, rttStats *congestion.RTTStats, + logger utils.Logger, ) StreamFlowController { return &streamFlowController{ streamID: streamID, @@ -42,6 +43,7 @@ func NewStreamFlowController( receiveWindowSize: receiveWindow, maxReceiveWindowSize: maxReceiveWindow, sendWindow: initialSendWindow, + logger: logger, }, } } @@ -137,7 +139,7 @@ func (c *streamFlowController) GetWindowUpdate() protocol.ByteCount { oldWindowSize := c.receiveWindowSize offset := c.baseFlowController.getWindowUpdate() if c.receiveWindowSize > oldWindowSize { // auto-tuning enlarged the window size - utils.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10)) + c.logger.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10)) if c.contributesToConnection { c.connection.EnsureMinimumWindowSize(protocol.ByteCount(float64(c.receiveWindowSize) * protocol.ConnectionFlowControlMultiplier)) } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go index 4257745c0..bc2bd8e57 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go @@ -11,15 +11,16 @@ import ( // The cookie is sent in the TLS Retry. // By including the cookie in its ClientHello, a client can proof ownership of its source address. type CookieHandler struct { - callback func(net.Addr, *Cookie) bool - + callback func(net.Addr, *Cookie) bool cookieGenerator *CookieGenerator + + logger utils.Logger } var _ mint.CookieHandler = &CookieHandler{} // NewCookieHandler creates a new CookieHandler. -func NewCookieHandler(callback func(net.Addr, *Cookie) bool) (*CookieHandler, error) { +func NewCookieHandler(callback func(net.Addr, *Cookie) bool, logger utils.Logger) (*CookieHandler, error) { cookieGenerator, err := NewCookieGenerator() if err != nil { return nil, err @@ -27,6 +28,7 @@ func NewCookieHandler(callback func(net.Addr, *Cookie) bool) (*CookieHandler, er return &CookieHandler{ callback: callback, cookieGenerator: cookieGenerator, + logger: logger, }, nil } @@ -42,7 +44,7 @@ func (h *CookieHandler) Generate(conn *mint.Conn) ([]byte, error) { func (h *CookieHandler) Validate(conn *mint.Conn, token []byte) bool { data, err := h.cookieGenerator.DecodeToken(token) if err != nil { - utils.Debugf("Couldn't decode cookie from %s: %s", conn.RemoteAddr(), err.Error()) + h.logger.Debugf("Couldn't decode cookie from %s: %s", conn.RemoteAddr(), err.Error()) return false } return h.callback(conn.RemoteAddr(), data) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go index cb500b583..0700399a8 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go @@ -38,13 +38,12 @@ type cryptoSetupClient struct { lastSentCHLO []byte certManager crypto.CertManager - divNonceChan chan []byte + divNonceChan <-chan []byte diversificationNonce []byte clientHelloCounter int serverVerified bool // has the certificate chain and the proof already been verified keyDerivation QuicCryptoKeyDerivationFunction - keyExchange KeyExchangeFunction receivedSecurePacket bool nullAEAD crypto.AEAD @@ -55,6 +54,8 @@ type cryptoSetupClient struct { handshakeEvent chan<- struct{} params *TransportParameters + + logger utils.Logger } var _ CryptoSetup = &cryptoSetupClient{} @@ -77,12 +78,14 @@ func NewCryptoSetupClient( handshakeEvent chan<- struct{}, initialVersion protocol.VersionNumber, negotiatedVersions []protocol.VersionNumber, -) (CryptoSetup, error) { + logger utils.Logger, +) (CryptoSetup, chan<- []byte, error) { nullAEAD, err := crypto.NewNullAEAD(protocol.PerspectiveClient, connID, version) if err != nil { - return nil, err + return nil, nil, err } - return &cryptoSetupClient{ + divNonceChan := make(chan []byte) + cs := &cryptoSetupClient{ cryptoStream: cryptoStream, hostname: hostname, connID: connID, @@ -90,14 +93,15 @@ func NewCryptoSetupClient( certManager: crypto.NewCertManager(tlsConfig), params: params, keyDerivation: crypto.DeriveQuicCryptoAESKeys, - keyExchange: getEphermalKEX, nullAEAD: nullAEAD, paramsChan: paramsChan, handshakeEvent: handshakeEvent, initialVersion: initialVersion, negotiatedVersions: negotiatedVersions, - divNonceChan: make(chan []byte), - }, nil + divNonceChan: divNonceChan, + logger: logger, + } + return cs, divNonceChan, nil } func (h *cryptoSetupClient) HandleCryptoStream() error { @@ -146,7 +150,7 @@ func (h *cryptoSetupClient) HandleCryptoStream() error { return err } - utils.Debugf("Got %s", message) + h.logger.Debugf("Got %s", message) switch message.Tag { case TagREJ: if err := h.handleREJMessage(message.Data); err != nil { @@ -211,7 +215,7 @@ func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error { err = h.certManager.Verify(h.hostname) if err != nil { - utils.Infof("Certificate validation failed: %s", err.Error()) + h.logger.Infof("Certificate validation failed: %s", err.Error()) return qerr.ProofInvalid } } @@ -219,7 +223,7 @@ func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error { if h.serverConfig != nil && len(h.proof) != 0 && h.certManager.GetLeafCert() != nil { validProof := h.certManager.VerifyServerProof(h.proof, h.chloForSignature, h.serverConfig.Get()) if !validProof { - utils.Infof("Server proof verification failed") + h.logger.Infof("Server proof verification failed") return qerr.ProofInvalid } @@ -373,14 +377,6 @@ func (h *cryptoSetupClient) GetSealerWithEncryptionLevel(encLevel protocol.Encry return nil, errors.New("CryptoSetupClient: no encryption level specified") } -func (h *cryptoSetupClient) DiversificationNonce() []byte { - panic("not needed for cryptoSetupClient") -} - -func (h *cryptoSetupClient) SetDiversificationNonce(data []byte) { - h.divNonceChan <- data -} - func (h *cryptoSetupClient) ConnectionState() ConnectionState { h.mutex.Lock() defer h.mutex.Unlock() @@ -408,7 +404,7 @@ func (h *cryptoSetupClient) sendCHLO() error { Data: tags, } - utils.Debugf("Sending %s", message) + h.logger.Debugf("Sending %s", message) message.Write(b) _, err = h.cryptoStream.Write(b.Bytes()) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go index 54c2b9bd4..d977f6553 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go @@ -19,7 +19,7 @@ import ( type QuicCryptoKeyDerivationFunction func(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte, divNonce []byte, pers protocol.Perspective) (crypto.AEAD, error) // KeyExchangeFunction is used to make a new KEX -type KeyExchangeFunction func() crypto.KeyExchange +type KeyExchangeFunction func() (crypto.KeyExchange, error) // The CryptoSetupServer handles all things crypto for the Session type cryptoSetupServer struct { @@ -54,6 +54,8 @@ type cryptoSetupServer struct { params *TransportParameters sni string // need to fill out the ConnectionState + + logger utils.Logger } var _ CryptoSetup = &cryptoSetupServer{} @@ -73,32 +75,36 @@ func NewCryptoSetup( connID protocol.ConnectionID, remoteAddr net.Addr, version protocol.VersionNumber, + divNonce []byte, scfg *ServerConfig, params *TransportParameters, supportedVersions []protocol.VersionNumber, acceptSTK func(net.Addr, *Cookie) bool, paramsChan chan<- TransportParameters, handshakeEvent chan<- struct{}, + logger utils.Logger, ) (CryptoSetup, error) { nullAEAD, err := crypto.NewNullAEAD(protocol.PerspectiveServer, connID, version) if err != nil { return nil, err } return &cryptoSetupServer{ - cryptoStream: cryptoStream, - connID: connID, - remoteAddr: remoteAddr, - version: version, - supportedVersions: supportedVersions, - scfg: scfg, - keyDerivation: crypto.DeriveQuicCryptoAESKeys, - keyExchange: getEphermalKEX, - nullAEAD: nullAEAD, - params: params, - acceptSTKCallback: acceptSTK, - sentSHLO: make(chan struct{}), - paramsChan: paramsChan, - handshakeEvent: handshakeEvent, + cryptoStream: cryptoStream, + connID: connID, + remoteAddr: remoteAddr, + version: version, + supportedVersions: supportedVersions, + diversificationNonce: divNonce, + scfg: scfg, + keyDerivation: crypto.DeriveQuicCryptoAESKeys, + keyExchange: getEphermalKEX, + nullAEAD: nullAEAD, + params: params, + acceptSTKCallback: acceptSTK, + sentSHLO: make(chan struct{}), + paramsChan: paramsChan, + handshakeEvent: handshakeEvent, + logger: logger, }, nil } @@ -114,7 +120,7 @@ func (h *cryptoSetupServer) HandleCryptoStream() error { return qerr.InvalidCryptoMessageType } - utils.Debugf("Got %s", message) + h.logger.Debugf("Got %s", message) done, err := h.handleMessage(chloData.Bytes(), message.Data) if err != nil { return err @@ -297,7 +303,7 @@ func (h *cryptoSetupServer) isInchoateCHLO(cryptoData map[Tag][]byte, cert []byt func (h *cryptoSetupServer) acceptSTK(token []byte) bool { stk, err := h.scfg.cookieGenerator.DecodeToken(token) if err != nil { - utils.Debugf("STK invalid: %s", err.Error()) + h.logger.Debugf("STK invalid: %s", err.Error()) return false } return h.acceptSTKCallback(h.remoteAddr, stk) @@ -340,7 +346,7 @@ func (h *cryptoSetupServer) handleInchoateCHLO(sni string, chlo []byte, cryptoDa var serverReply bytes.Buffer message.Write(&serverReply) - utils.Debugf("Sending %s", message) + h.logger.Debugf("Sending %s", message) return serverReply.Bytes(), nil } @@ -364,11 +370,6 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T return nil, err } - h.diversificationNonce = make([]byte, 32) - if _, err = rand.Read(h.diversificationNonce); err != nil { - return nil, err - } - clientNonce := cryptoData[TagNONC] err = h.validateClientNonce(clientNonce) if err != nil { @@ -405,7 +406,10 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T var fsNonce bytes.Buffer fsNonce.Write(clientNonce) fsNonce.Write(serverNonce) - ephermalKex := h.keyExchange() + ephermalKex, err := h.keyExchange() + if err != nil { + return nil, err + } ephermalSharedSecret, err := ephermalKex.CalculateSharedKey(cryptoData[TagPUBS]) if err != nil { return nil, err @@ -443,19 +447,10 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T } var reply bytes.Buffer message.Write(&reply) - utils.Debugf("Sending %s", message) + h.logger.Debugf("Sending %s", message) return reply.Bytes(), nil } -// DiversificationNonce returns the diversification nonce -func (h *cryptoSetupServer) DiversificationNonce() []byte { - return h.diversificationNonce -} - -func (h *cryptoSetupServer) SetDiversificationNonce(data []byte) { - panic("not needed for cryptoSetupServer") -} - func (h *cryptoSetupServer) ConnectionState() ConnectionState { h.mutex.Lock() defer h.mutex.Unlock() diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go index 54dfe1c03..43f854068 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go @@ -31,6 +31,8 @@ type cryptoSetupTLS struct { handshakeEvent chan<- struct{} } +var _ CryptoSetupTLS = &cryptoSetupTLS{} + // NewCryptoSetupTLSServer creates a new TLS CryptoSetup instance for a server func NewCryptoSetupTLSServer( tls MintTLS, @@ -38,7 +40,7 @@ func NewCryptoSetupTLSServer( nullAEAD crypto.AEAD, handshakeEvent chan<- struct{}, version protocol.VersionNumber, -) CryptoSetup { +) CryptoSetupTLS { return &cryptoSetupTLS{ tls: tls, cryptoStream: cryptoStream, @@ -57,7 +59,7 @@ func NewCryptoSetupTLSClient( handshakeEvent chan<- struct{}, tls MintTLS, version protocol.VersionNumber, -) (CryptoSetup, error) { +) (CryptoSetupTLS, error) { nullAEAD, err := crypto.NewNullAEAD(protocol.PerspectiveClient, connID, version) if err != nil { return nil, err @@ -107,22 +109,18 @@ handshakeLoop: return nil } -func (h *cryptoSetupTLS) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) { +func (h *cryptoSetupTLS) OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + return h.nullAEAD.Open(dst, src, packetNumber, associatedData) +} + +func (h *cryptoSetupTLS) Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { h.mutex.RLock() defer h.mutex.RUnlock() - if h.aead != nil { - data, err := h.aead.Open(dst, src, packetNumber, associatedData) - if err != nil { - return nil, protocol.EncryptionUnspecified, err - } - return data, protocol.EncryptionForwardSecure, nil + if h.aead == nil { + return nil, errors.New("no 1-RTT sealer") } - data, err := h.nullAEAD.Open(dst, src, packetNumber, associatedData) - if err != nil { - return nil, protocol.EncryptionUnspecified, err - } - return data, protocol.EncryptionUnencrypted, nil + return h.aead.Open(dst, src, packetNumber, associatedData) } func (h *cryptoSetupTLS) GetSealer() (protocol.EncryptionLevel, Sealer) { @@ -157,14 +155,6 @@ func (h *cryptoSetupTLS) GetSealerForCryptoStream() (protocol.EncryptionLevel, S return protocol.EncryptionUnencrypted, h.nullAEAD } -func (h *cryptoSetupTLS) DiversificationNonce() []byte { - panic("diversification nonce not needed for TLS") -} - -func (h *cryptoSetupTLS) SetDiversificationNonce([]byte) { - panic("diversification nonce not needed for TLS") -} - func (h *cryptoSetupTLS) ConnectionState() ConnectionState { h.mutex.Lock() defer h.mutex.Unlock() diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go index 3bccbef06..728715835 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go @@ -6,7 +6,6 @@ import ( "github.com/lucas-clemente/quic-go/internal/crypto" "github.com/lucas-clemente/quic-go/internal/protocol" - "github.com/lucas-clemente/quic-go/internal/utils" ) var ( @@ -24,13 +23,13 @@ var ( // used for all connections for 60 seconds is negligible. Thus we can amortise // the Diffie-Hellman key generation at the server over all the connections in a // small time span. -func getEphermalKEX() (res crypto.KeyExchange) { +func getEphermalKEX() (crypto.KeyExchange, error) { kexMutex.RLock() - res = kexCurrent + res := kexCurrent t := kexCurrentTime kexMutex.RUnlock() if res != nil && time.Since(t) < kexLifetime { - return res + return res, nil } kexMutex.Lock() @@ -39,12 +38,11 @@ func getEphermalKEX() (res crypto.KeyExchange) { if kexCurrent == nil || time.Since(kexCurrentTime) > kexLifetime { kex, err := crypto.NewCurve25519KEX() if err != nil { - utils.Errorf("could not set KEX: %s", err.Error()) - return kexCurrent + return nil, err } kexCurrent = kex kexCurrentTime = time.Now() - return kexCurrent + return kexCurrent, nil } - return kexCurrent + return kexCurrent, nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go index 0fd673313..8d8fd5455 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go @@ -35,13 +35,8 @@ type MintTLS interface { SetCryptoStream(io.ReadWriter) } -// CryptoSetup is a crypto setup -type CryptoSetup interface { - Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) +type baseCryptoSetup interface { HandleCryptoStream() error - // TODO: clean up this interface - DiversificationNonce() []byte // only needed for cryptoSetupServer - SetDiversificationNonce([]byte) // only needed for cryptoSetupClient ConnectionState() ConnectionState GetSealer() (protocol.EncryptionLevel, Sealer) @@ -49,6 +44,21 @@ type CryptoSetup interface { GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) } +// CryptoSetup is the crypto setup used by gQUIC +type CryptoSetup interface { + baseCryptoSetup + + Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) +} + +// CryptoSetupTLS is the crypto setup used by IETF QUIC +type CryptoSetupTLS interface { + baseCryptoSetup + + OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) + Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) +} + // ConnectionState records basic details about the QUIC connection. // Warning: This API should not be considered stable and might change soon. type ConnectionState struct { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go index 765cf79fc..8e711be58 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go @@ -19,6 +19,8 @@ type extensionHandlerClient struct { initialVersion protocol.VersionNumber supportedVersions []protocol.VersionNumber version protocol.VersionNumber + + logger utils.Logger } var _ mint.AppExtensionHandler = &extensionHandlerClient{} @@ -30,6 +32,7 @@ func NewExtensionHandlerClient( initialVersion protocol.VersionNumber, supportedVersions []protocol.VersionNumber, version protocol.VersionNumber, + logger utils.Logger, ) TLSExtensionHandler { // The client reads the transport parameters from the Encrypted Extensions message. // The paramsChan is used in the session's run loop's select statement. @@ -41,6 +44,7 @@ func NewExtensionHandlerClient( initialVersion: initialVersion, supportedVersions: supportedVersions, version: version, + logger: logger, } } @@ -49,7 +53,7 @@ func (h *extensionHandlerClient) Send(hType mint.HandshakeType, el *mint.Extensi return nil } - utils.Debugf("Sending Transport Parameters: %s", h.ourParams) + h.logger.Debugf("Sending Transport Parameters: %s", h.ourParams) data, err := syntax.Marshal(clientHelloTransportParameters{ InitialVersion: uint32(h.initialVersion), Parameters: h.ourParams.getTransportParameters(), @@ -122,7 +126,7 @@ func (h *extensionHandlerClient) Receive(hType mint.HandshakeType, el *mint.Exte if err != nil { return err } - utils.Debugf("Received Transport Parameters: %s", params) + h.logger.Debugf("Received Transport Parameters: %s", params) h.paramsChan <- *params return nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go index ec73585c8..138fc21bd 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go @@ -19,6 +19,8 @@ type extensionHandlerServer struct { version protocol.VersionNumber supportedVersions []protocol.VersionNumber + + logger utils.Logger } var _ mint.AppExtensionHandler = &extensionHandlerServer{} @@ -29,6 +31,7 @@ func NewExtensionHandlerServer( params *TransportParameters, supportedVersions []protocol.VersionNumber, version protocol.VersionNumber, + logger utils.Logger, ) TLSExtensionHandler { // Processing the ClientHello is performed statelessly (and from a single go-routine). // Therefore, we have to use a buffered chan to pass the transport parameters to that go routine. @@ -38,6 +41,7 @@ func NewExtensionHandlerServer( paramsChan: paramsChan, supportedVersions: supportedVersions, version: version, + logger: logger, } } @@ -56,7 +60,7 @@ func (h *extensionHandlerServer) Send(hType mint.HandshakeType, el *mint.Extensi for i, v := range supportedVersions { versions[i] = uint32(v) } - utils.Debugf("Sending Transport Parameters: %s", h.ourParams) + h.logger.Debugf("Sending Transport Parameters: %s", h.ourParams) data, err := syntax.Marshal(encryptedExtensionsTransportParameters{ NegotiatedVersion: uint32(h.version), SupportedVersions: versions, @@ -108,7 +112,7 @@ func (h *extensionHandlerServer) Receive(hType mint.HandshakeType, el *mint.Exte if err != nil { return err } - utils.Debugf("Received Transport Parameters: %s", params) + h.logger.Debugf("Received Transport Parameters: %s", params) h.paramsChan <- *params return nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go b/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go index fec7b6c14..b86ccfea6 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go @@ -109,18 +109,6 @@ func (mr *MockSendAlgorithmMockRecorder) OnRetransmissionTimeout(arg0 interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnRetransmissionTimeout", reflect.TypeOf((*MockSendAlgorithm)(nil).OnRetransmissionTimeout), arg0) } -// RetransmissionDelay mocks base method -func (m *MockSendAlgorithm) RetransmissionDelay() time.Duration { - ret := m.ctrl.Call(m, "RetransmissionDelay") - ret0, _ := ret[0].(time.Duration) - return ret0 -} - -// RetransmissionDelay indicates an expected call of RetransmissionDelay -func (mr *MockSendAlgorithmMockRecorder) RetransmissionDelay() *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetransmissionDelay", reflect.TypeOf((*MockSendAlgorithm)(nil).RetransmissionDelay)) -} - // SetNumEmulatedConnections mocks base method func (m *MockSendAlgorithm) SetNumEmulatedConnections(arg0 int) { m.ctrl.Call(m, "SetNumEmulatedConnections", arg0) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go index 545fc2038..096023ef2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go @@ -1,13 +1,10 @@ -// Generated by: main -// TypeWriter: linkedlist -// Directive: +gen on ByteInterval +// This file was automatically generated by genny. +// Any changes will be lost if this file is regenerated. +// see https://github.com/cheekybits/genny package utils -// List is a modification of http://golang.org/pkg/container/list/ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Linked list implementation from the Go standard library. // ByteIntervalElement is an element of a linked list. type ByteIntervalElement struct { @@ -41,8 +38,7 @@ func (e *ByteIntervalElement) Prev() *ByteIntervalElement { return nil } -// ByteIntervalList represents a doubly linked list. -// The zero value for ByteIntervalList is an empty list ready to use. +// ByteIntervalList is a linked list of ByteIntervals. type ByteIntervalList struct { root ByteIntervalElement // sentinel list element, only &root, root.prev, and root.next are used len int // current list length excluding (this) sentinel element @@ -63,7 +59,7 @@ func NewByteIntervalList() *ByteIntervalList { return new(ByteIntervalList).Init // The complexity is O(1). func (l *ByteIntervalList) Len() int { return l.len } -// Front returns the first element of list l or nil. +// Front returns the first element of list l or nil if the list is empty. func (l *ByteIntervalList) Front() *ByteIntervalElement { if l.len == 0 { return nil @@ -71,7 +67,7 @@ func (l *ByteIntervalList) Front() *ByteIntervalElement { return l.root.next } -// Back returns the last element of list l or nil. +// Back returns the last element of list l or nil if the list is empty. func (l *ByteIntervalList) Back() *ByteIntervalElement { if l.len == 0 { return nil @@ -79,7 +75,7 @@ func (l *ByteIntervalList) Back() *ByteIntervalElement { return l.root.prev } -// lazyInit lazily initializes a zero ByteIntervalList value. +// lazyInit lazily initializes a zero List value. func (l *ByteIntervalList) lazyInit() { if l.root.next == nil { l.Init() @@ -98,7 +94,7 @@ func (l *ByteIntervalList) insert(e, at *ByteIntervalElement) *ByteIntervalEleme return e } -// insertValue is a convenience wrapper for insert(&ByteIntervalElement{Value: v}, at). +// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). func (l *ByteIntervalList) insertValue(v ByteInterval, at *ByteIntervalElement) *ByteIntervalElement { return l.insert(&ByteIntervalElement{Value: v}, at) } @@ -116,10 +112,11 @@ func (l *ByteIntervalList) remove(e *ByteIntervalElement) *ByteIntervalElement { // Remove removes e from l if e is an element of list l. // It returns the element value e.Value. +// The element must not be nil. func (l *ByteIntervalList) Remove(e *ByteIntervalElement) ByteInterval { if e.list == l { // if e.list == l, l must have been initialized when e was inserted - // in l or l == nil (e is a zero ByteIntervalElement) and l.remove will crash + // in l or l == nil (e is a zero Element) and l.remove will crash l.remove(e) } return e.Value @@ -139,46 +136,51 @@ func (l *ByteIntervalList) PushBack(v ByteInterval) *ByteIntervalElement { // InsertBefore inserts a new element e with value v immediately before mark and returns e. // If mark is not an element of l, the list is not modified. +// The mark must not be nil. func (l *ByteIntervalList) InsertBefore(v ByteInterval, mark *ByteIntervalElement) *ByteIntervalElement { if mark.list != l { return nil } - // see comment in ByteIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l return l.insertValue(v, mark.prev) } // InsertAfter inserts a new element e with value v immediately after mark and returns e. // If mark is not an element of l, the list is not modified. +// The mark must not be nil. func (l *ByteIntervalList) InsertAfter(v ByteInterval, mark *ByteIntervalElement) *ByteIntervalElement { if mark.list != l { return nil } - // see comment in ByteIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l return l.insertValue(v, mark) } // MoveToFront moves element e to the front of list l. // If e is not an element of l, the list is not modified. +// The element must not be nil. func (l *ByteIntervalList) MoveToFront(e *ByteIntervalElement) { if e.list != l || l.root.next == e { return } - // see comment in ByteIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l l.insert(l.remove(e), &l.root) } // MoveToBack moves element e to the back of list l. // If e is not an element of l, the list is not modified. +// The element must not be nil. func (l *ByteIntervalList) MoveToBack(e *ByteIntervalElement) { if e.list != l || l.root.prev == e { return } - // see comment in ByteIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l l.insert(l.remove(e), l.root.prev) } // MoveBefore moves element e to its new position before mark. // If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. func (l *ByteIntervalList) MoveBefore(e, mark *ByteIntervalElement) { if e.list != l || e == mark || mark.list != l { return @@ -187,7 +189,8 @@ func (l *ByteIntervalList) MoveBefore(e, mark *ByteIntervalElement) { } // MoveAfter moves element e to its new position after mark. -// If e is not an element of l, or e == mark, the list is not modified. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. func (l *ByteIntervalList) MoveAfter(e, mark *ByteIntervalElement) { if e.list != l || e == mark || mark.list != l { return @@ -196,7 +199,7 @@ func (l *ByteIntervalList) MoveAfter(e, mark *ByteIntervalElement) { } // PushBackList inserts a copy of an other list at the back of list l. -// The lists l and other may be the same. +// The lists l and other may be the same. They must not be nil. func (l *ByteIntervalList) PushBackList(other *ByteIntervalList) { l.lazyInit() for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { @@ -205,7 +208,7 @@ func (l *ByteIntervalList) PushBackList(other *ByteIntervalList) { } // PushFrontList inserts a copy of an other list at the front of list l. -// The lists l and other may be the same. +// The lists l and other may be the same. They must not be nil. func (l *ByteIntervalList) PushFrontList(other *ByteIntervalList) { l.lazyInit() for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go new file mode 100644 index 000000000..bb839be66 --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go @@ -0,0 +1,4 @@ +package utils + +//go:generate genny -pkg utils -in linkedlist/linkedlist.go -out byteinterval_linkedlist.go gen Item=ByteInterval +//go:generate genny -pkg utils -in linkedlist/linkedlist.go -out packetinterval_linkedlist.go gen Item=PacketInterval diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go new file mode 100644 index 000000000..74b815a81 --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go @@ -0,0 +1,218 @@ +package linkedlist + +import "github.com/cheekybits/genny/generic" + +// Linked list implementation from the Go standard library. + +// Item is a generic type. +type Item generic.Type + +// ItemElement is an element of a linked list. +type ItemElement struct { + // Next and previous pointers in the doubly-linked list of elements. + // To simplify the implementation, internally a list l is implemented + // as a ring, such that &l.root is both the next element of the last + // list element (l.Back()) and the previous element of the first list + // element (l.Front()). + next, prev *ItemElement + + // The list to which this element belongs. + list *ItemList + + // The value stored with this element. + Value Item +} + +// Next returns the next list element or nil. +func (e *ItemElement) Next() *ItemElement { + if p := e.next; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// Prev returns the previous list element or nil. +func (e *ItemElement) Prev() *ItemElement { + if p := e.prev; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// ItemList is a linked list of Items. +type ItemList struct { + root ItemElement // sentinel list element, only &root, root.prev, and root.next are used + len int // current list length excluding (this) sentinel element +} + +// Init initializes or clears list l. +func (l *ItemList) Init() *ItemList { + l.root.next = &l.root + l.root.prev = &l.root + l.len = 0 + return l +} + +// NewItemList returns an initialized list. +func NewItemList() *ItemList { return new(ItemList).Init() } + +// Len returns the number of elements of list l. +// The complexity is O(1). +func (l *ItemList) Len() int { return l.len } + +// Front returns the first element of list l or nil if the list is empty. +func (l *ItemList) Front() *ItemElement { + if l.len == 0 { + return nil + } + return l.root.next +} + +// Back returns the last element of list l or nil if the list is empty. +func (l *ItemList) Back() *ItemElement { + if l.len == 0 { + return nil + } + return l.root.prev +} + +// lazyInit lazily initializes a zero List value. +func (l *ItemList) lazyInit() { + if l.root.next == nil { + l.Init() + } +} + +// insert inserts e after at, increments l.len, and returns e. +func (l *ItemList) insert(e, at *ItemElement) *ItemElement { + n := at.next + at.next = e + e.prev = at + e.next = n + n.prev = e + e.list = l + l.len++ + return e +} + +// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). +func (l *ItemList) insertValue(v Item, at *ItemElement) *ItemElement { + return l.insert(&ItemElement{Value: v}, at) +} + +// remove removes e from its list, decrements l.len, and returns e. +func (l *ItemList) remove(e *ItemElement) *ItemElement { + e.prev.next = e.next + e.next.prev = e.prev + e.next = nil // avoid memory leaks + e.prev = nil // avoid memory leaks + e.list = nil + l.len-- + return e +} + +// Remove removes e from l if e is an element of list l. +// It returns the element value e.Value. +// The element must not be nil. +func (l *ItemList) Remove(e *ItemElement) Item { + if e.list == l { + // if e.list == l, l must have been initialized when e was inserted + // in l or l == nil (e is a zero Element) and l.remove will crash + l.remove(e) + } + return e.Value +} + +// PushFront inserts a new element e with value v at the front of list l and returns e. +func (l *ItemList) PushFront(v Item) *ItemElement { + l.lazyInit() + return l.insertValue(v, &l.root) +} + +// PushBack inserts a new element e with value v at the back of list l and returns e. +func (l *ItemList) PushBack(v Item) *ItemElement { + l.lazyInit() + return l.insertValue(v, l.root.prev) +} + +// InsertBefore inserts a new element e with value v immediately before mark and returns e. +// If mark is not an element of l, the list is not modified. +// The mark must not be nil. +func (l *ItemList) InsertBefore(v Item, mark *ItemElement) *ItemElement { + if mark.list != l { + return nil + } + // see comment in List.Remove about initialization of l + return l.insertValue(v, mark.prev) +} + +// InsertAfter inserts a new element e with value v immediately after mark and returns e. +// If mark is not an element of l, the list is not modified. +// The mark must not be nil. +func (l *ItemList) InsertAfter(v Item, mark *ItemElement) *ItemElement { + if mark.list != l { + return nil + } + // see comment in List.Remove about initialization of l + return l.insertValue(v, mark) +} + +// MoveToFront moves element e to the front of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *ItemList) MoveToFront(e *ItemElement) { + if e.list != l || l.root.next == e { + return + } + // see comment in List.Remove about initialization of l + l.insert(l.remove(e), &l.root) +} + +// MoveToBack moves element e to the back of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *ItemList) MoveToBack(e *ItemElement) { + if e.list != l || l.root.prev == e { + return + } + // see comment in List.Remove about initialization of l + l.insert(l.remove(e), l.root.prev) +} + +// MoveBefore moves element e to its new position before mark. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. +func (l *ItemList) MoveBefore(e, mark *ItemElement) { + if e.list != l || e == mark || mark.list != l { + return + } + l.insert(l.remove(e), mark.prev) +} + +// MoveAfter moves element e to its new position after mark. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. +func (l *ItemList) MoveAfter(e, mark *ItemElement) { + if e.list != l || e == mark || mark.list != l { + return + } + l.insert(l.remove(e), mark) +} + +// PushBackList inserts a copy of an other list at the back of list l. +// The lists l and other may be the same. They must not be nil. +func (l *ItemList) PushBackList(other *ItemList) { + l.lazyInit() + for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { + l.insertValue(e.Value, l.root.prev) + } +} + +// PushFrontList inserts a copy of an other list at the front of list l. +// The lists l and other may be the same. They must not be nil. +func (l *ItemList) PushFrontList(other *ItemList) { + l.lazyInit() + for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { + l.insertValue(e.Value, &l.root) + } +} diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go index 342d8ddca..62a3d075e 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go @@ -11,8 +11,6 @@ import ( // LogLevel of quic-go type LogLevel uint8 -const logEnv = "QUIC_GO_LOG_LEVEL" - const ( // LogLevelNothing disables LogLevelNothing LogLevel = iota @@ -24,72 +22,92 @@ const ( LogLevelDebug ) -var ( - logLevel = LogLevelNothing - timeFormat = "" -) +const logEnv = "QUIC_GO_LOG_LEVEL" + +// A Logger logs. +type Logger interface { + SetLogLevel(LogLevel) + SetLogTimeFormat(format string) + Debug() bool + + Errorf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + Debugf(format string, args ...interface{}) +} + +// DefaultLogger is used by quic-go for logging. +var DefaultLogger Logger + +type defaultLogger struct { + logLevel LogLevel + timeFormat string +} + +var _ Logger = &defaultLogger{} // SetLogLevel sets the log level -func SetLogLevel(level LogLevel) { - logLevel = level +func (l *defaultLogger) SetLogLevel(level LogLevel) { + l.logLevel = level } // SetLogTimeFormat sets the format of the timestamp // an empty string disables the logging of timestamps -func SetLogTimeFormat(format string) { +func (l *defaultLogger) SetLogTimeFormat(format string) { log.SetFlags(0) // disable timestamp logging done by the log package - timeFormat = format + l.timeFormat = format } // Debugf logs something -func Debugf(format string, args ...interface{}) { - if logLevel == LogLevelDebug { - logMessage(format, args...) +func (l *defaultLogger) Debugf(format string, args ...interface{}) { + if l.logLevel == LogLevelDebug { + l.logMessage(format, args...) } } // Infof logs something -func Infof(format string, args ...interface{}) { - if logLevel >= LogLevelInfo { - logMessage(format, args...) +func (l *defaultLogger) Infof(format string, args ...interface{}) { + if l.logLevel >= LogLevelInfo { + l.logMessage(format, args...) } } // Errorf logs something -func Errorf(format string, args ...interface{}) { - if logLevel >= LogLevelError { - logMessage(format, args...) +func (l *defaultLogger) Errorf(format string, args ...interface{}) { + if l.logLevel >= LogLevelError { + l.logMessage(format, args...) } } -func logMessage(format string, args ...interface{}) { - if len(timeFormat) > 0 { - log.Printf(time.Now().Format(timeFormat)+" "+format, args...) +func (l *defaultLogger) logMessage(format string, args ...interface{}) { + if len(l.timeFormat) > 0 { + log.Printf(time.Now().Format(l.timeFormat)+" "+format, args...) } else { log.Printf(format, args...) } } // Debug returns true if the log level is LogLevelDebug -func Debug() bool { - return logLevel == LogLevelDebug +func (l *defaultLogger) Debug() bool { + return l.logLevel == LogLevelDebug } func init() { - readLoggingEnv() + DefaultLogger = &defaultLogger{} + DefaultLogger.SetLogLevel(readLoggingEnv()) } -func readLoggingEnv() { +func readLoggingEnv() LogLevel { switch strings.ToLower(os.Getenv(logEnv)) { case "": - return + return LogLevelNothing case "debug": - logLevel = LogLevelDebug + return LogLevelDebug case "info": - logLevel = LogLevelInfo + return LogLevelInfo case "error": - logLevel = LogLevelError + return LogLevelError default: fmt.Fprintln(os.Stderr, "invalid quic-go log level, see https://github.com/lucas-clemente/quic-go/wiki/Logging") + return LogLevelNothing } } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go index f49b0c426..62cc8b9cb 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go @@ -3,7 +3,6 @@ package utils import "github.com/lucas-clemente/quic-go/internal/protocol" // PacketInterval is an interval from one PacketNumber to the other -// +gen linkedlist type PacketInterval struct { Start protocol.PacketNumber End protocol.PacketNumber diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go index e3431d68c..b461e85a9 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go @@ -1,13 +1,10 @@ -// Generated by: main -// TypeWriter: linkedlist -// Directive: +gen on PacketInterval +// This file was automatically generated by genny. +// Any changes will be lost if this file is regenerated. +// see https://github.com/cheekybits/genny package utils -// List is a modification of http://golang.org/pkg/container/list/ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Linked list implementation from the Go standard library. // PacketIntervalElement is an element of a linked list. type PacketIntervalElement struct { @@ -41,8 +38,7 @@ func (e *PacketIntervalElement) Prev() *PacketIntervalElement { return nil } -// PacketIntervalList represents a doubly linked list. -// The zero value for PacketIntervalList is an empty list ready to use. +// PacketIntervalList is a linked list of PacketIntervals. type PacketIntervalList struct { root PacketIntervalElement // sentinel list element, only &root, root.prev, and root.next are used len int // current list length excluding (this) sentinel element @@ -63,7 +59,7 @@ func NewPacketIntervalList() *PacketIntervalList { return new(PacketIntervalList // The complexity is O(1). func (l *PacketIntervalList) Len() int { return l.len } -// Front returns the first element of list l or nil. +// Front returns the first element of list l or nil if the list is empty. func (l *PacketIntervalList) Front() *PacketIntervalElement { if l.len == 0 { return nil @@ -71,7 +67,7 @@ func (l *PacketIntervalList) Front() *PacketIntervalElement { return l.root.next } -// Back returns the last element of list l or nil. +// Back returns the last element of list l or nil if the list is empty. func (l *PacketIntervalList) Back() *PacketIntervalElement { if l.len == 0 { return nil @@ -79,7 +75,7 @@ func (l *PacketIntervalList) Back() *PacketIntervalElement { return l.root.prev } -// lazyInit lazily initializes a zero PacketIntervalList value. +// lazyInit lazily initializes a zero List value. func (l *PacketIntervalList) lazyInit() { if l.root.next == nil { l.Init() @@ -98,7 +94,7 @@ func (l *PacketIntervalList) insert(e, at *PacketIntervalElement) *PacketInterva return e } -// insertValue is a convenience wrapper for insert(&PacketIntervalElement{Value: v}, at). +// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). func (l *PacketIntervalList) insertValue(v PacketInterval, at *PacketIntervalElement) *PacketIntervalElement { return l.insert(&PacketIntervalElement{Value: v}, at) } @@ -116,10 +112,11 @@ func (l *PacketIntervalList) remove(e *PacketIntervalElement) *PacketIntervalEle // Remove removes e from l if e is an element of list l. // It returns the element value e.Value. +// The element must not be nil. func (l *PacketIntervalList) Remove(e *PacketIntervalElement) PacketInterval { if e.list == l { // if e.list == l, l must have been initialized when e was inserted - // in l or l == nil (e is a zero PacketIntervalElement) and l.remove will crash + // in l or l == nil (e is a zero Element) and l.remove will crash l.remove(e) } return e.Value @@ -139,46 +136,51 @@ func (l *PacketIntervalList) PushBack(v PacketInterval) *PacketIntervalElement { // InsertBefore inserts a new element e with value v immediately before mark and returns e. // If mark is not an element of l, the list is not modified. +// The mark must not be nil. func (l *PacketIntervalList) InsertBefore(v PacketInterval, mark *PacketIntervalElement) *PacketIntervalElement { if mark.list != l { return nil } - // see comment in PacketIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l return l.insertValue(v, mark.prev) } // InsertAfter inserts a new element e with value v immediately after mark and returns e. // If mark is not an element of l, the list is not modified. +// The mark must not be nil. func (l *PacketIntervalList) InsertAfter(v PacketInterval, mark *PacketIntervalElement) *PacketIntervalElement { if mark.list != l { return nil } - // see comment in PacketIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l return l.insertValue(v, mark) } // MoveToFront moves element e to the front of list l. // If e is not an element of l, the list is not modified. +// The element must not be nil. func (l *PacketIntervalList) MoveToFront(e *PacketIntervalElement) { if e.list != l || l.root.next == e { return } - // see comment in PacketIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l l.insert(l.remove(e), &l.root) } // MoveToBack moves element e to the back of list l. // If e is not an element of l, the list is not modified. +// The element must not be nil. func (l *PacketIntervalList) MoveToBack(e *PacketIntervalElement) { if e.list != l || l.root.prev == e { return } - // see comment in PacketIntervalList.Remove about initialization of l + // see comment in List.Remove about initialization of l l.insert(l.remove(e), l.root.prev) } // MoveBefore moves element e to its new position before mark. // If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. func (l *PacketIntervalList) MoveBefore(e, mark *PacketIntervalElement) { if e.list != l || e == mark || mark.list != l { return @@ -187,7 +189,8 @@ func (l *PacketIntervalList) MoveBefore(e, mark *PacketIntervalElement) { } // MoveAfter moves element e to its new position after mark. -// If e is not an element of l, or e == mark, the list is not modified. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. func (l *PacketIntervalList) MoveAfter(e, mark *PacketIntervalElement) { if e.list != l || e == mark || mark.list != l { return @@ -196,7 +199,7 @@ func (l *PacketIntervalList) MoveAfter(e, mark *PacketIntervalElement) { } // PushBackList inserts a copy of an other list at the back of list l. -// The lists l and other may be the same. +// The lists l and other may be the same. They must not be nil. func (l *PacketIntervalList) PushBackList(other *PacketIntervalList) { l.lazyInit() for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { @@ -205,7 +208,7 @@ func (l *PacketIntervalList) PushBackList(other *PacketIntervalList) { } // PushFrontList inserts a copy of an other list at the front of list l. -// The lists l and other may be the same. +// The lists l and other may be the same. They must not be nil. func (l *PacketIntervalList) PushFrontList(other *PacketIntervalList) { l.lazyInit() for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go index 3c8325b25..ec16d251b 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go @@ -3,7 +3,6 @@ package utils import "github.com/lucas-clemente/quic-go/internal/protocol" // ByteInterval is an interval from one ByteCount to the other -// +gen linkedlist type ByteInterval struct { Start protocol.ByteCount End protocol.ByteCount diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go index d85c33a0d..1a95bb9f3 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go @@ -24,8 +24,8 @@ type AckFrame struct { DelayTime time.Duration } -// ParseAckFrame reads an ACK frame -func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) { +// parseAckFrame reads an ACK frame +func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) { if !version.UsesIETFFrameFormat() { return parseAckFrameLegacy(r, version) } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go index e4cad2d6d..1d3e56e59 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go @@ -12,8 +12,8 @@ type BlockedFrame struct { Offset protocol.ByteCount } -// ParseBlockedFrame parses a BLOCKED frame -func ParseBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*BlockedFrame, error) { +// parseBlockedFrame parses a BLOCKED frame +func parseBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*BlockedFrame, error) { if _, err := r.ReadByte(); err != nil { return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go index 41cf0ee7e..9943e1668 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go @@ -11,11 +11,11 @@ type blockedFrameLegacy struct { StreamID protocol.StreamID } -// ParseBlockedFrameLegacy parses a BLOCKED frame (in gQUIC format) +// parseBlockedFrameLegacy parses a BLOCKED frame (in gQUIC format) // The frame returned is // * a STREAM_BLOCKED frame, if the BLOCKED applies to a stream // * a BLOCKED frame, if the BLOCKED applies to the connection -func ParseBlockedFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) { +func parseBlockedFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) { if _, err := r.ReadByte(); err != nil { // read the TypeByte return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go index e2f5b403c..667ded744 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go @@ -17,8 +17,8 @@ type ConnectionCloseFrame struct { ReasonPhrase string } -// ParseConnectionCloseFrame reads a CONNECTION_CLOSE frame -func ParseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) (*ConnectionCloseFrame, error) { +// parseConnectionCloseFrame reads a CONNECTION_CLOSE frame +func parseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) (*ConnectionCloseFrame, error) { if _, err := r.ReadByte(); err != nil { // read the TypeByte return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go new file mode 100644 index 000000000..6911446f9 --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go @@ -0,0 +1,152 @@ +package wire + +import ( + "bytes" + "fmt" + + "github.com/lucas-clemente/quic-go/internal/protocol" + "github.com/lucas-clemente/quic-go/qerr" +) + +// ParseNextFrame parses the next frame +// It skips PADDING frames. +func ParseNextFrame(r *bytes.Reader, hdr *Header, v protocol.VersionNumber) (Frame, error) { + if r.Len() == 0 { + return nil, nil + } + typeByte, _ := r.ReadByte() + if typeByte == 0x0 { // PADDING frame + return ParseNextFrame(r, hdr, v) + } + r.UnreadByte() + + if !v.UsesIETFFrameFormat() { + return parseGQUICFrame(r, typeByte, hdr, v) + } + return parseIETFFrame(r, typeByte, v) +} + +func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame, error) { + var frame Frame + var err error + if typeByte&0xf8 == 0x10 { + frame, err = parseStreamFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidStreamData, err.Error()) + } + return frame, err + } + // TODO: implement all IETF QUIC frame types + switch typeByte { + case 0x1: + frame, err = parseRstStreamFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidRstStreamData, err.Error()) + } + case 0x2: + frame, err = parseConnectionCloseFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error()) + } + case 0x4: + frame, err = parseMaxDataFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error()) + } + case 0x5: + frame, err = parseMaxStreamDataFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error()) + } + case 0x6: + frame, err = parseMaxStreamIDFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidFrameData, err.Error()) + } + case 0x7: + frame, err = parsePingFrame(r, v) + case 0x8: + frame, err = parseBlockedFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidBlockedData, err.Error()) + } + case 0x9: + frame, err = parseStreamBlockedFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidBlockedData, err.Error()) + } + case 0xa: + frame, err = parseStreamIDBlockedFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidFrameData, err.Error()) + } + case 0xc: + frame, err = parseStopSendingFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidFrameData, err.Error()) + } + case 0xe: + frame, err = parseAckFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidAckData, err.Error()) + } + default: + err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte)) + } + return frame, err +} + +func parseGQUICFrame(r *bytes.Reader, typeByte byte, hdr *Header, v protocol.VersionNumber) (Frame, error) { + var frame Frame + var err error + if typeByte&0x80 == 0x80 { + frame, err = parseStreamFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidStreamData, err.Error()) + } + return frame, err + } else if typeByte&0xc0 == 0x40 { + frame, err = parseAckFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidAckData, err.Error()) + } + return frame, err + } + switch typeByte { + case 0x1: + frame, err = parseRstStreamFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidRstStreamData, err.Error()) + } + case 0x2: + frame, err = parseConnectionCloseFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error()) + } + case 0x3: + frame, err = parseGoawayFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidGoawayData, err.Error()) + } + case 0x4: + frame, err = parseWindowUpdateFrame(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error()) + } + case 0x5: + frame, err = parseBlockedFrameLegacy(r, v) + if err != nil { + err = qerr.Error(qerr.InvalidBlockedData, err.Error()) + } + case 0x6: + frame, err = parseStopWaitingFrame(r, hdr.PacketNumber, hdr.PacketNumberLen, v) + if err != nil { + err = qerr.Error(qerr.InvalidStopWaitingData, err.Error()) + } + case 0x7: + frame, err = parsePingFrame(r, v) + default: + err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte)) + } + return frame, err +} diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go index 8a91e5023..86bf2b439 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go @@ -16,8 +16,8 @@ type GoawayFrame struct { ReasonPhrase string } -// ParseGoawayFrame parses a GOAWAY frame -func ParseGoawayFrame(r *bytes.Reader, _ protocol.VersionNumber) (*GoawayFrame, error) { +// parseGoawayFrame parses a GOAWAY frame +func parseGoawayFrame(r *bytes.Reader, _ protocol.VersionNumber) (*GoawayFrame, error) { frame := &GoawayFrame{} if _, err := r.ReadByte(); err != nil { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go index 207312fff..fc346f3f4 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go @@ -4,6 +4,7 @@ import ( "bytes" "github.com/lucas-clemente/quic-go/internal/protocol" + "github.com/lucas-clemente/quic-go/internal/utils" ) // Header is the header of a QUIC packet. @@ -103,10 +104,10 @@ func (h *Header) GetLength(pers protocol.Perspective, version protocol.VersionNu } // Log logs the Header -func (h *Header) Log() { +func (h *Header) Log(logger utils.Logger) { if h.isPublicHeader { - h.logPublicHeader() + h.logPublicHeader(logger) } else { - h.logHeader() + h.logHeader(logger) } } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go index 6d18ef394..01bf0a26b 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go @@ -174,14 +174,14 @@ func (h *Header) getHeaderLength() (protocol.ByteCount, error) { return length, nil } -func (h *Header) logHeader() { +func (h *Header) logHeader(logger utils.Logger) { if h.IsLongHeader { - utils.Debugf(" Long Header{Type: %s, ConnectionID: %#x, PacketNumber: %#x, Version: %s}", h.Type, h.ConnectionID, h.PacketNumber, h.Version) + logger.Debugf(" Long Header{Type: %s, ConnectionID: %#x, PacketNumber: %#x, Version: %s}", h.Type, h.ConnectionID, h.PacketNumber, h.Version) } else { connID := "(omitted)" if !h.OmitConnectionID { connID = fmt.Sprintf("%#x", h.ConnectionID) } - utils.Debugf(" Short Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", connID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase) + logger.Debugf(" Short Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", connID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase) } } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go index 0e72ea98a..eaf5b1ea9 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go @@ -3,8 +3,8 @@ package wire import "github.com/lucas-clemente/quic-go/internal/utils" // LogFrame logs a frame, either sent or received -func LogFrame(frame Frame, sent bool) { - if !utils.Debug() { +func LogFrame(logger utils.Logger, frame Frame, sent bool) { + if !logger.Debug() { return } dir := "<-" @@ -13,16 +13,16 @@ func LogFrame(frame Frame, sent bool) { } switch f := frame.(type) { case *StreamFrame: - utils.Debugf("\t%s &wire.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, f.StreamID, f.FinBit, f.Offset, f.DataLen(), f.Offset+f.DataLen()) + logger.Debugf("\t%s &wire.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, f.StreamID, f.FinBit, f.Offset, f.DataLen(), f.Offset+f.DataLen()) case *StopWaitingFrame: if sent { - utils.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x, PacketNumberLen: 0x%x}", dir, f.LeastUnacked, f.PacketNumberLen) + logger.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x, PacketNumberLen: 0x%x}", dir, f.LeastUnacked, f.PacketNumberLen) } else { - utils.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x}", dir, f.LeastUnacked) + logger.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x}", dir, f.LeastUnacked) } case *AckFrame: - utils.Debugf("\t%s &wire.AckFrame{LargestAcked: 0x%x, LowestAcked: 0x%x, AckRanges: %#v, DelayTime: %s}", dir, f.LargestAcked, f.LowestAcked, f.AckRanges, f.DelayTime.String()) + logger.Debugf("\t%s &wire.AckFrame{LargestAcked: 0x%x, LowestAcked: 0x%x, AckRanges: %#v, DelayTime: %s}", dir, f.LargestAcked, f.LowestAcked, f.AckRanges, f.DelayTime.String()) default: - utils.Debugf("\t%s %#v", dir, frame) + logger.Debugf("\t%s %#v", dir, frame) } } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go index 8ba4fc09a..0bca27da8 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go @@ -12,8 +12,8 @@ type MaxDataFrame struct { ByteOffset protocol.ByteCount } -// ParseMaxDataFrame parses a MAX_DATA frame -func ParseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDataFrame, error) { +// parseMaxDataFrame parses a MAX_DATA frame +func parseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDataFrame, error) { // read the TypeByte if _, err := r.ReadByte(); err != nil { return nil, err diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go index e88f245b5..6d8be236d 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go @@ -13,8 +13,8 @@ type MaxStreamDataFrame struct { ByteOffset protocol.ByteCount } -// ParseMaxStreamDataFrame parses a MAX_STREAM_DATA frame -func ParseMaxStreamDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxStreamDataFrame, error) { +// parseMaxStreamDataFrame parses a MAX_STREAM_DATA frame +func parseMaxStreamDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxStreamDataFrame, error) { frame := &MaxStreamDataFrame{} // read the TypeByte diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go index 31e51ae3d..9f5424daa 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go @@ -12,8 +12,8 @@ type MaxStreamIDFrame struct { StreamID protocol.StreamID } -// ParseMaxStreamIDFrame parses a MAX_STREAM_ID frame -func ParseMaxStreamIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamIDFrame, error) { +// parseMaxStreamIDFrame parses a MAX_STREAM_ID frame +func parseMaxStreamIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamIDFrame, error) { // read the Type byte if _, err := r.ReadByte(); err != nil { return nil, err diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go index ac4fd7d25..bc1dedac0 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go @@ -9,8 +9,8 @@ import ( // A PingFrame is a ping frame type PingFrame struct{} -// ParsePingFrame parses a Ping frame -func ParsePingFrame(r *bytes.Reader, version protocol.VersionNumber) (*PingFrame, error) { +// parsePingFrame parses a Ping frame +func parsePingFrame(r *bytes.Reader, version protocol.VersionNumber) (*PingFrame, error) { frame := &PingFrame{} _, err := r.ReadByte() diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go index 593ac7711..af996b292 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go @@ -20,6 +20,9 @@ var ( // writePublicHeader writes a Public Header. func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _ protocol.VersionNumber) error { + if h.VersionFlag && pers == protocol.PerspectiveServer { + return errors.New("PublicHeader: Writing of Version Negotiation Packets not supported") + } if h.VersionFlag && h.ResetFlag { return errResetAndVersionFlagSet } @@ -228,7 +231,7 @@ func (h *Header) hasPacketNumber(packetSentBy protocol.Perspective) bool { return true } -func (h *Header) logPublicHeader() { +func (h *Header) logPublicHeader(logger utils.Logger) { connID := "(omitted)" if !h.OmitConnectionID { connID = fmt.Sprintf("%#x", h.ConnectionID) @@ -237,5 +240,5 @@ func (h *Header) logPublicHeader() { if h.Version != 0 { ver = h.Version.String() } - utils.Debugf(" Public Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, Version: %s, DiversificationNonce: %#v}", connID, h.PacketNumber, h.PacketNumberLen, ver, h.DiversificationNonce) + logger.Debugf(" Public Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, Version: %s, DiversificationNonce: %#v}", connID, h.PacketNumber, h.PacketNumberLen, ver, h.DiversificationNonce) } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go index ea25f381d..209422c28 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go @@ -16,8 +16,8 @@ type RstStreamFrame struct { ByteOffset protocol.ByteCount } -// ParseRstStreamFrame parses a RST_STREAM frame -func ParseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstStreamFrame, error) { +// parseRstStreamFrame parses a RST_STREAM frame +func parseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstStreamFrame, error) { if _, err := r.ReadByte(); err != nil { // read the TypeByte return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go index 2a33756bd..b5e698047 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go @@ -13,8 +13,8 @@ type StopSendingFrame struct { ErrorCode protocol.ApplicationErrorCode } -// ParseStopSendingFrame parses a STOP_SENDING frame -func ParseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) { +// parseStopSendingFrame parses a STOP_SENDING frame +func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) { if _, err := r.ReadByte(); err != nil { // read the TypeByte return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go index 4ee9578e6..b87606ad3 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go @@ -56,8 +56,8 @@ func (f *StopWaitingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount { return 1 + protocol.ByteCount(f.PacketNumberLen) } -// ParseStopWaitingFrame parses a StopWaiting frame -func ParseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber, packetNumberLen protocol.PacketNumberLen, _ protocol.VersionNumber) (*StopWaitingFrame, error) { +// parseStopWaitingFrame parses a StopWaiting frame +func parseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber, packetNumberLen protocol.PacketNumberLen, _ protocol.VersionNumber) (*StopWaitingFrame, error) { frame := &StopWaitingFrame{} // read the TypeByte diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go index 625698cd1..a083a9f59 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go @@ -13,8 +13,8 @@ type StreamBlockedFrame struct { Offset protocol.ByteCount } -// ParseStreamBlockedFrame parses a STREAM_BLOCKED frame -func ParseStreamBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamBlockedFrame, error) { +// parseStreamBlockedFrame parses a STREAM_BLOCKED frame +func parseStreamBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamBlockedFrame, error) { if _, err := r.ReadByte(); err != nil { // read the TypeByte return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go index b87fce227..d848127ae 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go @@ -19,8 +19,8 @@ type StreamFrame struct { Data []byte } -// ParseStreamFrame reads a STREAM frame -func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamFrame, error) { +// parseStreamFrame reads a STREAM frame +func parseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamFrame, error) { if !version.UsesIETFFrameFormat() { return parseLegacyStreamFrame(r, version) } @@ -76,7 +76,8 @@ func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamF if frame.Offset+frame.DataLen() > protocol.MaxByteCount { return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset") } - if !frame.FinBit && frame.DataLen() == 0 { + // empty frames are only allowed if they have offset 0 or the FIN bit set + if frame.DataLen() == 0 && !frame.FinBit && frame.Offset != 0 { return nil, qerr.EmptyStreamFrameNoFin } return frame, nil diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go index 7b390a4d9..6476eb9de 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go @@ -12,8 +12,8 @@ type StreamIDBlockedFrame struct { StreamID protocol.StreamID } -// ParseStreamIDBlockedFrame parses a STREAM_ID_BLOCKED frame -func ParseStreamIDBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamIDBlockedFrame, error) { +// parseStreamIDBlockedFrame parses a STREAM_ID_BLOCKED frame +func parseStreamIDBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamIDBlockedFrame, error) { if _, err := r.ReadByte(); err != nil { return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go index dea90ee14..cf72fc2e6 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go @@ -10,17 +10,9 @@ import ( // ComposeGQUICVersionNegotiation composes a Version Negotiation Packet for gQUIC func ComposeGQUICVersionNegotiation(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte { - buf := &bytes.Buffer{} - ph := Header{ - ConnectionID: connID, - PacketNumber: 1, - VersionFlag: true, - IsVersionNegotiation: true, - } - if err := ph.writePublicHeader(buf, protocol.PerspectiveServer, protocol.VersionWhatever); err != nil { - utils.Errorf("error composing version negotiation packet: %s", err.Error()) - return nil - } + buf := bytes.NewBuffer(make([]byte, 0, 1+8+len(versions)*4)) + buf.Write([]byte{0x1 | 0x8}) // type byte + utils.BigEndian.WriteUint64(buf, uint64(connID)) for _, v := range versions { utils.BigEndian.WriteUint32(buf, uint32(v)) } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go index 8f7556e75..606e25cf2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go @@ -12,11 +12,11 @@ type windowUpdateFrame struct { ByteOffset protocol.ByteCount } -// ParseWindowUpdateFrame parses a WINDOW_UPDATE frame +// parseWindowUpdateFrame parses a WINDOW_UPDATE frame // The frame returned is // * a MAX_STREAM_DATA frame, if the WINDOW_UPDATE applies to a stream // * a MAX_DATA frame, if the WINDOW_UPDATE applies to the connection -func ParseWindowUpdateFrame(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) { +func parseWindowUpdateFrame(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) { if _, err := r.ReadByte(); err != nil { // read the TypeByte return nil, err } diff --git a/vendor/github.com/lucas-clemente/quic-go/mint_utils.go b/vendor/github.com/lucas-clemente/quic-go/mint_utils.go index 5156a6526..b32a09057 100644 --- a/vendor/github.com/lucas-clemente/quic-go/mint_utils.go +++ b/vendor/github.com/lucas-clemente/quic-go/mint_utils.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "crypto/x509" "errors" + "fmt" "io" "github.com/bifurcation/mint" @@ -76,6 +77,7 @@ func tlsToMintConfig(tlsConf *tls.Config, pers protocol.Perspective) (*mint.Conf mconf.ServerName = tlsConf.ServerName mconf.InsecureSkipVerify = tlsConf.InsecureSkipVerify mconf.Certificates = make([]*mint.Certificate, len(tlsConf.Certificates)) + mconf.RootCAs = tlsConf.RootCAs mconf.VerifyPeerCertificate = tlsConf.VerifyPeerCertificate for i, certChain := range tlsConf.Certificates { mconf.Certificates[i] = &mint.Certificate{ @@ -106,39 +108,45 @@ func tlsToMintConfig(tlsConf *tls.Config, pers protocol.Perspective) (*mint.Conf // unpackInitialOrRetryPacket unpacks packets Initial and Retry packets // These packets must contain a STREAM_FRAME for the crypto stream, starting at offset 0. -func unpackInitialPacket(aead crypto.AEAD, hdr *wire.Header, data []byte, version protocol.VersionNumber) (*wire.StreamFrame, error) { - unpacker := &packetUnpacker{aead: &nullAEAD{aead}, version: version} - packet, err := unpacker.Unpack(hdr.Raw, hdr, data) +func unpackInitialPacket(aead crypto.AEAD, hdr *wire.Header, data []byte, logger utils.Logger, version protocol.VersionNumber) (*wire.StreamFrame, error) { + decrypted, err := aead.Open(data[:0], data, hdr.PacketNumber, hdr.Raw) if err != nil { return nil, err } var frame *wire.StreamFrame - for _, f := range packet.frames { + r := bytes.NewReader(decrypted) + for { + f, err := wire.ParseNextFrame(r, hdr, version) + if err != nil { + return nil, err + } var ok bool - frame, ok = f.(*wire.StreamFrame) - if ok { + if frame, ok = f.(*wire.StreamFrame); ok || frame == nil { break } } if frame == nil { return nil, errors.New("Packet doesn't contain a STREAM_FRAME") } + if frame.StreamID != version.CryptoStreamID() { + return nil, fmt.Errorf("Received STREAM_FRAME for wrong stream (Stream ID %d)", frame.StreamID) + } // We don't need a check for the stream ID here. // The packetUnpacker checks that there's no unencrypted stream data except for the crypto stream. if frame.Offset != 0 { return nil, errors.New("received stream data with non-zero offset") } - if utils.Debug() { - utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID) - hdr.Log() - wire.LogFrame(frame, false) + if logger.Debug() { + logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID) + hdr.Log(logger) + wire.LogFrame(logger, frame, false) } return frame, nil } // packUnencryptedPacket provides a low-overhead way to pack a packet. // It is supposed to be used in the early stages of the handshake, before a session (which owns a packetPacker) is available. -func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, pers protocol.Perspective) ([]byte, error) { +func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, pers protocol.Perspective, logger utils.Logger) ([]byte, error) { raw := *getPacketBuffer() buffer := bytes.NewBuffer(raw[:0]) if err := hdr.Write(buffer, pers, hdr.Version); err != nil { @@ -151,10 +159,10 @@ func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, per raw = raw[0:buffer.Len()] _ = aead.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], hdr.PacketNumber, raw[:payloadStartIndex]) raw = raw[0 : buffer.Len()+aead.Overhead()] - if utils.Debug() { - utils.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(raw), hdr.ConnectionID, protocol.EncryptionUnencrypted) - hdr.Log() - wire.LogFrame(f, true) + if logger.Debug() { + logger.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(raw), hdr.ConnectionID, protocol.EncryptionUnencrypted) + hdr.Log(logger) + wire.LogFrame(logger, f, true) } return raw, nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/mockgen.go b/vendor/github.com/lucas-clemente/quic-go/mockgen.go index 3802a8633..65f385468 100644 --- a/vendor/github.com/lucas-clemente/quic-go/mockgen.go +++ b/vendor/github.com/lucas-clemente/quic-go/mockgen.go @@ -9,4 +9,8 @@ package quic //go:generate sh -c "./mockgen_private.sh quic mock_crypto_stream_test.go github.com/lucas-clemente/quic-go cryptoStreamI CryptoStream" //go:generate sh -c "./mockgen_private.sh quic mock_stream_manager_test.go github.com/lucas-clemente/quic-go streamManager StreamManager" //go:generate sh -c "sed -i '' 's/quic_go.//g' mock_stream_getter_test.go mock_stream_manager_test.go" +//go:generate sh -c "./mockgen_private.sh quic mock_unpacker_test.go github.com/lucas-clemente/quic-go unpacker Unpacker" +//go:generate sh -c "sed -i '' 's/quic_go.//g' mock_unpacker_test.go mock_unpacker_test.go" +//go:generate sh -c "./mockgen_private.sh quic mock_quic_aead_test.go github.com/lucas-clemente/quic-go quicAEAD QuicAEAD" +//go:generate sh -c "./mockgen_private.sh quic mock_gquic_aead_test.go github.com/lucas-clemente/quic-go gQUICAEAD GQUICAEAD" //go:generate sh -c "goimports -w mock*_test.go" diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_packer.go b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go index b9b71edfe..e4fa653a5 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_packer.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "sync" + "time" "github.com/lucas-clemente/quic-go/internal/ackhandler" "github.com/lucas-clemente/quic-go/internal/handshake" @@ -28,9 +29,16 @@ func (p *packedPacket) ToAckHandlerPacket() *ackhandler.Packet { Frames: p.frames, Length: protocol.ByteCount(len(p.raw)), EncryptionLevel: p.encryptionLevel, + SendTime: time.Now(), } } +type sealingManager interface { + GetSealer() (protocol.EncryptionLevel, handshake.Sealer) + GetSealerForCryptoStream() (protocol.EncryptionLevel, handshake.Sealer) + GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (handshake.Sealer, error) +} + type streamFrameSource interface { HasCryptoStreamData() bool PopCryptoStreamFrame(protocol.ByteCount) *wire.StreamFrame @@ -41,7 +49,8 @@ type packetPacker struct { connectionID protocol.ConnectionID perspective protocol.Perspective version protocol.VersionNumber - cryptoSetup handshake.CryptoSetup + divNonce []byte + cryptoSetup sealingManager packetNumberGenerator *packetNumberGenerator getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen @@ -62,7 +71,8 @@ func newPacketPacker(connectionID protocol.ConnectionID, initialPacketNumber protocol.PacketNumber, getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen, remoteAddr net.Addr, // only used for determining the max packet size - cryptoSetup handshake.CryptoSetup, + divNonce []byte, + cryptoSetup sealingManager, streamFramer streamFrameSource, perspective protocol.Perspective, version protocol.VersionNumber, @@ -82,6 +92,7 @@ func newPacketPacker(connectionID protocol.ConnectionID, } return &packetPacker{ cryptoSetup: cryptoSetup, + divNonce: divNonce, connectionID: connectionID, perspective: perspective, version: version, @@ -455,7 +466,7 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header } if !p.version.UsesTLS() { if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure { - header.DiversificationNonce = p.cryptoSetup.DiversificationNonce() + header.DiversificationNonce = p.divNonce } if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure { header.VersionFlag = true diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go index a978675d8..994979072 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go @@ -2,7 +2,6 @@ package quic import ( "bytes" - "fmt" "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/wire" @@ -14,52 +13,65 @@ type unpackedPacket struct { frames []wire.Frame } -type quicAEAD interface { +type gQUICAEAD interface { Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) } -type packetUnpacker struct { - version protocol.VersionNumber - aead quicAEAD +type quicAEAD interface { + OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) + Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) } -func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) { - buf := *getPacketBuffer() - buf = buf[:0] - defer putPacketBuffer(&buf) - decrypted, encryptionLevel, err := u.aead.Open(buf, data, hdr.PacketNumber, headerBinary) - if err != nil { - // Wrap err in quicError so that public reset is sent by session - return nil, qerr.Error(qerr.DecryptionFailure, err.Error()) - } - r := bytes.NewReader(decrypted) +type packetUnpackerBase struct { + version protocol.VersionNumber +} +func (u *packetUnpackerBase) parseFrames(decrypted []byte, hdr *wire.Header) ([]wire.Frame, error) { + r := bytes.NewReader(decrypted) if r.Len() == 0 { return nil, qerr.MissingPayload } fs := make([]wire.Frame, 0, 2) - // Read all frames in the packet - for r.Len() > 0 { - typeByte, _ := r.ReadByte() - if typeByte == 0x0 { // PADDING frame - continue - } - r.UnreadByte() - - frame, err := u.parseFrame(r, typeByte, hdr) + for { + frame, err := wire.ParseNextFrame(r, hdr, u.version) if err != nil { return nil, err } - if sf, ok := frame.(*wire.StreamFrame); ok { - if sf.StreamID != u.version.CryptoStreamID() && encryptionLevel <= protocol.EncryptionUnencrypted { - return nil, qerr.Error(qerr.UnencryptedStreamData, fmt.Sprintf("received unencrypted stream data on stream %d", sf.StreamID)) - } - } - if frame != nil { - fs = append(fs, frame) + if frame == nil { + break } + fs = append(fs, frame) + } + return fs, nil +} + +// The packetUnpackerGQUIC unpacks gQUIC packets. +type packetUnpackerGQUIC struct { + packetUnpackerBase + aead gQUICAEAD +} + +var _ unpacker = &packetUnpackerGQUIC{} + +func newPacketUnpackerGQUIC(aead gQUICAEAD, version protocol.VersionNumber) unpacker { + return &packetUnpackerGQUIC{ + packetUnpackerBase: packetUnpackerBase{version: version}, + aead: aead, + } +} + +func (u *packetUnpackerGQUIC) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) { + decrypted, encryptionLevel, err := u.aead.Open(data[:0], data, hdr.PacketNumber, headerBinary) + if err != nil { + // Wrap err in quicError so that public reset is sent by session + return nil, qerr.Error(qerr.DecryptionFailure, err.Error()) + } + + fs, err := u.parseFrames(decrypted, hdr) + if err != nil { + return nil, err } return &unpackedPacket{ @@ -68,134 +80,48 @@ func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []by }, nil } -func (u *packetUnpacker) parseFrame(r *bytes.Reader, typeByte byte, hdr *wire.Header) (wire.Frame, error) { - if u.version.UsesIETFFrameFormat() { - return u.parseIETFFrame(r, typeByte, hdr) - } - return u.parseGQUICFrame(r, typeByte, hdr) +// The packetUnpacker unpacks IETF QUIC packets. +type packetUnpacker struct { + packetUnpackerBase + aead quicAEAD } -func (u *packetUnpacker) parseIETFFrame(r *bytes.Reader, typeByte byte, hdr *wire.Header) (wire.Frame, error) { - var frame wire.Frame - var err error - if typeByte&0xf8 == 0x10 { - frame, err = wire.ParseStreamFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidStreamData, err.Error()) - } - return frame, err +var _ unpacker = &packetUnpacker{} + +func newPacketUnpacker(aead quicAEAD, version protocol.VersionNumber) unpacker { + return &packetUnpacker{ + packetUnpackerBase: packetUnpackerBase{version: version}, + aead: aead, } - // TODO: implement all IETF QUIC frame types - switch typeByte { - case 0x1: - frame, err = wire.ParseRstStreamFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidRstStreamData, err.Error()) - } - case 0x2: - frame, err = wire.ParseConnectionCloseFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error()) - } - case 0x4: - frame, err = wire.ParseMaxDataFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error()) - } - case 0x5: - frame, err = wire.ParseMaxStreamDataFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error()) - } - case 0x6: - frame, err = wire.ParseMaxStreamIDFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidFrameData, err.Error()) - } - case 0x7: - frame, err = wire.ParsePingFrame(r, u.version) - case 0x8: - frame, err = wire.ParseBlockedFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidBlockedData, err.Error()) - } - case 0x9: - frame, err = wire.ParseStreamBlockedFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidBlockedData, err.Error()) - } - case 0xa: - frame, err = wire.ParseStreamIDBlockedFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidFrameData, err.Error()) - } - case 0xc: - frame, err = wire.ParseStopSendingFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidFrameData, err.Error()) - } - case 0xe: - frame, err = wire.ParseAckFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidAckData, err.Error()) - } - default: - err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte)) - } - return frame, err } -func (u *packetUnpacker) parseGQUICFrame(r *bytes.Reader, typeByte byte, hdr *wire.Header) (wire.Frame, error) { - var frame wire.Frame +func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) { + buf := *getPacketBuffer() + buf = buf[:0] + defer putPacketBuffer(&buf) + + var decrypted []byte + var encryptionLevel protocol.EncryptionLevel var err error - if typeByte&0x80 == 0x80 { - frame, err = wire.ParseStreamFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidStreamData, err.Error()) - } - return frame, err - } else if typeByte&0xc0 == 0x40 { - frame, err = wire.ParseAckFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidAckData, err.Error()) - } - return frame, err + if hdr.IsLongHeader { + decrypted, err = u.aead.OpenHandshake(buf, data, hdr.PacketNumber, headerBinary) + encryptionLevel = protocol.EncryptionUnencrypted + } else { + decrypted, err = u.aead.Open1RTT(buf, data, hdr.PacketNumber, headerBinary) + encryptionLevel = protocol.EncryptionForwardSecure } - switch typeByte { - case 0x1: - frame, err = wire.ParseRstStreamFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidRstStreamData, err.Error()) - } - case 0x2: - frame, err = wire.ParseConnectionCloseFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error()) - } - case 0x3: - frame, err = wire.ParseGoawayFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidGoawayData, err.Error()) - } - case 0x4: - frame, err = wire.ParseWindowUpdateFrame(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error()) - } - case 0x5: - frame, err = wire.ParseBlockedFrameLegacy(r, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidBlockedData, err.Error()) - } - case 0x6: - frame, err = wire.ParseStopWaitingFrame(r, hdr.PacketNumber, hdr.PacketNumberLen, u.version) - if err != nil { - err = qerr.Error(qerr.InvalidStopWaitingData, err.Error()) - } - case 0x7: - frame, err = wire.ParsePingFrame(r, u.version) - default: - err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte)) + if err != nil { + // Wrap err in quicError so that public reset is sent by session + return nil, qerr.Error(qerr.DecryptionFailure, err.Error()) } - return frame, err + + fs, err := u.parseFrames(decrypted, hdr) + if err != nil { + return nil, err + } + + return &unpackedPacket{ + encryptionLevel: encryptionLevel, + frames: fs, + }, nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go b/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go index a620bd192..42d08c4c5 100644 --- a/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go +++ b/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go @@ -2,8 +2,6 @@ package qerr import ( "fmt" - - "github.com/lucas-clemente/quic-go/internal/utils" ) // ErrorCode can be used as a normal error without reason. @@ -51,6 +49,5 @@ func ToQuicError(err error) *QuicError { case ErrorCode: return Error(e, "") } - utils.Errorf("Internal error: %v", err) return Error(InternalError, err.Error()) } diff --git a/vendor/github.com/lucas-clemente/quic-go/server.go b/vendor/github.com/lucas-clemente/quic-go/server.go index 7a19afcb5..1e56f0b91 100644 --- a/vendor/github.com/lucas-clemente/quic-go/server.go +++ b/vendor/github.com/lucas-clemente/quic-go/server.go @@ -50,8 +50,10 @@ type server struct { errorChan chan struct{} // set as members, so they can be set in the tests - newSession func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config) (packetHandler, error) + newSession func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config, logger utils.Logger) (packetHandler, error) deleteClosedSessionsAfter time.Duration + + logger utils.Logger } var _ Listener = &server{} @@ -110,6 +112,7 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, sessionQueue: make(chan Session, 5), errorChan: make(chan struct{}), supportsTLS: supportsTLS, + logger: utils.DefaultLogger, } if supportsTLS { if err := s.setupTLS(); err != nil { @@ -117,16 +120,16 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, } } go s.serve() - utils.Debugf("Listening for %s connections on %s", conn.LocalAddr().Network(), conn.LocalAddr().String()) + s.logger.Debugf("Listening for %s connections on %s", conn.LocalAddr().Network(), conn.LocalAddr().String()) return s, nil } func (s *server) setupTLS() error { - cookieHandler, err := handshake.NewCookieHandler(s.config.AcceptCookie) + cookieHandler, err := handshake.NewCookieHandler(s.config.AcceptCookie, s.logger) if err != nil { return err } - serverTLS, sessionChan, err := newServerTLS(s.conn, s.config, cookieHandler, s.tlsConf) + serverTLS, sessionChan, err := newServerTLS(s.conn, s.config, cookieHandler, s.tlsConf, s.logger) if err != nil { return err } @@ -245,7 +248,7 @@ func (s *server) serve() { } data = data[:n] if err := s.handlePacket(s.conn, remoteAddr, data); err != nil { - utils.Errorf("error handling packet: %s", err.Error()) + s.logger.Errorf("error handling packet: %s", err.Error()) } } } @@ -328,12 +331,12 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet var pr *wire.PublicReset pr, err = wire.ParsePublicReset(r) if err != nil { - utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.", hdr.ConnectionID) + s.logger.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.", hdr.ConnectionID) } else { - utils.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.ConnectionID, pr.RejectedPacketNumber) + s.logger.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.ConnectionID, pr.RejectedPacketNumber) } } else { - utils.Infof("Received Public Reset for unknown connection %x.", hdr.ConnectionID) + s.logger.Infof("Received Public Reset for unknown connection %x.", hdr.ConnectionID) } return nil } @@ -360,7 +363,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet if len(packet) < protocol.MinClientHelloSize+len(hdr.Raw) { return errors.New("dropping small packet with unknown version") } - utils.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version) + s.logger.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version) _, err := pconn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.ConnectionID, s.config.Versions), remoteAddr) return err } @@ -377,7 +380,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet return errors.New("Server BUG: negotiated version not supported") } - utils.Infof("Serving new connection: %x, version %s from %v", hdr.ConnectionID, version, remoteAddr) + s.logger.Infof("Serving new connection: %x, version %s from %v", hdr.ConnectionID, version, remoteAddr) session, err = s.newSession( &conn{pconn: pconn, currentAddr: remoteAddr}, version, @@ -385,6 +388,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet s.scfg, s.tlsConf, s.config, + s.logger, ) if err != nil { return err diff --git a/vendor/github.com/lucas-clemente/quic-go/server_tls.go b/vendor/github.com/lucas-clemente/quic-go/server_tls.go index 38d7abb15..9f3874090 100644 --- a/vendor/github.com/lucas-clemente/quic-go/server_tls.go +++ b/vendor/github.com/lucas-clemente/quic-go/server_tls.go @@ -21,9 +21,12 @@ type nullAEAD struct { var _ quicAEAD = &nullAEAD{} -func (n *nullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) { - data, err := n.aead.Open(dst, src, packetNumber, associatedData) - return data, protocol.EncryptionUnencrypted, err +func (n *nullAEAD) OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + return n.aead.Open(dst, src, packetNumber, associatedData) +} + +func (n *nullAEAD) Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) { + return nil, errors.New("no 1-RTT keys") } type tlsSession struct { @@ -40,6 +43,8 @@ type serverTLS struct { newMintConn func(*handshake.CryptoStreamConn, protocol.VersionNumber) (handshake.MintTLS, <-chan handshake.TransportParameters, error) sessionChan chan<- tlsSession + + logger utils.Logger } func newServerTLS( @@ -47,6 +52,7 @@ func newServerTLS( config *Config, cookieHandler *handshake.CookieHandler, tlsConf *tls.Config, + logger utils.Logger, ) (*serverTLS, <-chan tlsSession, error) { mconf, err := tlsToMintConfig(tlsConf, protocol.PerspectiveServer) if err != nil { @@ -74,16 +80,17 @@ func newServerTLS( MaxBidiStreams: uint16(config.MaxIncomingStreams), MaxUniStreams: uint16(config.MaxIncomingUniStreams), }, + logger: logger, } s.newMintConn = s.newMintConnImpl return s, sessionChan, nil } func (s *serverTLS) HandleInitial(remoteAddr net.Addr, hdr *wire.Header, data []byte) { - utils.Debugf("Received a Packet. Handling it statelessly.") + s.logger.Debugf("Received a Packet. Handling it statelessly.") sess, err := s.handleInitialImpl(remoteAddr, hdr, data) if err != nil { - utils.Errorf("Error occurred handling initial packet: %s", err) + s.logger.Errorf("Error occurred handling initial packet: %s", err) return } if sess == nil { // a stateless reset was done @@ -97,7 +104,7 @@ func (s *serverTLS) HandleInitial(remoteAddr net.Addr, hdr *wire.Header, data [] // will be set to s.newMintConn by the constructor func (s *serverTLS) newMintConnImpl(bc *handshake.CryptoStreamConn, v protocol.VersionNumber) (handshake.MintTLS, <-chan handshake.TransportParameters, error) { - extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, v) + extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, v, s.logger) conf := s.mintConf.Clone() conf.ExtensionHandler = extHandler return newMintController(bc, conf, protocol.PerspectiveServer), extHandler.GetPeerParams(), nil @@ -115,7 +122,7 @@ func (s *serverTLS) sendConnectionClose(remoteAddr net.Addr, clientHdr *wire.Hea PacketNumber: 1, // random packet number Version: clientHdr.Version, } - data, err := packUnencryptedPacket(aead, replyHdr, ccf, protocol.PerspectiveServer) + data, err := packUnencryptedPacket(aead, replyHdr, ccf, protocol.PerspectiveServer, s.logger) if err != nil { return err } @@ -129,7 +136,7 @@ func (s *serverTLS) handleInitialImpl(remoteAddr net.Addr, hdr *wire.Header, dat } // check version, if not matching send VNP if !protocol.IsSupportedVersion(s.supportedVersions, hdr.Version) { - utils.Debugf("Client offered version %s, sending VersionNegotiationPacket", hdr.Version) + s.logger.Debugf("Client offered version %s, sending VersionNegotiationPacket", hdr.Version) _, err := s.conn.WriteTo(wire.ComposeVersionNegotiation(hdr.ConnectionID, s.supportedVersions), remoteAddr) return nil, err } @@ -139,15 +146,15 @@ func (s *serverTLS) handleInitialImpl(remoteAddr net.Addr, hdr *wire.Header, dat if err != nil { return nil, err } - frame, err := unpackInitialPacket(aead, hdr, data, hdr.Version) + frame, err := unpackInitialPacket(aead, hdr, data, s.logger, hdr.Version) if err != nil { - utils.Debugf("Error unpacking initial packet: %s", err) + s.logger.Debugf("Error unpacking initial packet: %s", err) return nil, nil } sess, err := s.handleUnpackedInitial(remoteAddr, hdr, frame, aead) if err != nil { if ccerr := s.sendConnectionClose(remoteAddr, hdr, aead, err); ccerr != nil { - utils.Debugf("Error sending CONNECTION_CLOSE: %s", ccerr) + s.logger.Debugf("Error sending CONNECTION_CLOSE: %s", ccerr) } return nil, err } @@ -177,7 +184,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header, StreamID: version.CryptoStreamID(), Data: bc.GetDataForWriting(), } - data, err := packUnencryptedPacket(aead, replyHdr, f, protocol.PerspectiveServer) + data, err := packUnencryptedPacket(aead, replyHdr, f, protocol.PerspectiveServer, s.logger) if err != nil { return nil, err } @@ -207,6 +214,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header, aead, ¶ms, version, + s.logger, ) if err != nil { return nil, err diff --git a/vendor/github.com/lucas-clemente/quic-go/session.go b/vendor/github.com/lucas-clemente/quic-go/session.go index 622b668e1..ed73637ce 100644 --- a/vendor/github.com/lucas-clemente/quic-go/session.go +++ b/vendor/github.com/lucas-clemente/quic-go/session.go @@ -2,6 +2,7 @@ package quic import ( "context" + "crypto/rand" "crypto/tls" "errors" "fmt" @@ -44,6 +45,11 @@ type streamManager interface { CloseWithError(error) } +type cryptoStreamHandler interface { + HandleCryptoStream() error + ConnectionState() handshake.ConnectionState +} + type receivedPacket struct { remoteAddr net.Addr header *wire.Header @@ -84,7 +90,8 @@ type session struct { unpacker unpacker packer *packetPacker - cryptoSetup handshake.CryptoSetup + cryptoStreamHandler cryptoStreamHandler + divNonceChan chan<- []byte // only set for the client receivedPackets chan *receivedPacket sendingScheduled chan struct{} @@ -129,6 +136,8 @@ type session struct { // keepAlivePingSent stores whether a Ping frame was sent to the peer or not // it is reset as soon as we receive a packet from the peer keepAlivePingSent bool + + logger utils.Logger } var _ Session = &session{} @@ -142,6 +151,7 @@ func newSession( scfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config, + logger utils.Logger, ) (packetHandler, error) { paramsChan := make(chan handshake.TransportParameters) handshakeEvent := make(chan struct{}, 1) @@ -153,6 +163,7 @@ func newSession( config: config, handshakeEvent: handshakeEvent, paramsChan: paramsChan, + logger: logger, } s.preSetup() transportParams := &handshake.TransportParameters{ @@ -161,23 +172,42 @@ func newSession( MaxStreams: uint32(s.config.MaxIncomingStreams), IdleTimeout: s.config.IdleTimeout, } + divNonce := make([]byte, 32) + if _, err := rand.Read(divNonce); err != nil { + return nil, err + } cs, err := newCryptoSetup( s.cryptoStream, s.connectionID, s.conn.RemoteAddr(), s.version, + divNonce, scfg, transportParams, s.config.Versions, s.config.AcceptCookie, paramsChan, handshakeEvent, + s.logger, ) if err != nil { return nil, err } - s.cryptoSetup = cs - return s, s.postSetup(1) + s.cryptoStreamHandler = cs + s.unpacker = newPacketUnpackerGQUIC(cs, s.version) + s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective) + s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version) + s.packer = newPacketPacker(s.connectionID, + 1, + s.sentPacketHandler.GetPacketNumberLen, + s.RemoteAddr(), + divNonce, + cs, + s.streamFramer, + s.perspective, + s.version, + ) + return s, s.postSetup() } // declare this as a variable, so that we can it mock it in the tests @@ -190,6 +220,7 @@ var newClientSession = func( config *Config, initialVersion protocol.VersionNumber, negotiatedVersions []protocol.VersionNumber, // needed for validation of the GQUIC version negotiation + logger utils.Logger, ) (packetHandler, error) { paramsChan := make(chan handshake.TransportParameters) handshakeEvent := make(chan struct{}, 1) @@ -201,6 +232,7 @@ var newClientSession = func( config: config, handshakeEvent: handshakeEvent, paramsChan: paramsChan, + logger: logger, } s.preSetup() transportParams := &handshake.TransportParameters{ @@ -210,7 +242,7 @@ var newClientSession = func( IdleTimeout: s.config.IdleTimeout, OmitConnectionID: s.config.RequestConnectionIDOmission, } - cs, err := newCryptoSetupClient( + cs, divNonceChan, err := newCryptoSetupClient( s.cryptoStream, hostname, s.connectionID, @@ -221,12 +253,27 @@ var newClientSession = func( handshakeEvent, initialVersion, negotiatedVersions, + s.logger, ) if err != nil { return nil, err } - s.cryptoSetup = cs - return s, s.postSetup(1) + s.cryptoStreamHandler = cs + s.divNonceChan = divNonceChan + s.unpacker = newPacketUnpackerGQUIC(cs, s.version) + s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective) + s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version) + s.packer = newPacketPacker(s.connectionID, + 1, + s.sentPacketHandler.GetPacketNumberLen, + s.RemoteAddr(), + nil, // no diversification nonce + cs, + s.streamFramer, + s.perspective, + s.version, + ) + return s, s.postSetup() } func newTLSServerSession( @@ -239,6 +286,7 @@ func newTLSServerSession( nullAEAD crypto.AEAD, peerParams *handshake.TransportParameters, v protocol.VersionNumber, + logger utils.Logger, ) (packetHandler, error) { handshakeEvent := make(chan struct{}, 1) s := &session{ @@ -248,21 +296,35 @@ func newTLSServerSession( perspective: protocol.PerspectiveServer, version: v, handshakeEvent: handshakeEvent, + logger: logger, } s.preSetup() - s.cryptoSetup = handshake.NewCryptoSetupTLSServer( + cs := handshake.NewCryptoSetupTLSServer( tls, cryptoStreamConn, nullAEAD, handshakeEvent, v, ) - if err := s.postSetup(initialPacketNumber); err != nil { + s.cryptoStreamHandler = cs + s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version) + s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version) + s.packer = newPacketPacker(s.connectionID, + initialPacketNumber, + s.sentPacketHandler.GetPacketNumberLen, + s.RemoteAddr(), + nil, // no diversification nonce + cs, + s.streamFramer, + s.perspective, + s.version, + ) + if err := s.postSetup(); err != nil { return nil, err } s.peerParams = peerParams s.processTransportParameters(peerParams) - s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version} + s.unpacker = newPacketUnpacker(cs, s.version) return s, nil } @@ -276,6 +338,7 @@ var newTLSClientSession = func( tls handshake.MintTLS, paramsChan <-chan handshake.TransportParameters, initialPacketNumber protocol.PacketNumber, + logger utils.Logger, ) (packetHandler, error) { handshakeEvent := make(chan struct{}, 1) s := &session{ @@ -286,6 +349,7 @@ var newTLSClientSession = func( version: v, handshakeEvent: handshakeEvent, paramsChan: paramsChan, + logger: logger, } s.preSetup() tls.SetCryptoStream(s.cryptoStream) @@ -300,21 +364,36 @@ var newTLSClientSession = func( if err != nil { return nil, err } - s.cryptoSetup = cs - return s, s.postSetup(initialPacketNumber) + s.cryptoStreamHandler = cs + s.unpacker = newPacketUnpacker(cs, s.version) + s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version) + s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version) + s.packer = newPacketPacker(s.connectionID, + initialPacketNumber, + s.sentPacketHandler.GetPacketNumberLen, + s.RemoteAddr(), + nil, // no diversification nonce + cs, + s.streamFramer, + s.perspective, + s.version, + ) + return s, s.postSetup() } func (s *session) preSetup() { s.rttStats = &congestion.RTTStats{} + s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats, s.logger) s.connFlowController = flowcontrol.NewConnectionFlowController( protocol.ReceiveConnectionFlowControlWindow, protocol.ByteCount(s.config.MaxReceiveConnectionFlowControlWindow), s.rttStats, + s.logger, ) s.cryptoStream = s.newCryptoStream() } -func (s *session) postSetup(initialPacketNumber protocol.PacketNumber) error { +func (s *session) postSetup() error { s.handshakeChan = make(chan error, 1) s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets) s.closeChan = make(chan closeError, 1) @@ -327,26 +406,8 @@ func (s *session) postSetup(initialPacketNumber protocol.PacketNumber) error { s.lastNetworkActivityTime = now s.sessionCreationTime = now - s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats) s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.version) - - if s.version.UsesTLS() { - s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version) - } else { - s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective) - } - s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version) - s.packer = newPacketPacker(s.connectionID, - initialPacketNumber, - s.sentPacketHandler.GetPacketNumberLen, - s.RemoteAddr(), - s.cryptoSetup, - s.streamFramer, - s.perspective, - s.version, - ) s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.cryptoStream, s.packer.QueueControlFrame) - s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version} return nil } @@ -355,13 +416,12 @@ func (s *session) run() error { defer s.ctxCancel() go func() { - if err := s.cryptoSetup.HandleCryptoStream(); err != nil { + if err := s.cryptoStreamHandler.HandleCryptoStream(); err != nil { s.Close(err) } }() var closeErr closeError - handshakeEvent := s.handshakeEvent runLoop: for { @@ -370,6 +430,9 @@ runLoop: select { case closeErr = <-s.closeChan: break runLoop + case _, ok := <-s.handshakeEvent: + // when the handshake is completed, the channel will be closed + s.handleHandshakeEvent(!ok) default: } @@ -400,20 +463,9 @@ runLoop: putPacketBuffer(&p.header.Raw) case p := <-s.paramsChan: s.processTransportParameters(&p) - case _, ok := <-handshakeEvent: - if !ok { // the aeadChanged chan was closed. This means that the handshake is completed. - s.handshakeComplete = true - handshakeEvent = nil // prevent this case from ever being selected again - if !s.version.UsesTLS() && s.perspective == protocol.PerspectiveClient { - // In gQUIC, there's no equivalent to the Finished message in TLS - // The server knows that the handshake is complete when it receives the first forward-secure packet sent by the client. - // We need to make sure that the client actually sends such a packet. - s.packer.QueueControlFrame(&wire.PingFrame{}) - } - close(s.handshakeChan) - } else { - s.tryDecryptingQueuedPackets() - } + case _, ok := <-s.handshakeEvent: + // when the handshake is completed, the channel will be closed + s.handleHandshakeEvent(!ok) } now := time.Now() @@ -470,7 +522,7 @@ func (s *session) Context() context.Context { } func (s *session) ConnectionState() ConnectionState { - return s.cryptoSetup.ConnectionState() + return s.cryptoStreamHandler.ConnectionState() } func (s *session) maybeResetTimer() { @@ -501,11 +553,27 @@ func (s *session) maybeResetTimer() { s.timer.Reset(deadline) } +func (s *session) handleHandshakeEvent(completed bool) { + if !completed { + s.tryDecryptingQueuedPackets() + return + } + s.handshakeComplete = true + s.handshakeEvent = nil // prevent this case from ever being selected again + if !s.version.UsesTLS() && s.perspective == protocol.PerspectiveClient { + // In gQUIC, there's no equivalent to the Finished message in TLS + // The server knows that the handshake is complete when it receives the first forward-secure packet sent by the client. + // We need to make sure that the client actually sends such a packet. + s.packer.QueueControlFrame(&wire.PingFrame{}) + s.scheduleSending() + } + close(s.handshakeChan) +} + func (s *session) handlePacketImpl(p *receivedPacket) error { if s.perspective == protocol.PerspectiveClient { - diversificationNonce := p.header.DiversificationNonce - if len(diversificationNonce) > 0 { - s.cryptoSetup.SetDiversificationNonce(diversificationNonce) + if divNonce := p.header.DiversificationNonce; len(divNonce) > 0 { + s.divNonceChan <- divNonce } } @@ -528,13 +596,13 @@ func (s *session) handlePacketImpl(p *receivedPacket) error { ) packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data) - if utils.Debug() { + if s.logger.Debug() { if err != nil { - utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID) + s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID) } else { - utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID, packet.encryptionLevel) + s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID, packet.encryptionLevel) } - hdr.Log() + hdr.Log(s.logger) } // if the decryption failed, this might be a packet sent by an attacker if err != nil { @@ -569,10 +637,10 @@ func (s *session) handlePacketImpl(p *receivedPacket) error { func (s *session) handleFrames(fs []wire.Frame, encLevel protocol.EncryptionLevel) error { for _, ff := range fs { var err error - wire.LogFrame(ff, false) + wire.LogFrame(s.logger, ff, false) switch frame := ff.(type) { case *wire.StreamFrame: - err = s.handleStreamFrame(frame) + err = s.handleStreamFrame(frame, encLevel) case *wire.AckFrame: err = s.handleAckFrame(frame, encLevel) case *wire.ConnectionCloseFrame: @@ -615,12 +683,14 @@ func (s *session) handlePacket(p *receivedPacket) { } } -func (s *session) handleStreamFrame(frame *wire.StreamFrame) error { +func (s *session) handleStreamFrame(frame *wire.StreamFrame, encLevel protocol.EncryptionLevel) error { if frame.StreamID == s.version.CryptoStreamID() { if frame.FinBit { return errors.New("Received STREAM frame with FIN bit for the crypto stream") } return s.cryptoStream.handleStreamFrame(frame) + } else if encLevel <= protocol.EncryptionUnencrypted { + return qerr.Error(qerr.UnencryptedStreamData, fmt.Sprintf("received unencrypted stream data on stream %d", frame.StreamID)) } str, err := s.streamsMap.GetOrOpenReceiveStream(frame.StreamID) if err != nil { @@ -730,9 +800,9 @@ func (s *session) handleCloseError(closeErr closeError) error { } // Don't log 'normal' reasons if quicErr.ErrorCode == qerr.PeerGoingAway || quicErr.ErrorCode == qerr.NetworkIdleTimeout { - utils.Infof("Closing connection %x", s.connectionID) + s.logger.Infof("Closing connection %x", s.connectionID) } else { - utils.Errorf("Closing session with error: %s", closeErr.err.Error()) + s.logger.Errorf("Closing session with error: %s", closeErr.err.Error()) } s.cryptoStream.closeForShutdown(quicErr) @@ -789,6 +859,25 @@ sendLoop: // There will only be a new ACK after receiving new packets. // SendAck is only returned when we're congestion limited, so we don't need to set the pacingt timer. return s.maybeSendAckOnlyPacket() + case ackhandler.SendRTO: + // try to send a retransmission first + sentPacket, err := s.maybeSendRetransmission() + if err != nil { + return err + } + if !sentPacket { + // In RTO mode, a probe packet has to be sent. + // Add a PING frame to make sure a (retransmittable) packet will be sent. + s.queueControlFrame(&wire.PingFrame{}) + sentPacket, err := s.sendPacket() + if err != nil { + return err + } + if !sentPacket { + return errors.New("session BUG: expected a packet to be sent in RTO mode") + } + } + numPacketsSent++ case ackhandler.SendRetransmission: sentPacket, err := s.maybeSendRetransmission() if err != nil { @@ -858,16 +947,16 @@ func (s *session) maybeSendRetransmission() (bool, error) { // An Initial might have been retransmitted multiple times before we receive a response. // As soon as we receive one response, we don't need to send any more Initials. if s.receivedFirstPacket && retransmitPacket.PacketType == protocol.PacketTypeInitial { - utils.Debugf("Skipping retransmission of packet %d. Already received a response to an Initial.", retransmitPacket.PacketNumber) + s.logger.Debugf("Skipping retransmission of packet %d. Already received a response to an Initial.", retransmitPacket.PacketNumber) continue } break } if retransmitPacket.EncryptionLevel != protocol.EncryptionForwardSecure { - utils.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber) + s.logger.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber) } else { - utils.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber) + s.logger.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber) } if s.version.UsesStopWaitingFrames() { @@ -938,14 +1027,14 @@ func (s *session) sendConnectionClose(quicErr *qerr.QuicError) error { } func (s *session) logPacket(packet *packedPacket) { - if !utils.Debug() { + if !s.logger.Debug() { // We don't need to allocate the slices for calling the format functions return } - utils.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", packet.header.PacketNumber, len(packet.raw), s.connectionID, packet.encryptionLevel) - packet.header.Log() + s.logger.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", packet.header.PacketNumber, len(packet.raw), s.connectionID, packet.encryptionLevel) + packet.header.Log(s.logger) for _, frame := range packet.frames { - wire.LogFrame(frame, true) + wire.LogFrame(s.logger, frame, true) } } @@ -1008,6 +1097,7 @@ func (s *session) newFlowController(id protocol.StreamID) flowcontrol.StreamFlow protocol.ByteCount(s.config.MaxReceiveStreamFlowControlWindow), initialSendWindow, s.rttStats, + s.logger, ) } @@ -1021,12 +1111,13 @@ func (s *session) newCryptoStream() cryptoStreamI { protocol.ByteCount(s.config.MaxReceiveStreamFlowControlWindow), 0, s.rttStats, + s.logger, ) return newCryptoStream(s, flowController, s.version) } func (s *session) sendPublicReset(rejectedPacketNumber protocol.PacketNumber) error { - utils.Infof("Sending public reset for connection %x, packet number %d", s.connectionID, rejectedPacketNumber) + s.logger.Infof("Sending public reset for connection %x, packet number %d", s.connectionID, rejectedPacketNumber) return s.conn.Write(wire.WritePublicReset(s.connectionID, rejectedPacketNumber, 0)) } @@ -1040,7 +1131,7 @@ func (s *session) scheduleSending() { func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket) { if s.handshakeComplete { - utils.Debugf("Received undecryptable packet from %s after the handshake: %#v, %d bytes data", p.remoteAddr.String(), p.header, len(p.data)) + s.logger.Debugf("Received undecryptable packet from %s after the handshake: %#v, %d bytes data", p.remoteAddr.String(), p.header, len(p.data)) return } if len(s.undecryptablePackets)+1 > protocol.MaxUndecryptablePackets { @@ -1049,10 +1140,10 @@ func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket) { s.receivedTooManyUndecrytablePacketsTime = time.Now() s.maybeResetTimer() } - utils.Infof("Dropping undecrytable packet 0x%x (undecryptable packet queue full)", p.header.PacketNumber) + s.logger.Infof("Dropping undecrytable packet 0x%x (undecryptable packet queue full)", p.header.PacketNumber) return } - utils.Infof("Queueing packet 0x%x for later decryption", p.header.PacketNumber) + s.logger.Infof("Queueing packet 0x%x for later decryption", p.header.PacketNumber) s.undecryptablePackets = append(s.undecryptablePackets, p) } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go new file mode 100644 index 000000000..f48db212d --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go @@ -0,0 +1,11 @@ +package quic + +import "github.com/cheekybits/genny/generic" + +// In the auto-generated streams maps, we need to be able to close the streams. +// Therefore, extend the generic.Type with the stream close method. +// This definition must be in a file that Genny doesn't process. +type item interface { + generic.Type + closeForShutdown(error) +} diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go index f7f80a280..317f5e237 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go @@ -123,6 +123,9 @@ func (m *incomingBidiStreamsMap) DeleteStream(id protocol.StreamID) error { func (m *incomingBidiStreamsMap) CloseWithError(err error) { m.mutex.Lock() m.closeErr = err + for _, str := range m.streams { + str.closeForShutdown(err) + } m.mutex.Unlock() m.cond.Broadcast() } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go index 40d7b7500..58f1ccbe2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go @@ -121,6 +121,9 @@ func (m *incomingItemsMap) DeleteStream(id protocol.StreamID) error { func (m *incomingItemsMap) CloseWithError(err error) { m.mutex.Lock() m.closeErr = err + for _, str := range m.streams { + str.closeForShutdown(err) + } m.mutex.Unlock() m.cond.Broadcast() } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go index f9fe97b7e..8e775aac5 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go @@ -123,6 +123,9 @@ func (m *incomingUniStreamsMap) DeleteStream(id protocol.StreamID) error { func (m *incomingUniStreamsMap) CloseWithError(err error) { m.mutex.Lock() m.closeErr = err + for _, str := range m.streams { + str.closeForShutdown(err) + } m.mutex.Unlock() m.cond.Broadcast() } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go index e7d9150be..ea9f47e60 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go @@ -118,6 +118,9 @@ func (m *outgoingBidiStreamsMap) SetMaxStream(id protocol.StreamID) { func (m *outgoingBidiStreamsMap) CloseWithError(err error) { m.mutex.Lock() m.closeErr = err + for _, str := range m.streams { + str.closeForShutdown(err) + } m.cond.Broadcast() m.mutex.Unlock() } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go index 80236c153..f4b3eb619 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go @@ -4,14 +4,11 @@ import ( "fmt" "sync" - "github.com/cheekybits/genny/generic" "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/wire" "github.com/lucas-clemente/quic-go/qerr" ) -type item generic.Type - //go:generate genny -in $GOFILE -out streams_map_outgoing_bidi.go gen "item=streamI Item=BidiStream" //go:generate genny -in $GOFILE -out streams_map_outgoing_uni.go gen "item=sendStreamI Item=UniStream" type outgoingItemsMap struct { @@ -119,6 +116,9 @@ func (m *outgoingItemsMap) SetMaxStream(id protocol.StreamID) { func (m *outgoingItemsMap) CloseWithError(err error) { m.mutex.Lock() m.closeErr = err + for _, str := range m.streams { + str.closeForShutdown(err) + } m.cond.Broadcast() m.mutex.Unlock() } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go index fd2701b75..6ad0348c4 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go @@ -118,6 +118,9 @@ func (m *outgoingUniStreamsMap) SetMaxStream(id protocol.StreamID) { func (m *outgoingUniStreamsMap) CloseWithError(err error) { m.mutex.Lock() m.closeErr = err + for _, str := range m.streams { + str.closeForShutdown(err) + } m.cond.Broadcast() m.mutex.Unlock() } diff --git a/vendor/github.com/xenolf/lego/acmev2/client.go b/vendor/github.com/xenolf/lego/acmev2/client.go index 40acdbc14..3698f0eca 100644 --- a/vendor/github.com/xenolf/lego/acmev2/client.go +++ b/vendor/github.com/xenolf/lego/acmev2/client.go @@ -265,7 +265,7 @@ func (c *Client) QueryRegistration() (*RegistrationResource, error) { // your issued certificate as a bundle. // This function will never return a partial certificate. If one domain in the list fails, // the whole certificate will fail. -func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, map[string]error) { +func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, error) { // figure out what domains it concerns // start with the common name domains := []string{csr.Subject.CommonName} @@ -292,11 +292,7 @@ DNSNames: order, err := c.createOrderForIdentifiers(domains) if err != nil { - identErrors := make(map[string]error) - for _, auth := range order.Identifiers { - identErrors[auth.Value] = err - } - return CertificateResource{}, identErrors + return CertificateResource{}, err } authz, failures := c.getAuthzForOrder(order) // If any challenge fails - return. Do not generate partial SAN certificates. @@ -338,7 +334,11 @@ DNSNames: // your issued certificate as a bundle. // This function will never return a partial certificate. If one domain in the list fails, // the whole certificate will fail. -func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, map[string]error) { +func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) { + if len(domains) == 0 { + return CertificateResource{}, errors.New("Passed no domains into ObtainCertificate") + } + if bundle { logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", ")) } else { @@ -347,11 +347,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto order, err := c.createOrderForIdentifiers(domains) if err != nil { - identErrors := make(map[string]error) - for _, auth := range order.Identifiers { - identErrors[auth.Value] = err - } - return CertificateResource{}, identErrors + return CertificateResource{}, err } authz, failures := c.getAuthzForOrder(order) // If any challenge fails - return. Do not generate partial SAN certificates. @@ -433,7 +429,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b return CertificateResource{}, err } newCert, failures := c.ObtainCertificateForCSR(*csr, bundle) - return newCert, failures[cert.Domain] + return newCert, failures } var privKey crypto.PrivateKey @@ -445,7 +441,6 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b } var domains []string - var failures map[string]error // check for SAN certificate if len(x509Cert.DNSNames) > 1 { domains = append(domains, x509Cert.Subject.CommonName) @@ -459,8 +454,8 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b domains = append(domains, x509Cert.Subject.CommonName) } - newCert, failures := c.ObtainCertificate(domains, bundle, privKey, mustStaple) - return newCert, failures[cert.Domain] + newCert, err := c.ObtainCertificate(domains, bundle, privKey, mustStaple) + return newCert, err } func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) { @@ -482,6 +477,7 @@ func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, err orderRes := orderResource{ URL: hdr.Get("Location"), + Domains: domains, orderMessage: response, } return orderRes, nil @@ -489,9 +485,9 @@ func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, err // Looks through the challenge combinations to find a solvable match. // Then solves the challenges in series and returns. -func (c *Client) solveChallengeForAuthz(authorizations []authorization) map[string]error { +func (c *Client) solveChallengeForAuthz(authorizations []authorization) ObtainError { // loop through the resources, basically through the domains. - failures := make(map[string]error) + failures := make(ObtainError) for _, authz := range authorizations { if authz.Status == "valid" { // Boulder might recycle recent validated authz (see issue #267) @@ -527,7 +523,7 @@ func (c *Client) chooseSolver(auth authorization, domain string) (int, solver) { } // Get the challenges needed to proof our identifier to the ACME server. -func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, map[string]error) { +func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, ObtainError) { resc, errc := make(chan authorization), make(chan domainError) delay := time.Second / overallRequestLimit @@ -590,7 +586,7 @@ func (c *Client) requestCertificateForOrder(order orderResource, bundle bool, pr } // determine certificate name(s) based on the authorization resources - commonName := order.Identifiers[0].Value + commonName := order.Domains[0] var san []string for _, auth := range order.Identifiers { san = append(san, auth.Value) @@ -606,12 +602,7 @@ func (c *Client) requestCertificateForOrder(order orderResource, bundle bool, pr } func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr []byte, privateKeyPem []byte) (CertificateResource, error) { - commonName := order.Identifiers[0].Value - - var authURLs []string - for _, auth := range order.Identifiers[1:] { - authURLs = append(authURLs, auth.Value) - } + commonName := order.Domains[0] csrString := base64.RawURLEncoding.EncodeToString(csr) var retOrder orderMessage diff --git a/vendor/github.com/xenolf/lego/acmev2/error.go b/vendor/github.com/xenolf/lego/acmev2/error.go index 650270b1e..78694debe 100644 --- a/vendor/github.com/xenolf/lego/acmev2/error.go +++ b/vendor/github.com/xenolf/lego/acmev2/error.go @@ -1,6 +1,7 @@ package acme import ( + "bytes" "encoding/json" "fmt" "io/ioutil" @@ -42,6 +43,18 @@ type domainError struct { Error error } +// ObtainError is returned when there are specific errors available +// per domain. For example in ObtainCertificate +type ObtainError map[string]error + +func (e ObtainError) Error() string { + buffer := bytes.NewBufferString("acme: Error -> One or more domains had a problem:\n") + for dom, err := range e { + buffer.WriteString(fmt.Sprintf("[%s] %s\n", dom, err)) + } + return buffer.String() +} + func handleHTTPError(resp *http.Response) error { var errorDetail RemoteError diff --git a/vendor/github.com/xenolf/lego/acmev2/messages.go b/vendor/github.com/xenolf/lego/acmev2/messages.go index 9981851d9..0b7344372 100644 --- a/vendor/github.com/xenolf/lego/acmev2/messages.go +++ b/vendor/github.com/xenolf/lego/acmev2/messages.go @@ -34,7 +34,8 @@ type accountMessage struct { } type orderResource struct { - URL string `json:"url,omitempty"` + URL string `json:"url,omitempty"` + Domains []string `json:"domains,omitempty"` orderMessage `json:"body,omitempty"` } diff --git a/vendor/manifest b/vendor/manifest index 95306189a..b106ecf28 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -129,7 +129,7 @@ "importpath": "github.com/lucas-clemente/aes12", "repository": "https://github.com/lucas-clemente/aes12", "vcs": "git", - "revision": "25700e67be5c860bcc999137275b9ef8b65932bd", + "revision": "cd47fb39b79f867c6e4e5cd39cf7abd799f71670", "branch": "master", "notests": true }, @@ -145,7 +145,7 @@ "importpath": "github.com/lucas-clemente/quic-go", "repository": "https://github.com/lucas-clemente/quic-go", "vcs": "git", - "revision": "9fa739409e6edddbbd47c8031cb7bb3d1a209cc8", + "revision": "da7708e47066ab0aff0f20f66b21c1f329db1eff", "branch": "master", "notests": true }, @@ -193,7 +193,7 @@ "importpath": "github.com/xenolf/lego/acmev2", "repository": "https://github.com/xenolf/lego", "vcs": "git", - "revision": "805eec97569ff533e1b75b16eac0bdd94e67bdd6", + "revision": "6e962fbfb37f9ea4a8201e32acb1b94ffb3b8398", "branch": "acmev2", "path": "/acmev2", "notests": true