func (g *Gateway) managedAcceptConnPeer(conn net.Conn, remoteVersion string) error {
	g.log.Debugln("Sending sessionHeader with address", g.myAddr, g.myAddr.IsLocal())
	g.mu.RLock()
	ourHeader := sessionHeader{
		GenesisID:  types.GenesisID,
		UniqueID:   g.staticId,
		NetAddress: g.myAddr,
	}
	g.mu.RUnlock()
	remoteHeader, err := exchangeRemoteHeader(conn, ourHeader)
	if err != nil {
		return err
	}
	if err := exchangeOurHeader(conn, ourHeader); err != nil {
		return err
	}
	remoteIP := modules.NetAddress(conn.RemoteAddr().String()).Host()
	remotePort := remoteHeader.NetAddress.Port()
	remoteAddr := modules.NetAddress(net.JoinHostPort(remoteIP, remotePort))
	peer := &peer{
		Peer: modules.Peer{
			Inbound: true,
			Local: remoteAddr.IsLocal(),
			NetAddress: remoteAddr,
			Version:    remoteVersion,
		},
		sess: newServerStream(conn, remoteVersion),
	}
	g.mu.Lock()
	g.acceptPeer(peer)
	g.mu.Unlock()
	go func() {
		err := g.staticPingNode(remoteAddr)
		if err == nil {
			g.mu.Lock()
			g.addNode(remoteAddr)
			g.mu.Unlock()
		}
	}()
	return nil
}
managedAcceptConnPeer accepts connection requests from peers >= v1.3.1.
The requesting peer is added as a node and a peer. The peer is only added if
a nil error is returned.
package gateway
import (
	"errors"
	"fmt"
	"net"
	"time"
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/types"
	"github.com/NebulousLabs/fastrand"
)
var (
	errPeerExists       = errors.New("already connected to this peer")
	errPeerRejectedConn = errors.New("peer rejected connection")
)
type insufficientVersionError string
func (s insufficientVersionError) Error() string {
	return "unacceptable version: " + string(s)
}
type invalidVersionError string
func (s invalidVersionError) Error() string {
	return "invalid version: " + string(s)
}
type peer struct {
	modules.Peer
	sess streamSession
}
type sessionHeader struct {
	GenesisID  types.BlockID
	UniqueID   gatewayID
	NetAddress modules.NetAddress
}
func (p *peer) open() (modules.PeerConn, error) {
	conn, err := p.sess.Open()
	if err != nil {
		return nil, err
	}
	return &peerConn{conn, p.NetAddress}, nil
}
func (p *peer) accept() (modules.PeerConn, error) {
	conn, err := p.sess.Accept()
	if err != nil {
		return nil, err
	}
	return &peerConn{conn, p.NetAddress}, nil
}
func (g *Gateway) addPeer(p *peer) {
	g.peers[p.NetAddress] = p
	go g.threadedListenPeer(p)
}
func (g *Gateway) callInitRPCs(addr modules.NetAddress) {
	for name, fn := range g.initRPCs {
		go func(name string, fn modules.RPCFunc) {
			if g.threads.Add() != nil {
				return
			}
			defer g.threads.Done()
			err := g.managedRPC(addr, name, fn)
			if err != nil {
				g.log.Debugf("INFO: RPC %q on peer %q failed: %v", name, addr, err)
			}
		}(name, fn)
	}
}
func (g *Gateway) randomOutboundPeer() (modules.NetAddress, error) {
	var addrs []modules.NetAddress
	for addr, peer := range g.peers {
		if peer.Inbound {
			continue
		}
		addrs = append(addrs, addr)
	}
	if len(addrs) == 0 {
		return "", errNoPeers
	}
	return addrs[fastrand.Intn(len(addrs))], nil
}
func (g *Gateway) permanentListen(closeChan chan struct{}) {
	defer close(closeChan)
	for {
		conn, err := g.listener.Accept()
		if err != nil {
			g.log.Debugln("[PL] Closing permanentListen:", err)
			return
		}
		go g.threadedAcceptConn(conn)
		select {
		case <-time.After(acceptInterval):
		case <-g.threads.StopChan():
			return
		}
	}
}
func (g *Gateway) threadedAcceptConn(conn net.Conn) {
	if g.threads.Add() != nil {
		conn.Close()
		return
	}
	defer g.threads.Done()
	conn.SetDeadline(time.Now().Add(connStdDeadline))
	addr := modules.NetAddress(conn.RemoteAddr().String())
	g.log.Debugf("INFO: %v wants to connect", addr)
	remoteVersion, err := acceptVersionHandshake(conn, build.Version)
	if err != nil {
		g.log.Debugf("INFO: %v wanted to connect but version handshake failed: %v", addr, err)
		conn.Close()
		return
	}
	if build.VersionCmp(remoteVersion, minimumAcceptablePeerVersion) >= 0 {
		err = g.managedAcceptConnPeer(conn, remoteVersion)
	} else {
		err = errors.New("version number is below threshold")
	}
	if err != nil {
		g.log.Debugf("INFO: %v wanted to connect, but failed: %v", addr, err)
		conn.Close()
		return
	}
	conn.SetDeadline(time.Time{})
	g.log.Debugf("INFO: accepted connection from new peer %v (v%v)", addr, remoteVersion)
}
func acceptableSessionHeader(ourHeader, remoteHeader sessionHeader, remoteAddr string) error {
	if remoteHeader.GenesisID != ourHeader.GenesisID {
		return errPeerGenesisID
	} else if remoteHeader.UniqueID == ourHeader.UniqueID {
		return errOurAddress
	} else if err := remoteHeader.NetAddress.IsStdValid(); err != nil {
		return fmt.Errorf("invalid remote address: %v", err)
	}
	return nil
}