diff --git a/transport/internet/quic/conn.go b/transport/internet/quic/conn.go index a5b7ccf9e..2b730833b 100644 --- a/transport/internet/quic/conn.go +++ b/transport/internet/quic/conn.go @@ -142,6 +142,29 @@ func (c *interConn) Read(b []byte) (int, error) { return c.stream.Read(b) } +func (c *interConn) ReadMultiBuffer() (buf.MultiBuffer, error) { + mb := make(buf.MultiBuffer, 0, 8) + { + b := buf.New() + if _, err := b.ReadFrom(c.stream); err != nil { + b.Release() + return nil, err + } + mb = append(mb, b) + } + + for c.stream.HasMoreData() { + b := buf.New() + if _, err := b.ReadFrom(c.stream); err != nil { + b.Release() + break + } + mb = append(mb, b) + } + + return mb, nil +} + func (c *interConn) WriteMultiBuffer(mb buf.MultiBuffer) error { if mb.IsEmpty() { return nil diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go index 13847ffda..7f4661e81 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go @@ -8,13 +8,6 @@ const MaxPacketSizeIPv4 = 1252 // MaxPacketSizeIPv6 is the maximum packet size that we use for sending IPv6 packets. const MaxPacketSizeIPv6 = 1232 -// MinStatelessResetSize is the minimum size of a stateless reset packet -const MinStatelessResetSize = 1 + 20 + 16 - -// NonForwardSecurePacketSizeReduction is the number of bytes a non forward-secure packet has to be smaller than a forward-secure packet -// This makes sure that those packets can always be retransmitted without splitting the contained StreamFrames -const NonForwardSecurePacketSizeReduction = 50 - const defaultMaxCongestionWindowPackets = 1000 // DefaultMaxCongestionWindow is the default for the max congestion window @@ -23,8 +16,7 @@ const DefaultMaxCongestionWindow ByteCount = defaultMaxCongestionWindowPackets * // InitialCongestionWindow is the initial congestion window in QUIC packets const InitialCongestionWindow ByteCount = 32 * DefaultTCPMSS -// MaxUndecryptablePackets limits the number of undecryptable packets that a -// session queues for later until it sends a public reset. +// MaxUndecryptablePackets limits the number of undecryptable packets that are queued in the session. const MaxUndecryptablePackets = 10 // ConnectionFlowControlMultiplier determines how much larger the connection flow control windows needs to be relative to any stream's flow control window diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/protocol.go b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/protocol.go index 929708db9..26f69fdc6 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/protocol.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/protocol.go @@ -58,5 +58,8 @@ const DefaultTCPMSS ByteCount = 1460 // MinInitialPacketSize is the minimum size an Initial packet is required to have. const MinInitialPacketSize = 1200 +// MinStatelessResetSize is the minimum size of a stateless reset packet +const MinStatelessResetSize = 1 /* first byte */ + 22 /* random bytes */ + 16 /* token */ + // MinConnectionIDLenInitial is the minimum length of the destination connection ID on an Initial packet. const MinConnectionIDLenInitial = 8 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 a87fcc809..291b64ac2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_packer.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go @@ -96,7 +96,6 @@ type packetPacker struct { acks ackFrameSource maxPacketSize protocol.ByteCount - hasSentPacket bool // has the packetPacker already sent a packet numNonRetransmittableAcks int } @@ -168,14 +167,12 @@ func (p *packetPacker) MaybePackAckPacket() (*packedPacket, error) { // For packets sent after completion of the handshake, it might happen that 2 packets have to be sent. // This can happen e.g. when a longer packet number is used in the header. func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedPacket, error) { - if packet.EncryptionLevel != protocol.Encryption1RTT { - p, err := p.packHandshakeRetransmission(packet) - return []*packedPacket{p}, err - } - var controlFrames []wire.Frame var streamFrames []*wire.StreamFrame for _, f := range packet.Frames { + // CRYPTO frames are treated as control frames here. + // Since we're making sure that the header can never be larger for a retransmission, + // we never have to split CRYPTO frames. if sf, ok := f.(*wire.StreamFrame); ok { sf.DataLenPresent = true streamFrames = append(streamFrames, sf) @@ -244,27 +241,6 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP return packets, nil } -// packHandshakeRetransmission retransmits a handshake packet -func (p *packetPacker) packHandshakeRetransmission(packet *ackhandler.Packet) (*packedPacket, error) { - sealer, err := p.cryptoSetup.GetSealerWithEncryptionLevel(packet.EncryptionLevel) - if err != nil { - return nil, err - } - // make sure that the retransmission for an Initial packet is sent as an Initial packet - if packet.PacketType == protocol.PacketTypeInitial { - p.hasSentPacket = false - } - header := p.getHeader(packet.EncryptionLevel) - header.Type = packet.PacketType - raw, err := p.writeAndSealPacket(header, packet.Frames, sealer) - return &packedPacket{ - header: header, - raw: raw, - frames: packet.Frames, - encryptionLevel: packet.EncryptionLevel, - }, err -} - // PackPacket packs a new packet // the other controlFrames are sent in the next packet, but might be queued and sent in the next packet if the packet would overflow MaxPacketSize otherwise func (p *packetPacker) PackPacket() (*packedPacket, error) { @@ -275,10 +251,6 @@ func (p *packetPacker) PackPacket() (*packedPacket, error) { if packet != nil { return packet, nil } - // if this is the first packet to be send, make sure it contains stream data - if !p.hasSentPacket && packet == nil { - return nil, nil - } encLevel, sealer := p.cryptoSetup.GetSealer() header := p.getHeader(encLevel) @@ -288,7 +260,7 @@ func (p *packetPacker) PackPacket() (*packedPacket, error) { } maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLen - frames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel)) + frames, err := p.composeNextPacket(maxSize) if err != nil { return nil, err } @@ -360,10 +332,7 @@ func (p *packetPacker) maybePackCryptoPacket() (*packedPacket, error) { }, nil } -func (p *packetPacker) composeNextPacket( - maxFrameSize protocol.ByteCount, - canSendStreamFrames bool, -) ([]wire.Frame, error) { +func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount) ([]wire.Frame, error) { var length protocol.ByteCount var frames []wire.Frame @@ -377,10 +346,6 @@ func (p *packetPacker) composeNextPacket( frames, lengthAdded = p.framer.AppendControlFrames(frames, maxFrameSize-length) length += lengthAdded - if !canSendStreamFrames { - return frames, nil - } - // temporarily increase the maxFrameSize by the (minimum) length of the DataLen field // this leads to a properly sized packet in all cases, since we do all the packet length calculations with STREAM frames that have the DataLen set // however, for the last STREAM frame in the packet, we can omit the DataLen, thus yielding a packet of exactly the correct size @@ -407,6 +372,10 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Extend if encLevel != protocol.Encryption1RTT { header.IsLongHeader = true + // Always send Initial and Handshake packets with the maximum packet number length. + // This simplifies retransmissions: Since the header can't get any larger, + // we don't need to split CRYPTO frames. + header.PacketNumberLen = protocol.PacketNumberLen4 header.SrcConnectionID = p.srcConnID // Set the length to the maximum packet size. // Since it is encoded as a varint, this guarantees us that the header will end up at most as big as GetLength() returns. @@ -423,23 +392,24 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Extend } func (p *packetPacker) writeAndSealPacket( - header *wire.ExtendedHeader, frames []wire.Frame, + header *wire.ExtendedHeader, + frames []wire.Frame, sealer handshake.Sealer, ) ([]byte, error) { raw := *getPacketBuffer() buffer := bytes.NewBuffer(raw[:0]) - addPadding := p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial && !p.hasSentPacket + addPaddingForInitial := p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial - // the length is only needed for Long Headers if header.IsLongHeader { if p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial { header.Token = p.token } - if addPadding { + if addPaddingForInitial { headerLen := header.GetLength(p.version) header.Length = protocol.ByteCount(header.PacketNumberLen) + protocol.MinInitialPacketSize - headerLen } else { + // long header packets always use 4 byte packet number, so we never need to pad short payloads length := protocol.ByteCount(sealer.Overhead()) + protocol.ByteCount(header.PacketNumberLen) for _, frame := range frames { length += frame.Length(p.version) @@ -453,19 +423,31 @@ func (p *packetPacker) writeAndSealPacket( } payloadStartIndex := buffer.Len() - // the Initial packet needs to be padded, so the last STREAM frame must have the data length present - if p.perspective == protocol.PerspectiveClient && header.Type == protocol.PacketTypeInitial { - lastFrame := frames[len(frames)-1] - if sf, ok := lastFrame.(*wire.StreamFrame); ok { - sf.DataLenPresent = true - } - } - for _, frame := range frames { + // write all frames but the last one + for _, frame := range frames[:len(frames)-1] { if err := frame.Write(buffer, p.version); err != nil { return nil, err } } - if addPadding { + lastFrame := frames[len(frames)-1] + if addPaddingForInitial { + // when appending padding, we need to make sure that the last STREAM frames has the data length set + if sf, ok := lastFrame.(*wire.StreamFrame); ok { + sf.DataLenPresent = true + } + } else { + payloadLen := buffer.Len() - payloadStartIndex + int(lastFrame.Length(p.version)) + if paddingLen := 4 - int(header.PacketNumberLen) - payloadLen; paddingLen > 0 { + // Pad the packet such that packet number length + payload length is 4 bytes. + // This is needed to enable the peer to get a 16 byte sample for header protection. + buffer.Write(bytes.Repeat([]byte{0}, paddingLen)) + } + } + if err := lastFrame.Write(buffer, p.version); err != nil { + return nil, err + } + + if addPaddingForInitial { paddingLen := protocol.MinInitialPacketSize - sealer.Overhead() - buffer.Len() if paddingLen > 0 { buffer.Write(bytes.Repeat([]byte{0}, paddingLen)) @@ -484,14 +466,9 @@ func (p *packetPacker) writeAndSealPacket( if num != header.PacketNumber { return nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match") } - p.hasSentPacket = true return raw, nil } -func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool { - return encLevel == protocol.Encryption1RTT -} - func (p *packetPacker) ChangeDestConnectionID(connID protocol.ConnectionID) { p.destConnID = connID } 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 52aa47590..f75dcb754 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go @@ -58,7 +58,6 @@ func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.ExtendedHeader, d encryptionLevel = protocol.Encryption1RTT } if err != nil { - // Wrap err in quicError so that public reset is sent by session return nil, qerr.Error(qerr.DecryptionFailure, 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 33a3123c9..6abde79be 100644 --- a/vendor/github.com/lucas-clemente/quic-go/server.go +++ b/vendor/github.com/lucas-clemente/quic-go/server.go @@ -128,6 +128,10 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, } func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*server, error) { + // TODO(#1655): only require that tls.Config.Certificates or tls.Config.GetCertificate is set + if tlsConf == nil || len(tlsConf.Certificates) == 0 { + return nil, errors.New("quic: Certificates not set in tls.Config") + } config = populateServerConfig(config) for _, v := range config.Versions { if !protocol.IsValidVersion(v) { diff --git a/vendor/github.com/lucas-clemente/quic-go/session.go b/vendor/github.com/lucas-clemente/quic-go/session.go index 6ab7746d0..7880697bc 100644 --- a/vendor/github.com/lucas-clemente/quic-go/session.go +++ b/vendor/github.com/lucas-clemente/quic-go/session.go @@ -114,9 +114,7 @@ type session struct { receivedFirstPacket bool // since packet numbers start at 0, we can't use largestRcvdPacketNumber != 0 for this receivedFirstForwardSecurePacket bool - // Used to calculate the next packet number from the truncated wire - // representation, and sent back in public reset packets - largestRcvdPacketNumber protocol.PacketNumber + largestRcvdPacketNumber protocol.PacketNumber // used to calculate the next packet number sessionCreationTime time.Time lastNetworkActivityTime time.Time @@ -905,12 +903,7 @@ func (s *session) maybeSendRetransmission() (bool, error) { break } - if retransmitPacket.EncryptionLevel != protocol.Encryption1RTT { - s.logger.Debugf("Dequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber) - } else { - s.logger.Debugf("Dequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber) - } - + s.logger.Debugf("Dequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber) packets, err := s.packer.PackRetransmission(retransmitPacket) if err != nil { return false, err diff --git a/vendor/github.com/lucas-clemente/sync-files.sh b/vendor/github.com/lucas-clemente/sync-files.sh new file mode 100755 index 000000000..e2992df3d --- /dev/null +++ b/vendor/github.com/lucas-clemente/sync-files.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +rsync -rv "$GOPATH/src/github.com/lucas-clemente/quic-go/" "$GOPATH/src/v2ray.com/core/vendor/github.com/lucas-clemente/quic-go/" +find . -name "*_test.go" -delete +rm -rf ./quic-go/\.* +rm -rf ./quic-go/benchmark +rm -rf ./quic-go/docs +rm -rf ./quic-go/example +rm -rf ./quic-go/h2quic +rm -rf ./quic-go/integrationtests +rm -rf ./quic-go/vendor/golang\.org/ +rm ./quic-go/vendor/vendor.json