func (s *session) run() error {
	defer s.ctxCancel()
	go func() {
		if err := s.cryptoStreamHandler.RunHandshake(); err != nil {
			s.closeLocal(err)
			return
		}
		close(s.handshakeCompleteChan)
	}()
	if s.perspective == protocol.PerspectiveClient {
		select {
		case <-s.clientHelloWritten:
			s.scheduleSending()
		case closeErr := <-s.closeChan:
			s.closeChan <- closeErr
		}
	}
	var closeErr closeError
runLoop:
	for {
		select {
		case closeErr = <-s.closeChan:
			break runLoop
		case <-s.handshakeCompleteChan:
			s.handleHandshakeComplete()
		default:
		}
		s.maybeResetTimer()
		select {
		case closeErr = <-s.closeChan:
			break runLoop
		case <-s.timer.Chan():
			s.timer.SetRead()
		case <-s.sendingScheduled:
		case p := <-s.receivedPackets:
			if wasProcessed := s.handlePacketImpl(p); !wasProcessed {
				continue
			}
		case <-s.handshakeCompleteChan:
			s.handleHandshakeComplete()
		}
		now := time.Now()
		if timeout := s.sentPacketHandler.GetAlarmTimeout(); !timeout.IsZero() && timeout.Before(now) {
			if err := s.sentPacketHandler.OnAlarm(); err != nil {
				s.closeLocal(err)
			}
		}
		var pacingDeadline time.Time
		if s.pacingDeadline.IsZero() {  
			pacingDeadline = s.sentPacketHandler.TimeUntilSend()
		}
		if s.config.KeepAlive && !s.keepAlivePingSent && s.handshakeComplete && s.firstRetransmittablePacketAfterIdleSentTime.IsZero() && time.Since(s.lastPacketReceivedTime) >= s.peerParams.IdleTimeout/2 {
			s.logger.Debugf("Sending a keep-alive ping to keep the connection alive.")
			s.framer.QueueControlFrame(&wire.PingFrame{})
			s.keepAlivePingSent = true
		} else if !pacingDeadline.IsZero() && now.Before(pacingDeadline) {
			s.pacingDeadline = pacingDeadline
			continue
		}
		if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.HandshakeTimeout {
			s.destroy(qerr.TimeoutError("Handshake did not complete in time"))
			continue
		}
		if s.handshakeComplete && now.Sub(s.idleTimeoutStartTime()) >= s.config.IdleTimeout {
			s.destroy(qerr.TimeoutError("No recent network activity"))
			continue
		}
		if err := s.sendPackets(); err != nil {
			s.closeLocal(err)
		}
	}
	s.handleCloseError(closeErr)
	s.closed.Set(true)
	s.logger.Infof("Connection %s closed.", s.srcConnID)
	s.cryptoStreamHandler.Close()
	return closeErr.err
}
run the session main loop
package quic
import (
	"bytes"
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"reflect"
	"sync"
	"time"
	"github.com/lucas-clemente/quic-go/internal/ackhandler"
	"github.com/lucas-clemente/quic-go/internal/congestion"
	"github.com/lucas-clemente/quic-go/internal/flowcontrol"
	"github.com/lucas-clemente/quic-go/internal/handshake"
	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/qerr"
	"github.com/lucas-clemente/quic-go/internal/utils"
	"github.com/lucas-clemente/quic-go/internal/wire"
)
type unpacker interface {
	Unpack(hdr *wire.Header, data []byte) (*unpackedPacket, error)
}
type streamGetter interface {
	GetOrOpenReceiveStream(protocol.StreamID) (receiveStreamI, error)
	GetOrOpenSendStream(protocol.StreamID) (sendStreamI, error)
}
type streamManager interface {
	GetOrOpenSendStream(protocol.StreamID) (sendStreamI, error)
	GetOrOpenReceiveStream(protocol.StreamID) (receiveStreamI, error)
	OpenStream() (Stream, error)
	OpenUniStream() (SendStream, error)
	OpenStreamSync() (Stream, error)
	OpenUniStreamSync() (SendStream, error)
	AcceptStream() (Stream, error)
	AcceptUniStream() (ReceiveStream, error)
	DeleteStream(protocol.StreamID) error
	UpdateLimits(*handshake.TransportParameters) error
	HandleMaxStreamsFrame(*wire.MaxStreamsFrame) error
	CloseWithError(error)
}
type cryptoStreamHandler interface {
	RunHandshake() error
	ChangeConnectionID(protocol.ConnectionID) error
	io.Closer
	ConnectionState() tls.ConnectionState
}
type receivedPacket struct {
	remoteAddr net.Addr
	rcvTime    time.Time
	data       []byte
	buffer *packetBuffer
}
func (p *receivedPacket) Clone() *receivedPacket {
	return &receivedPacket{
		remoteAddr: p.remoteAddr,
		rcvTime:    p.rcvTime,
		data:       p.data,
		buffer:     p.buffer,
	}
}
type closeError struct {
	err       error
	remote    bool
	sendClose bool
}
var errCloseForRecreating = errors.New("closing session in order to recreate it")
type session struct {
	sessionRunner sessionRunner
	destConnID     protocol.ConnectionID
	origDestConnID protocol.ConnectionID  
	srcConnID      protocol.ConnectionID
	perspective    protocol.Perspective
	initialVersion protocol.VersionNumber  
	version        protocol.VersionNumber
	config         *Config
	conn connection
	streamsMap streamManager
	rttStats *congestion.RTTStats
	cryptoStreamManager   *cryptoStreamManager
	sentPacketHandler     ackhandler.SentPacketHandler
	receivedPacketHandler ackhandler.ReceivedPacketHandler
	framer                framer
	windowUpdateQueue     *windowUpdateQueue
	connFlowController    flowcontrol.ConnectionFlowController
	unpacker    unpacker
	frameParser wire.FrameParser
	packer      packer
	cryptoStreamHandler cryptoStreamHandler
	receivedPackets  chan *receivedPacket
	sendingScheduled chan struct{}
	closeOnce sync.Once
	closed    utils.AtomicBool
	closeChan                 chan closeError
	connectionClosePacket     *packedPacket
	packetsReceivedAfterClose int
	ctx       context.Context
	ctxCancel context.CancelFunc
	undecryptablePackets []*receivedPacket
	clientHelloWritten    <-chan struct{}
	handshakeCompleteChan chan struct{}  
	handshakeComplete     bool
	receivedRetry                    bool
	receivedFirstPacket              bool
	receivedFirstForwardSecurePacket bool
	sessionCreationTime time.Time
	lastPacketReceivedTime time.Time
	firstRetransmittablePacketAfterIdleSentTime time.Time
	pacingDeadline time.Time
	peerParams *handshake.TransportParameters
	timer *utils.Timer
	keepAlivePingSent bool
	logger utils.Logger
}
var _ Session = &session{}
var _ streamSender = &session{}
var newSession = func(
	conn connection,
	runner sessionRunner,
	clientDestConnID protocol.ConnectionID,
	destConnID protocol.ConnectionID,
	srcConnID protocol.ConnectionID,
	conf *Config,
	tlsConf *tls.Config,
	params *handshake.TransportParameters,
	logger utils.Logger,
	v protocol.VersionNumber,
) (quicSession, error) {
	s := &session{
		conn:                  conn,
		sessionRunner:         runner,
		config:                conf,
		srcConnID:             srcConnID,
		destConnID:            destConnID,
		perspective:           protocol.PerspectiveServer,
		handshakeCompleteChan: make(chan struct{}),
		logger:                logger,
		version:               v,
	}
	s.preSetup()
	s.sentPacketHandler = ackhandler.NewSentPacketHandler(0, s.rttStats, s.logger)
	s.streamsMap = newStreamsMap(
		s,
		s.newFlowController,
		uint64(s.config.MaxIncomingStreams),
		uint64(s.config.MaxIncomingUniStreams),
		s.perspective,
		s.version,
	)
	s.framer = newFramer(s.streamsMap, s.version)
	initialStream := newCryptoStream()
	handshakeStream := newCryptoStream()
	oneRTTStream := newPostHandshakeCryptoStream(s.framer)
	cs, err := handshake.NewCryptoSetupServer(
		initialStream,
		handshakeStream,
		oneRTTStream,
		clientDestConnID,
		conn.RemoteAddr(),
		params,
		s.processTransportParameters,
		tlsConf,
		logger,
	)
	if err != nil {
		return nil, err
	}
	s.cryptoStreamHandler = cs
	s.packer = newPacketPacker(
		s.destConnID,
		s.srcConnID,
		initialStream,
		handshakeStream,
		s.sentPacketHandler,
		s.RemoteAddr(),
		cs,
		s.framer,
		s.receivedPacketHandler,
		s.perspective,
		s.version,
	)
	s.cryptoStreamManager = newCryptoStreamManager(cs, initialStream, handshakeStream, oneRTTStream)
	if err := s.postSetup(); err != nil {
		return nil, err
	}
	s.unpacker = newPacketUnpacker(cs, s.version)
	return s, nil
}
var newClientSession = func(
	conn connection,
	runner sessionRunner,
	destConnID protocol.ConnectionID,
	srcConnID protocol.ConnectionID,
	conf *Config,
	tlsConf *tls.Config,
	initialPacketNumber protocol.PacketNumber,
	params *handshake.TransportParameters,
	initialVersion protocol.VersionNumber,
	logger utils.Logger,
	v protocol.VersionNumber,
) (quicSession, error) {
	s := &session{
		conn:                  conn,
		sessionRunner:         runner,
		config:                conf,
		srcConnID:             srcConnID,
		destConnID:            destConnID,
		perspective:           protocol.PerspectiveClient,
		handshakeCompleteChan: make(chan struct{}),
		logger:                logger,
		initialVersion:        initialVersion,
		version:               v,
	}
	s.preSetup()
	s.sentPacketHandler = ackhandler.NewSentPacketHandler(initialPacketNumber, s.rttStats, s.logger)
	initialStream := newCryptoStream()
	handshakeStream := newCryptoStream()
	oneRTTStream := newPostHandshakeCryptoStream(s.framer)
	cs, clientHelloWritten, err := handshake.NewCryptoSetupClient(
		initialStream,
		handshakeStream,
		oneRTTStream,
		s.destConnID,
		conn.RemoteAddr(),
		params,
		s.processTransportParameters,
		tlsConf,
		logger,
	)
	if err != nil {
		return nil, err
	}
	s.clientHelloWritten = clientHelloWritten
	s.cryptoStreamHandler = cs
	s.cryptoStreamManager = newCryptoStreamManager(cs, initialStream, handshakeStream, oneRTTStream)
	s.unpacker = newPacketUnpacker(cs, s.version)
	s.streamsMap = newStreamsMap(
		s,
		s.newFlowController,
		uint64(s.config.MaxIncomingStreams),
		uint64(s.config.MaxIncomingUniStreams),
		s.perspective,
		s.version,
	)
	s.framer = newFramer(s.streamsMap, s.version)
	s.packer = newPacketPacker(
		s.destConnID,
		s.srcConnID,
		initialStream,
		handshakeStream,
		s.sentPacketHandler,
		s.RemoteAddr(),
		cs,
		s.framer,
		s.receivedPacketHandler,
		s.perspective,
		s.version,
	)
	return s, s.postSetup()
}
func (s *session) preSetup() {
	s.frameParser = wire.NewFrameParser(s.version)
	s.rttStats = &congestion.RTTStats{}
	s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.logger, s.version)
	s.connFlowController = flowcontrol.NewConnectionFlowController(
		protocol.InitialMaxData,
		protocol.ByteCount(s.config.MaxReceiveConnectionFlowControlWindow),
		s.onHasConnectionWindowUpdate,
		s.rttStats,
		s.logger,
	)
}
func (s *session) postSetup() error {
	s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets)
	s.closeChan = make(chan closeError, 1)
	s.sendingScheduled = make(chan struct{}, 1)
	s.undecryptablePackets = make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets)
	s.ctx, s.ctxCancel = context.WithCancel(context.Background())
	s.timer = utils.NewTimer()
	now := time.Now()
	s.lastPacketReceivedTime = now
	s.sessionCreationTime = now
	s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.connFlowController, s.framer.QueueControlFrame)
	return nil
}