func (h *BasicHost) Network() network.Network {
	return h.network
}
Network returns the Network interface of the Host
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
}
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
}
func (h *BasicHost) updateLocalIpAddr() {
	h.addrMu.Lock()
	defer h.addrMu.Unlock()
	h.filteredInterfaceAddrs = nil
	h.allInterfaceAddrs = nil
	if r, err := netroute.New(); err != nil {
		log.Debugw("failed to build Router for kernel's routing table", "error", err)
	} else {
		if _, _, localIPv4, err := r.Route(net.IPv4zero); err != nil {
			log.Debugw("failed to fetch local IPv4 address", "error", err)
		} else if localIPv4.IsGlobalUnicast() {
			maddr, err := manet.FromIP(localIPv4)
			if err == nil {
				h.filteredInterfaceAddrs = append(h.filteredInterfaceAddrs, maddr)
			}
		}
		if _, _, localIPv6, err := r.Route(net.IPv6unspecified); err != nil {
			log.Debugw("failed to fetch local IPv6 address", "error", err)
		} else if localIPv6.IsGlobalUnicast() {
			maddr, err := manet.FromIP(localIPv6)
			if err == nil {
				h.filteredInterfaceAddrs = append(h.filteredInterfaceAddrs, maddr)
			}
		}
	}
	ifaceAddrs, err := manet.InterfaceMultiaddrs()
	if err != nil {
		log.Errorw("failed to resolve local interface addresses", "error", err)
		h.filteredInterfaceAddrs = append(h.filteredInterfaceAddrs, manet.IP4Loopback, manet.IP6Loopback)
		h.allInterfaceAddrs = h.filteredInterfaceAddrs
		return
	}
	for _, addr := range ifaceAddrs {
		if !manet.IsIP6LinkLocal(addr) {
			h.allInterfaceAddrs = append(h.allInterfaceAddrs, addr)
		}
	}
	if len(h.filteredInterfaceAddrs) == 0 {
		h.filteredInterfaceAddrs = h.allInterfaceAddrs
	} else {
		for _, addr := range h.allInterfaceAddrs {
			if manet.IsIPLoopback(addr) {
				h.filteredInterfaceAddrs = append(h.filteredInterfaceAddrs, addr)
			}
		}
	}
}
func (h *BasicHost) Start() {
	h.refCount.Add(1)
	go h.background()
}
func (h *BasicHost) newStreamHandler(s network.Stream) {
	before := time.Now()
	if h.negtimeout > 0 {
		if err := s.SetDeadline(time.Now().Add(h.negtimeout)); err != nil {
			log.Debug("setting stream deadline: ", err)
			s.Reset()
			return
		}
	}
	lzc, protoID, handle, err := h.Mux().NegotiateLazy(s)
	took := time.Since(before)
	if err != nil {
		if err == io.EOF {
			logf := log.Debugf
			if took > time.Second*10 {
				logf = log.Warningf
			}
			logf("protocol EOF: %s (took %s)", s.Conn().RemotePeer(), took)
		} else {
			log.Debugf("protocol mux failed: %s (took %s)", err, took)
		}
		s.Reset()
		return
	}
	s = &streamWrapper{
		Stream: s,
		rw:     lzc,
	}
	if h.negtimeout > 0 {
		if err := s.SetDeadline(time.Time{}); err != nil {
			log.Debugf("resetting stream deadline: ", err)
			s.Reset()
			return
		}
	}
	s.SetProtocol(protocol.ID(protoID))
	log.Debugf("protocol negotiation took %s", took)
	go handle(protoID, s)
}
func (h *BasicHost) SignalAddressChange() {
	select {
	case h.addrChangeChan <- struct{}{}:
	default:
	}
}
func makeUpdatedAddrEvent(prev, current []ma.Multiaddr) *event.EvtLocalAddressesUpdated {
	prevmap := make(map[string]ma.Multiaddr, len(prev))
	evt := event.EvtLocalAddressesUpdated{Diffs: true}
	addrsAdded := false
	for _, addr := range prev {
		prevmap[string(addr.Bytes())] = addr
	}
	for _, addr := range current {
		_, ok := prevmap[string(addr.Bytes())]
		updated := event.UpdatedAddress{Address: addr}
		if ok {
			updated.Action = event.Maintained
		} else {
			updated.Action = event.Added
			addrsAdded = true
		}
		evt.Current = append(evt.Current, updated)
		delete(prevmap, string(addr.Bytes()))
	}
	for _, addr := range prevmap {
		updated := event.UpdatedAddress{Action: event.Removed, Address: addr}
		evt.Removed = append(evt.Removed, updated)
	}
	if !addrsAdded && len(evt.Removed) == 0 {
		return nil
	}
	return &evt
}
func (h *BasicHost) makeSignedPeerRecord(evt *event.EvtLocalAddressesUpdated) (*record.Envelope, error) {
	current := make([]multiaddr.Multiaddr, 0, len(evt.Current))
	for _, a := range evt.Current {
		current = append(current, a.Address)
	}
	rec := peer.PeerRecordFromAddrInfo(peer.AddrInfo{h.ID(), current})
	return record.Seal(rec, h.signKey)
}
func (h *BasicHost) background() {
	defer h.refCount.Done()
	var lastAddrs []ma.Multiaddr
	emitAddrChange := func(currentAddrs []ma.Multiaddr, lastAddrs []ma.Multiaddr) {
		if currentAddrs == nil && lastAddrs == nil {
			return
		}
		changeEvt := makeUpdatedAddrEvent(lastAddrs, currentAddrs)
		if changeEvt == nil {
			return
		}
		if !h.disableSignedPeerRecord {
			sr, err := h.makeSignedPeerRecord(changeEvt)
			if err != nil {
				log.Errorf("error creating a signed peer record from the set of current addresses, err=%s", err)
				return
			}
			changeEvt.SignedPeerRecord = sr
			if _, err := h.caBook.ConsumePeerRecord(sr, peerstore.PermanentAddrTTL); err != nil {
				log.Errorf("failed to persist signed peer record in peer store, err=%s", err)
				return
			}
		}
		if err := h.emitters.evtLocalAddrsUpdated.Emit(*changeEvt); err != nil {
			log.Warnf("error emitting event for updated addrs: %s", err)
		}
	}
	ticker := time.NewTicker(addrChangeTickrInterval)
	defer ticker.Stop()
	for {
		h.updateLocalIpAddr()
		curr := h.Addrs()
		emitAddrChange(curr, lastAddrs)
		lastAddrs = curr
		select {
		case <-ticker.C:
		case <-h.addrChangeChan:
		case <-h.ctx.Done():
			return
		}
	}
}
func (h *BasicHost) ID() peer.ID {
	return h.Network().LocalPeer()
}
func (h *BasicHost) Peerstore() peerstore.Peerstore {
	return h.Network().Peerstore()
}