func (s *Conn) recv(b []byte, now time.Time) (int, error) {
	p := packet{
		header: packetHeader{
			dcil: uint8(len(s.scid)),
		},
	}
	_, err := p.decodeHeader(b)
	if err != nil {
		s.logPacketDropped(&p, logTriggerHeaderParseError, now)
		return 0, newPacketDroppedError(logTriggerHeaderParseError)
	}
	switch p.typ {
	case packetTypeInitial:
		return s.recvPacketInitial(b, &p, now)
	case packetTypeZeroRTT:
		return 0, newError(InternalError, "zerortt packet not supported")
	case packetTypeHandshake:
		return s.recvPacketHandshake(b, &p, now)
	case packetTypeRetry:
		return s.recvPacketRetry(b, &p, now)
	case packetTypeVersionNegotiation:
		return s.recvPacketVersionNegotiation(b, &p, now)
	case packetTypeOneRTT:
		return s.recvPacketShort(b, &p, now)
	default:
		panic(sprint("unsupported packet type ", p.typ))
	}
}
recv processes single received packet.
package transport
import (
	"bytes"
	"crypto/tls"
	"time"
)
type connectionState uint8
const (
	stateAttempted connectionState = iota
	stateHandshake
	stateActive
	stateDraining
	stateClosed
)
var connectionStateNames = [...]string{
	stateAttempted: "attempted",
	stateHandshake: "handshake",
	stateActive:    "active",
	stateDraining:  "draining",
	stateClosed:    "closed",
}
func (s connectionState) String() string {
	return connectionStateNames[s]
}
type ConnectionState struct {
	State string  
	RecvPackets uint64
	RecvBytes   uint64
	SentPackets uint64
	SentBytes   uint64
	LostPackets uint64
	LostBytes   uint64
	PeerParams Parameters
	TLS tls.ConnectionState
	LocalError error
	PeerError  error
}
type Conn struct {
	scid  []byte  
	dcid  []byte  
	odcid []byte  
	rscid []byte  
	token []byte  
	packetNumberSpaces [packetSpaceCount]*packetNumberSpace
	streams            streamMap
	datagram           Datagram
	localParams Parameters
	peerParams  Parameters
	handshake tlsHandshake
	recovery  lossRecovery
	flow      flowControl
	timeFn func() time.Time  
	idleTimer     time.Time  
	drainingTimer time.Time  
	pathResponse []byte  
	localError *Error  
	peerError  *Error  
	events []Event
	logEventFn func(LogEvent)
	sentPackets uint64
	sentBytes   uint64
	recvPackets uint64
	recvBytes   uint64
	invalidPackets uint  
	version               uint32
	state                 connectionState
	isClient              bool
	gotPeerCID            bool
	didRetry              bool
	didVersionNegotiation bool
	peerAddressVerified   bool  
	ackElicitingSent      bool  
	handshakeConfirmed    bool  
	derivedInitialSecrets bool
	updateMaxData         bool  
}
func Connect(scid, dcid []byte, config *Config) (*Conn, error) {
	return newConn(config, scid, dcid, true)
}
func Accept(scid, odcid []byte, config *Config) (*Conn, error) {
	return newConn(config, scid, odcid, false)
}
func newConn(config *Config, scid, dcid []byte, isClient bool) (*Conn, error) {
	if config == nil {
		return nil, newError(InternalError, "config required")
	}
	if len(scid) > MaxCIDLength || len(dcid) > MaxCIDLength {
		return nil, newError(ProtocolViolation, sprint("cid length exceeded ", MaxCIDLength))
	}
	s := &Conn{
		version:     config.Version,
		isClient:    isClient,
		localParams: config.Params,
		state:       stateAttempted,
	}
	for i := range s.packetNumberSpaces {
		s.packetNumberSpaces[i] = newPacketNumberSpace()
	}
	if config.MaxPacketsPerKey > 0 {
		s.packetNumberSpaces[packetSpaceApplication].maxEncryptedPackets = config.MaxPacketsPerKey
	}
	if config.TLS != nil && config.TLS.Time != nil {
		s.timeFn = config.TLS.Time
	} else {
		s.timeFn = time.Now
	}
	s.handshake.init(config.TLS, &s.packetNumberSpaces, isClient)
	s.streams.init(s.localParams.InitialMaxStreamsBidi, s.localParams.InitialMaxStreamsUni)
	s.recovery.init()
	s.recovery.enablePacing = enablePacing
	s.recovery.congestion.enableCubic = enableCubic
	s.recovery.congestion.enablePRR = enablePRR
	s.flow.init(s.localParams.InitialMaxData, 0)
	s.scid = scid
	s.localParams.InitialSourceCID = s.scid  
	s.localParams.OriginalDestinationCID = nil
	s.localParams.RetrySourceCID = nil
	if isClient {
		s.localParams.StatelessResetToken = nil
		if len(dcid) == 0 {
			return nil, newError(InternalError, "destination cid required")
		}
		s.dcid = dcid
		s.deriveInitialKeyMaterial(s.dcid)
	} else {
		if len(dcid) > 0 {
			s.odcid = dcid
			s.localParams.OriginalDestinationCID = s.odcid
			s.localParams.RetrySourceCID = s.scid
			s.didRetry = true  
			s.peerAddressVerified = true
		}
		s.recovery.setPeerCompletedAddressValidation()
	}
	if err := s.localParams.validate(isClient); err != nil {
		return nil, err
	}
	s.handshake.setTransportParams(&s.localParams)
	s.datagram.setMaxRecv(s.localParams.MaxDatagramFramePayloadSize)
	return s, nil
}
func (s *Conn) Write(b []byte) (int, error) {
	now := s.timeFn()
	n := 0
	for n < len(b) {
		if s.state >= stateDraining {
			break
		}
		i, err := s.recv(b[n:], now)
		n += i
		s.recvPackets++
		s.recvBytes += uint64(i)
		if err != nil {
			return n, err
		}
	}
	if n == 0 || !s.handshakeConfirmed {
		s.checkTimeout(now)
	}
	return n, nil
}
func (s *Conn) deriveInitialKeyMaterial(cid []byte) {
	client, server := newInitialSecrets(cid)
	pnSpace := s.packetNumberSpaces[packetSpaceInitial]
	if s.isClient {
		pnSpace.opener, pnSpace.sealer = server, client
	} else {
		pnSpace.opener, pnSpace.sealer = client, server
	}
	s.derivedInitialSecrets = true
}