func (node *Node) goPublic() error {
	if len(node.dir) == 0 {
		return NoDirectory
	}
	node.mx.Lock()
	defer node.mx.Unlock()
	switch node.status {
	case StatusOffline:
		err := node._goOnline()
		if err != nil {
			return err
		}
		time.Sleep(5 * time.Second)
		fallthrough
	case StatusOnline:
		for _, dir := range node.dir {
			go node.registerPeer(node.netCtx, dir)
		}
		go node.registerPeerDHT(node.netCtx)
		node.status = StatusPublic
		log.Println("Node is public")
		return nil
	default:
		return nil
	}
}
goPublic starts the network if it's not already up and registers with the
directory; fails with NoDirectory if that hasn't been configured.
package main
import (
	"context"
	"encoding/json"
	ggio "github.com/gogo/protobuf/io"
	p2p_net "github.com/libp2p/go-libp2p-net"
	p2p_peer "github.com/libp2p/go-libp2p-peer"
	p2p_pstore "github.com/libp2p/go-libp2p-peerstore"
	p2p_proto "github.com/libp2p/go-libp2p-protocol"
	p2p_ping "github.com/libp2p/go-libp2p/p2p/protocol/ping"
	mc "github.com/mediachain/concat/mc"
	mcq "github.com/mediachain/concat/mc/query"
	pb "github.com/mediachain/concat/proto"
	multiaddr "github.com/multiformats/go-multiaddr"
	"log"
	"time"
)
func (node *Node) goOffline() error {
	node.mx.Lock()
	defer node.mx.Unlock()
	switch node.status {
	case StatusPublic:
		fallthrough
	case StatusOnline:
		node.netCancel()
		err := node.dht.Close()
		if err != nil {
			log.Printf("Error closing DHT: %s", err.Error())
		}
		node.dht = nil
		err = node.host.Close()
		if err != nil {
			log.Printf("Error closing host: %s", err.Error())
		}
		node.host = nil
		node.ping = nil
		node.status = StatusOffline
		node.natCfg.Clear()
		log.Println("Node is offline")
		return err
	default:
		return nil
	}
}
func (node *Node) goOnline() error {
	node.mx.Lock()
	defer node.mx.Unlock()
	switch node.status {
	case StatusOffline:
		err := node._goOnline()
		if err != nil {
			return err
		}
		node.status = StatusOnline
		log.Println("Node is online")
		return nil
	default:
		return nil
	}
}
func (node *Node) _goOnline() error {
	var opts []interface{}
	if node.natCfg.Opt == mc.NATConfigAuto {
		opts = []interface{}{mc.NATPortMap}
	}
	ctx, cancel := context.WithCancel(context.Background())
	host, err := mc.NewHost(ctx, node.PeerIdentity, node.laddr, opts...)
	if err != nil {
		cancel()
		return err
	}
	host.SetStreamHandler("/mediachain/node/id", node.idHandler)
	host.SetStreamHandler("/mediachain/node/manifest", node.manifestHandler)
	host.SetStreamHandler("/mediachain/node/ping", node.pingHandler)
	host.SetStreamHandler("/mediachain/node/query", node.queryHandler)
	host.SetStreamHandler("/mediachain/node/data", node.dataHandler)
	host.SetStreamHandler("/mediachain/node/push", node.pushHandler)
	ping := p2p_ping.NewPingService(host)
	dht := NewDHT(ctx, host)
	err = dht.Bootstrap()
	if err != nil {
		log.Printf("Error boostrapping DHT: %s", err.Error())
	}
	node.host = host
	node.netCtx = ctx
	node.netCancel = cancel
	node.ping = ping
	node.dht = dht
	return nil
}