code: func (srv *Server) NodeInfo() *NodeInfo {
  	// Gather and assemble the generic node infos
  	node := srv.Self()
  	info := &NodeInfo{
  		Name:       srv.Name,
  		Enode:      node.String(),
  		ID:         node.ID().String(),
  		IP:         node.IP().String(),
  		ListenAddr: srv.ListenAddr,
  		Protocols:  make(map[string]interface{}),
  	}
  	info.Ports.Discovery = node.UDP()
  	info.Ports.Listener = node.TCP()
  	if enc, err := rlp.EncodeToBytes(node.Record()); err == nil {
  		info.ENR = "0x" + hex.EncodeToString(enc)
  	}
  
  	// Gather all the running protocol infos (only once per protocol type)
  	for _, proto := range srv.Protocols {
  		if _, ok := info.Protocols[proto.Name]; !ok {
  			nodeInfo := interface{}("unknown")
  			if query := proto.NodeInfo; query != nil {
  				nodeInfo = proto.NodeInfo()
  			}
  			info.Protocols[proto.Name] = nodeInfo
  		}
  	}
  	return info
  }
docs: // NodeInfo gathers and returns a collection of metadata known about the host.