func NewHost(ctx context.Context, n network.Network, opts *HostOpts) (*BasicHost, error) {
	hostCtx, cancel := context.WithCancel(ctx)
	h := &BasicHost{
		network:                 n,
		mux:                     msmux.NewMultistreamMuxer(),
		negtimeout:              DefaultNegotiationTimeout,
		AddrsFactory:            DefaultAddrsFactory,
		maResolver:              madns.DefaultResolver,
		eventbus:                eventbus.NewBus(),
		addrChangeChan:          make(chan struct{}, 1),
		ctx:                     hostCtx,
		ctxCancel:               cancel,
		disableSignedPeerRecord: opts.DisableSignedPeerRecord,
		idFirst:                 opts.IDFirst,
	}
	h.updateLocalIpAddr()
	var err error
	if h.emitters.evtLocalProtocolsUpdated, err = h.eventbus.Emitter(&event.EvtLocalProtocolsUpdated{}); err != nil {
		return nil, err
	}
	if h.emitters.evtLocalAddrsUpdated, err = h.eventbus.Emitter(&event.EvtLocalAddressesUpdated{}); err != nil {
		return nil, err
	}
	if !h.disableSignedPeerRecord {
		cab, ok := peerstore.GetCertifiedAddrBook(n.Peerstore())
		if !ok {
			return nil, errors.New("peerstore should also be a certified address book")
		}
		h.caBook = cab
		h.signKey = h.Peerstore().PrivKey(h.ID())
		if h.signKey == nil {
			return nil, errors.New("unable to access host key")
		}
		rec := peer.PeerRecordFromAddrInfo(peer.AddrInfo{h.ID(), h.Addrs()})
		ev, err := record.Seal(rec, h.signKey)
		if err != nil {
			return nil, fmt.Errorf("failed to create signed record for self: %w", err)
		}
		if _, err := cab.ConsumePeerRecord(ev, peerstore.PermanentAddrTTL); err != nil {
			return nil, fmt.Errorf("failed to persist signed record to peerstore: %w", err)
		}
	}
	if opts.MultistreamMuxer != nil {
		h.mux = opts.MultistreamMuxer
	}
	if opts.EnableIdentify {
		if h.disableSignedPeerRecord {
			h.ids = identify.NewIDService(h, identify.UserAgent(opts.UserAgent), identify.DisableSignedPeerRecord())
		} else {
			h.ids = identify.NewIDService(h, identify.UserAgent(opts.UserAgent))
		}
	}
	if uint64(opts.NegotiationTimeout) != 0 {
		h.negtimeout = opts.NegotiationTimeout
	}
	if opts.AddrsFactory != nil {
		h.AddrsFactory = opts.AddrsFactory
	}
	if opts.NATManager != nil {
		h.natmgr = opts.NATManager(n)
	}
	if opts.MultiaddrResolver != nil {
		h.maResolver = opts.MultiaddrResolver
	}
	if opts.ConnManager == nil {
		h.cmgr = &connmgr.NullConnMgr{}
	} else {
		h.cmgr = opts.ConnManager
		n.Notify(h.cmgr.Notifee())
	}
	if opts.EnablePing {
		h.pings = ping.NewPingService(h)
	}
	n.SetStreamHandler(h.newStreamHandler)
	listenHandler := func(network.Network, ma.Multiaddr) {
		h.SignalAddressChange()
	}
	n.Notify(&network.NotifyBundle{
		ListenF:      listenHandler,
		ListenCloseF: listenHandler,
	})
	return h, nil
}
NewHost constructs a new *BasicHost and activates it by attaching its stream and connection handlers to the given inet.Network.
package custom
import (
	"context"
	"errors"
	"fmt"
	basichost "github.com/libp2p/go-libp2p/p2p/host/basic"
	"io"
	"net"
	"sync"
	"time"
	autonat "github.com/libp2p/go-libp2p-autonat"
	"github.com/libp2p/go-libp2p-core/connmgr"
	"github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/event"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"
	"github.com/libp2p/go-libp2p-core/protocol"
	"github.com/libp2p/go-libp2p-core/record"
	addrutil "github.com/libp2p/go-addr-util"
	"github.com/libp2p/go-eventbus"
	inat "github.com/libp2p/go-libp2p-nat"
	"github.com/libp2p/go-libp2p/p2p/protocol/identify"
	"github.com/libp2p/go-libp2p/p2p/protocol/ping"
	"github.com/libp2p/go-netroute"
	logging "github.com/ipfs/go-log"
	"github.com/multiformats/go-multiaddr"
	ma "github.com/multiformats/go-multiaddr"
	madns "github.com/multiformats/go-multiaddr-dns"
	manet "github.com/multiformats/go-multiaddr-net"
	msmux "github.com/multiformats/go-multistream"
)
const maxAddressResolution = 32
var addrChangeTickrInterval = 5 * time.Second
var log = logging.Logger("basichost")
var (
	DefaultNegotiationTimeout = time.Second * 60
	DefaultAddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr { return addrs }
)
type AddrsFactory func([]ma.Multiaddr) []ma.Multiaddr
type BasicHost struct {
	ctx       context.Context
	ctxCancel context.CancelFunc
	closeSync sync.Once
	refCount sync.WaitGroup
	idFirst bool
	network    network.Network
	mux        *msmux.MultistreamMuxer
	ids        *identify.IDService
	pings      *ping.PingService
	natmgr     basichost.NATManager
	maResolver *madns.Resolver
	cmgr       connmgr.ConnManager
	eventbus   event.Bus
	AddrsFactory AddrsFactory
	negtimeout time.Duration
	emitters struct {
		evtLocalProtocolsUpdated event.Emitter
		evtLocalAddrsUpdated     event.Emitter
	}
	addrChangeChan chan struct{}
	addrMu                 sync.RWMutex
	filteredInterfaceAddrs []ma.Multiaddr
	allInterfaceAddrs      []ma.Multiaddr
	disableSignedPeerRecord bool
	signKey                 crypto.PrivKey
	caBook                  peerstore.CertifiedAddrBook
	AutoNat autonat.AutoNAT
}
var _ host.Host = (*BasicHost)(nil)
type HostOpts struct {
	MultistreamMuxer *msmux.MultistreamMuxer
	NegotiationTimeout time.Duration
	AddrsFactory AddrsFactory
	MultiaddrResolver *madns.Resolver
	NATManager func(network.Network) basichost.NATManager
	ConnManager connmgr.ConnManager
	EnablePing bool
	UserAgent string
	DisableSignedPeerRecord bool
	EnableIdentify bool
	IDFirst bool
}