Browse Source

implement ReadMultiBuffer in quic conn

Darien Raymond 7 years ago
parent
commit
61ad81c326

+ 23 - 0
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

+ 1 - 9
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

+ 3 - 0
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

+ 34 - 57
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]
+	// 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
+		}
+	}
+	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
 		}
-	}
-	for _, frame := range frames {
-		if err := frame.Write(buffer, p.version); err != nil {
-			return nil, err
+	} 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 addPadding {
+	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
 }

+ 0 - 1
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())
 	}
 

+ 4 - 0
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) {

+ 2 - 9
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

+ 12 - 0
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