func (e *endpoint) handleSynSegment(ctx *listenContext, s *segment, opts *header.TCPSynOptions) {
	defer decSynRcvdCount()
	defer e.decSynRcvdCount()
	defer s.decRef()
	n, err := ctx.createEndpointAndPerformHandshake(s, opts)
	if err != nil {
		e.stack.Stats().TCP.FailedConnectionAttempts.Increment()
		e.stats.FailedConnectionAttempts.Increment()
		return
	}
	ctx.removePendingEndpoint(n)
	wq := &waiter.Queue{}
	n.startAcceptedLoop(wq)
	e.stack.Stats().TCP.PassiveConnectionOpenings.Increment()
	e.deliverAccepted(n)
}
handleSynSegment is called in its own goroutine once the listening endpoint
receives a SYN segment. It is responsible for completing the handshake and
queueing the new endpoint for acceptance.

A limited number of these goroutines are allowed before TCP starts using SYN
cookies to accept connections.
package tcp
import (
	"crypto/sha1"
	"encoding/binary"
	"hash"
	"io"
	"sync"
	"time"
	"github.com/google/netstack/rand"
	"github.com/google/netstack/sleep"
	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/seqnum"
	"github.com/google/netstack/tcpip/stack"
	"github.com/google/netstack/waiter"
)
const (
	tsLen = 8
	tsMask = (1 << tsLen) - 1
	tsOffset = 24
	hashMask = (1 << tsOffset) - 1
	maxTSDiff = 2
)
var (
	SynRcvdCountThreshold uint64 = 1000
	mssTable = []uint16{536, 1300, 1440, 1460}
)
func encodeMSS(mss uint16) uint32 {
	for i := len(mssTable) - 1; i > 0; i-- {
		if mss >= mssTable[i] {
			return uint32(i)
		}
	}
	return 0
}
var synRcvdCount struct {
	sync.Mutex
	value   uint64
	pending sync.WaitGroup
}
type listenContext struct {
	stack    *stack.Stack
	rcvWnd   seqnum.Size
	nonce    [2][sha1.BlockSize]byte
	listenEP *endpoint
	hasherMu sync.Mutex
	hasher   hash.Hash
	v6only   bool
	netProto tcpip.NetworkProtocolNumber
	pendingMu sync.Mutex
	pending sync.WaitGroup
	pendingEndpoints map[stack.TransportEndpointID]*endpoint
}
func timeStamp() uint32 {
	return uint32(time.Now().Unix()>>6) & tsMask
}
func incSynRcvdCount() bool {
	synRcvdCount.Lock()
	if synRcvdCount.value >= SynRcvdCountThreshold {
		synRcvdCount.Unlock()
		return false
	}
	synRcvdCount.pending.Add(1)
	synRcvdCount.value++
	synRcvdCount.Unlock()
	return true
}
func decSynRcvdCount() {
	synRcvdCount.Lock()
	synRcvdCount.value--
	synRcvdCount.pending.Done()
	synRcvdCount.Unlock()
}
func synCookiesInUse() bool {
	synRcvdCount.Lock()
	v := synRcvdCount.value
	synRcvdCount.Unlock()
	return v >= SynRcvdCountThreshold
}
func newListenContext(stk *stack.Stack, listenEP *endpoint, rcvWnd seqnum.Size, v6only bool, netProto tcpip.NetworkProtocolNumber) *listenContext {
	l := &listenContext{
		stack:            stk,
		rcvWnd:           rcvWnd,
		hasher:           sha1.New(),
		v6only:           v6only,
		netProto:         netProto,
		listenEP:         listenEP,
		pendingEndpoints: make(map[stack.TransportEndpointID]*endpoint),
	}
	rand.Read(l.nonce[0][:])
	rand.Read(l.nonce[1][:])
	return l
}
func (l *listenContext) cookieHash(id stack.TransportEndpointID, ts uint32, nonceIndex int) uint32 {
	var payload [8]byte
	binary.BigEndian.PutUint16(payload[0:], id.LocalPort)
	binary.BigEndian.PutUint16(payload[2:], id.RemotePort)
	binary.BigEndian.PutUint32(payload[4:], ts)
	l.hasherMu.Lock()
	l.hasher.Reset()
	l.hasher.Write(payload[:])
	l.hasher.Write(l.nonce[nonceIndex][:])
	io.WriteString(l.hasher, string(id.LocalAddress))
	io.WriteString(l.hasher, string(id.RemoteAddress))
	h := make([]byte, 0, sha1.Size)
	h = l.hasher.Sum(h)
	l.hasherMu.Unlock()
	return binary.BigEndian.Uint32(h[:])
}
func (l *listenContext) createCookie(id stack.TransportEndpointID, seq seqnum.Value, data uint32) seqnum.Value {
	ts := timeStamp()
	v := l.cookieHash(id, 0, 0) + uint32(seq) + (ts << tsOffset)
	v += (l.cookieHash(id, ts, 1) + data) & hashMask
	return seqnum.Value(v)
}
func (l *listenContext) isCookieValid(id stack.TransportEndpointID, cookie seqnum.Value, seq seqnum.Value) (uint32, bool) {
	ts := timeStamp()
	v := uint32(cookie) - l.cookieHash(id, 0, 0) - uint32(seq)
	cookieTS := v >> tsOffset
	if ((ts - cookieTS) & tsMask) > maxTSDiff {
		return 0, false
	}
	return (v - l.cookieHash(id, cookieTS, 1)) & hashMask, true
}
func (l *listenContext) createConnectingEndpoint(s *segment, iss seqnum.Value, irs seqnum.Value, rcvdSynOpts *header.TCPSynOptions) (*endpoint, *tcpip.Error) {
	netProto := l.netProto
	if netProto == 0 {
		netProto = s.route.NetProto
	}
	n := newEndpoint(l.stack, netProto, nil)
	n.v6only = l.v6only
	n.ID = s.id
	n.boundNICID = s.route.NICID()
	n.route = s.route.Clone()
	n.effectiveNetProtos = []tcpip.NetworkProtocolNumber{s.route.NetProto}
	n.rcvBufSize = int(l.rcvWnd)
	n.amss = mssForRoute(&n.route)
	n.maybeEnableTimestamp(rcvdSynOpts)
	n.maybeEnableSACKPermitted(rcvdSynOpts)
	n.initGSO()
	if err := n.stack.RegisterTransportEndpoint(n.boundNICID, n.effectiveNetProtos, ProtocolNumber, n.ID, n, n.reusePort, n.bindToDevice); err != nil {
		n.Close()
		return nil, err
	}
	n.isRegistered = true
	n.snd = newSender(n, iss, irs, s.window, rcvdSynOpts.MSS, rcvdSynOpts.WS)
	n.rcv = newReceiver(n, irs, seqnum.Size(n.initialReceiveWindow()), 0, seqnum.Size(n.receiveBufferSize()))
	n.rcvAutoParams.prevCopied = n.initialReceiveWindow()
	return n, nil
}
func (l *listenContext) createEndpointAndPerformHandshake(s *segment, opts *header.TCPSynOptions) (*endpoint, *tcpip.Error) {
	irs := s.sequenceNumber
	isn := generateSecureISN(s.id, l.stack.Seed())
	ep, err := l.createConnectingEndpoint(s, isn, irs, opts)
	if err != nil {
		return nil, err
	}
	if l.listenEP != nil {
		l.listenEP.mu.Lock()
		if l.listenEP.state != StateListen {
			l.listenEP.mu.Unlock()
			return nil, tcpip.ErrConnectionAborted
		}
		l.addPendingEndpoint(ep)
		l.listenEP.mu.Unlock()
	}
	h := newHandshake(ep, seqnum.Size(ep.initialReceiveWindow()))
	h.resetToSynRcvd(isn, irs, opts)
	if err := h.execute(); err != nil {
		ep.Close()
		if l.listenEP != nil {
			l.removePendingEndpoint(ep)
		}
		return nil, err
	}
	ep.mu.Lock()
	ep.stack.Stats().TCP.CurrentEstablished.Increment()
	ep.state = StateEstablished
	ep.isConnectNotified = true
	ep.mu.Unlock()
	ep.rcv.rcvWndScale = h.effectiveRcvWndScale()
	return ep, nil
}
func (l *listenContext) addPendingEndpoint(n *endpoint) {
	l.pendingMu.Lock()
	l.pendingEndpoints[n.ID] = n
	l.pending.Add(1)
	l.pendingMu.Unlock()
}
func (l *listenContext) removePendingEndpoint(n *endpoint) {
	l.pendingMu.Lock()
	delete(l.pendingEndpoints, n.ID)
	l.pending.Done()
	l.pendingMu.Unlock()
}
func (l *listenContext) closeAllPendingEndpoints() {
	l.pendingMu.Lock()
	for _, n := range l.pendingEndpoints {
		n.notifyProtocolGoroutine(notifyClose)
	}
	l.pendingMu.Unlock()
	l.pending.Wait()
}
func (e *endpoint) deliverAccepted(n *endpoint) {
	e.mu.Lock()
	state := e.state
	e.pendingAccepted.Add(1)
	defer e.pendingAccepted.Done()
	acceptedChan := e.acceptedChan
	e.mu.Unlock()
	if state == StateListen {
		acceptedChan <- n
		e.waiterQueue.Notify(waiter.EventIn)
	} else {
		n.Close()
	}
}