eth, p2p, rpc/api: polish protocol info gathering
This commit is contained in:
		@@ -472,62 +472,10 @@ func New(config *Config) (*Ethereum, error) {
 | 
			
		||||
	return eth, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NodeInfo struct {
 | 
			
		||||
	Name       string
 | 
			
		||||
	NodeUrl    string
 | 
			
		||||
	NodeID     string
 | 
			
		||||
	IP         string
 | 
			
		||||
	DiscPort   int // UDP listening port for discovery protocol
 | 
			
		||||
	TCPPort    int // TCP listening port for RLPx
 | 
			
		||||
	Td         string
 | 
			
		||||
	ListenAddr string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Ethereum) NodeInfo() *NodeInfo {
 | 
			
		||||
	node := s.net.Self()
 | 
			
		||||
 | 
			
		||||
	return &NodeInfo{
 | 
			
		||||
		Name:       s.Name(),
 | 
			
		||||
		NodeUrl:    node.String(),
 | 
			
		||||
		NodeID:     node.ID.String(),
 | 
			
		||||
		IP:         node.IP.String(),
 | 
			
		||||
		DiscPort:   int(node.UDP),
 | 
			
		||||
		TCPPort:    int(node.TCP),
 | 
			
		||||
		ListenAddr: s.net.ListenAddr,
 | 
			
		||||
		Td:         s.BlockChain().GetTd(s.BlockChain().CurrentBlock().Hash()).String(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PeerInfo struct {
 | 
			
		||||
	ID            string
 | 
			
		||||
	Name          string
 | 
			
		||||
	Caps          string
 | 
			
		||||
	RemoteAddress string
 | 
			
		||||
	LocalAddress  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newPeerInfo(peer *p2p.Peer) *PeerInfo {
 | 
			
		||||
	var caps []string
 | 
			
		||||
	for _, cap := range peer.Caps() {
 | 
			
		||||
		caps = append(caps, cap.String())
 | 
			
		||||
	}
 | 
			
		||||
	return &PeerInfo{
 | 
			
		||||
		ID:            peer.ID().String(),
 | 
			
		||||
		Name:          peer.Name(),
 | 
			
		||||
		Caps:          strings.Join(caps, ", "),
 | 
			
		||||
		RemoteAddress: peer.RemoteAddr().String(),
 | 
			
		||||
		LocalAddress:  peer.LocalAddr().String(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PeersInfo returns an array of PeerInfo objects describing connected peers
 | 
			
		||||
func (s *Ethereum) PeersInfo() (peersinfo []*PeerInfo) {
 | 
			
		||||
	for _, peer := range s.net.Peers() {
 | 
			
		||||
		if peer != nil {
 | 
			
		||||
			peersinfo = append(peersinfo, newPeerInfo(peer))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
// Network retrieves the underlying P2P network server. This should eventually
 | 
			
		||||
// be moved out into a protocol independent package, but for now use an accessor.
 | 
			
		||||
func (s *Ethereum) Network() *p2p.Server {
 | 
			
		||||
	return s.net
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ import (
 | 
			
		||||
	"github.com/ethereum/go-ethereum/logger"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/logger/glog"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/p2p"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/p2p/discover"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/pow"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rlp"
 | 
			
		||||
)
 | 
			
		||||
@@ -55,6 +56,8 @@ type hashFetcherFn func(common.Hash) error
 | 
			
		||||
type blockFetcherFn func([]common.Hash) error
 | 
			
		||||
 | 
			
		||||
type ProtocolManager struct {
 | 
			
		||||
	networkId int
 | 
			
		||||
 | 
			
		||||
	fastSync   bool
 | 
			
		||||
	txpool     txPool
 | 
			
		||||
	blockchain *core.BlockChain
 | 
			
		||||
@@ -91,6 +94,7 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
 | 
			
		||||
	}
 | 
			
		||||
	// Create the protocol manager with the base fields
 | 
			
		||||
	manager := &ProtocolManager{
 | 
			
		||||
		networkId:  networkId,
 | 
			
		||||
		fastSync:   fastSync,
 | 
			
		||||
		eventMux:   mux,
 | 
			
		||||
		txpool:     txpool,
 | 
			
		||||
@@ -111,14 +115,23 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
 | 
			
		||||
		// Compatible; initialise the sub-protocol
 | 
			
		||||
		version := version // Closure for the run
 | 
			
		||||
		manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
 | 
			
		||||
			Name:    "eth",
 | 
			
		||||
			Name:    ProtocolName,
 | 
			
		||||
			Version: version,
 | 
			
		||||
			Length:  ProtocolLengths[i],
 | 
			
		||||
			Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
 | 
			
		||||
				peer := manager.newPeer(int(version), networkId, p, rw)
 | 
			
		||||
				peer := manager.newPeer(int(version), p, rw)
 | 
			
		||||
				manager.newPeerCh <- peer
 | 
			
		||||
				return manager.handle(peer)
 | 
			
		||||
			},
 | 
			
		||||
			NodeInfo: func() interface{} {
 | 
			
		||||
				return manager.NodeInfo()
 | 
			
		||||
			},
 | 
			
		||||
			PeerInfo: func(id discover.NodeID) interface{} {
 | 
			
		||||
				if p := manager.peers.Peer(fmt.Sprintf("%x", id[:8])); p != nil {
 | 
			
		||||
					return p.Info()
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			},
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	if len(manager.SubProtocols) == 0 {
 | 
			
		||||
@@ -188,8 +201,8 @@ func (pm *ProtocolManager) Stop() {
 | 
			
		||||
	glog.V(logger.Info).Infoln("Ethereum protocol handler stopped")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
 | 
			
		||||
	return newPeer(pv, nv, p, newMeteredMsgWriter(rw))
 | 
			
		||||
func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
 | 
			
		||||
	return newPeer(pv, p, newMeteredMsgWriter(rw))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// handle is the callback invoked to manage the life cycle of an eth peer. When
 | 
			
		||||
@@ -199,7 +212,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
 | 
			
		||||
 | 
			
		||||
	// Execute the Ethereum handshake
 | 
			
		||||
	td, head, genesis := pm.blockchain.Status()
 | 
			
		||||
	if err := p.Handshake(td, head, genesis); err != nil {
 | 
			
		||||
	if err := p.Handshake(pm.networkId, td, head, genesis); err != nil {
 | 
			
		||||
		glog.V(logger.Debug).Infof("%v: handshake failed: %v", p, err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -730,3 +743,22 @@ func (self *ProtocolManager) txBroadcastLoop() {
 | 
			
		||||
		self.BroadcastTx(event.Tx.Hash(), event.Tx)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EthNodeInfo represents a short summary of the Ethereum sub-protocol metadata known
 | 
			
		||||
// about the host peer.
 | 
			
		||||
type EthNodeInfo struct {
 | 
			
		||||
	Network    int      `json:"network"`    // Ethereum network ID (0=Olympic, 1=Frontier, 2=Morden)
 | 
			
		||||
	Difficulty *big.Int `json:"difficulty"` // Total difficulty of the host's blockchain
 | 
			
		||||
	Genesis    string   `json:"genesis"`    // SHA3 hash of the host's genesis block
 | 
			
		||||
	Head       string   `json:"head"`       // SHA3 hash of the host's best owned block
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NodeInfo retrieves some protocol metadata about the running host node.
 | 
			
		||||
func (self *ProtocolManager) NodeInfo() *EthNodeInfo {
 | 
			
		||||
	return &EthNodeInfo{
 | 
			
		||||
		Network:    self.networkId,
 | 
			
		||||
		Difficulty: self.blockchain.GetTd(self.blockchain.CurrentBlock().Hash()),
 | 
			
		||||
		Genesis:    fmt.Sprintf("%x", self.blockchain.Genesis().Hash()),
 | 
			
		||||
		Head:       fmt.Sprintf("%x", self.blockchain.CurrentBlock().Hash()),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -117,7 +117,7 @@ func newTestPeer(name string, version int, pm *ProtocolManager, shake bool) (*te
 | 
			
		||||
	var id discover.NodeID
 | 
			
		||||
	rand.Read(id[:])
 | 
			
		||||
 | 
			
		||||
	peer := pm.newPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net)
 | 
			
		||||
	peer := pm.newPeer(version, p2p.NewPeer(id, name, nil), net)
 | 
			
		||||
 | 
			
		||||
	// Start the peer on a new thread
 | 
			
		||||
	errc := make(chan error, 1)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								eth/peer.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								eth/peer.go
									
									
									
									
									
								
							@@ -44,16 +44,21 @@ const (
 | 
			
		||||
	handshakeTimeout = 5 * time.Second
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type peer struct {
 | 
			
		||||
	*p2p.Peer
 | 
			
		||||
// PeerInfo represents a short summary of the Ethereum sub-protocol metadata known
 | 
			
		||||
// about a connected peer.
 | 
			
		||||
type PeerInfo struct {
 | 
			
		||||
	Version    int      `json:"version"`    // Ethereum protocol version negotiated
 | 
			
		||||
	Difficulty *big.Int `json:"difficulty"` // Total difficulty of the peer's blockchain
 | 
			
		||||
	Head       string   `json:"head"`       // SHA3 hash of the peer's best owned block
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type peer struct {
 | 
			
		||||
	id string
 | 
			
		||||
 | 
			
		||||
	*p2p.Peer
 | 
			
		||||
	rw p2p.MsgReadWriter
 | 
			
		||||
 | 
			
		||||
	version int // Protocol version negotiated
 | 
			
		||||
	network int // Network ID being on
 | 
			
		||||
 | 
			
		||||
	id string
 | 
			
		||||
 | 
			
		||||
	head    common.Hash
 | 
			
		||||
	td      *big.Int
 | 
			
		||||
	lock    sync.RWMutex
 | 
			
		||||
@@ -62,20 +67,28 @@ type peer struct {
 | 
			
		||||
	knownBlocks *set.Set // Set of block hashes known to be known by this peer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newPeer(version, network int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
 | 
			
		||||
func newPeer(version int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
 | 
			
		||||
	id := p.ID()
 | 
			
		||||
 | 
			
		||||
	return &peer{
 | 
			
		||||
		Peer:        p,
 | 
			
		||||
		rw:          rw,
 | 
			
		||||
		version:     version,
 | 
			
		||||
		network:     network,
 | 
			
		||||
		id:          fmt.Sprintf("%x", id[:8]),
 | 
			
		||||
		knownTxs:    set.New(),
 | 
			
		||||
		knownBlocks: set.New(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Info gathers and returns a collection of metadata known about a peer.
 | 
			
		||||
func (p *peer) Info() *PeerInfo {
 | 
			
		||||
	return &PeerInfo{
 | 
			
		||||
		Version:    p.version,
 | 
			
		||||
		Difficulty: p.Td(),
 | 
			
		||||
		Head:       fmt.Sprintf("%x", p.Head()),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Head retrieves a copy of the current head (most recent) hash of the peer.
 | 
			
		||||
func (p *peer) Head() (hash common.Hash) {
 | 
			
		||||
	p.lock.RLock()
 | 
			
		||||
@@ -268,20 +281,22 @@ func (p *peer) RequestReceipts(hashes []common.Hash) error {
 | 
			
		||||
 | 
			
		||||
// Handshake executes the eth protocol handshake, negotiating version number,
 | 
			
		||||
// network IDs, difficulties, head and genesis blocks.
 | 
			
		||||
func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash) error {
 | 
			
		||||
func (p *peer) Handshake(network int, td *big.Int, head common.Hash, genesis common.Hash) error {
 | 
			
		||||
	// Send out own handshake in a new thread
 | 
			
		||||
	errc := make(chan error, 2)
 | 
			
		||||
	var status statusData // safe to read after two values have been received from errc
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		errc <- p2p.Send(p.rw, StatusMsg, &statusData{
 | 
			
		||||
			ProtocolVersion: uint32(p.version),
 | 
			
		||||
			NetworkId:       uint32(p.network),
 | 
			
		||||
			NetworkId:       uint32(network),
 | 
			
		||||
			TD:              td,
 | 
			
		||||
			CurrentBlock:    head,
 | 
			
		||||
			GenesisBlock:    genesis,
 | 
			
		||||
		})
 | 
			
		||||
	}()
 | 
			
		||||
	go func() {
 | 
			
		||||
		errc <- p.readStatus(&status, genesis)
 | 
			
		||||
		errc <- p.readStatus(network, &status, genesis)
 | 
			
		||||
	}()
 | 
			
		||||
	timeout := time.NewTimer(handshakeTimeout)
 | 
			
		||||
	defer timeout.Stop()
 | 
			
		||||
@@ -299,7 +314,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash) err
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *peer) readStatus(status *statusData, genesis common.Hash) (err error) {
 | 
			
		||||
func (p *peer) readStatus(network int, status *statusData, genesis common.Hash) (err error) {
 | 
			
		||||
	msg, err := p.rw.ReadMsg()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -317,8 +332,8 @@ func (p *peer) readStatus(status *statusData, genesis common.Hash) (err error) {
 | 
			
		||||
	if status.GenesisBlock != genesis {
 | 
			
		||||
		return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock, genesis)
 | 
			
		||||
	}
 | 
			
		||||
	if int(status.NetworkId) != p.network {
 | 
			
		||||
		return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, p.network)
 | 
			
		||||
	if int(status.NetworkId) != network {
 | 
			
		||||
		return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, network)
 | 
			
		||||
	}
 | 
			
		||||
	if int(status.ProtocolVersion) != p.version {
 | 
			
		||||
		return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version)
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,9 @@ const (
 | 
			
		||||
	eth63 = 63
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Official short name of the protocol used during capability negotiation.
 | 
			
		||||
var ProtocolName = "eth"
 | 
			
		||||
 | 
			
		||||
// Supported versions of the eth protocol (first is primary).
 | 
			
		||||
var ProtocolVersions = []uint{eth63, eth62, eth61}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,8 @@ func TestFastSyncDisabling(t *testing.T) {
 | 
			
		||||
	// Sync up the two peers
 | 
			
		||||
	io1, io2 := p2p.MsgPipe()
 | 
			
		||||
 | 
			
		||||
	go pmFull.handle(pmFull.newPeer(63, NetworkId, p2p.NewPeer(discover.NodeID{}, "empty", nil), io2))
 | 
			
		||||
	go pmEmpty.handle(pmEmpty.newPeer(63, NetworkId, p2p.NewPeer(discover.NodeID{}, "full", nil), io1))
 | 
			
		||||
	go pmFull.handle(pmFull.newPeer(63, p2p.NewPeer(discover.NodeID{}, "empty", nil), io2))
 | 
			
		||||
	go pmEmpty.handle(pmEmpty.newPeer(63, p2p.NewPeer(discover.NodeID{}, "full", nil), io1))
 | 
			
		||||
 | 
			
		||||
	time.Sleep(250 * time.Millisecond)
 | 
			
		||||
	pmEmpty.synchronise(pmEmpty.peers.BestPeer())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								p2p/peer.go
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								p2p/peer.go
									
									
									
									
									
								
							@@ -359,3 +359,49 @@ func (rw *protoRW) ReadMsg() (Msg, error) {
 | 
			
		||||
		return Msg{}, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PeerInfo represents a short summary of the information known about a connected
 | 
			
		||||
// peer. Sub-protocol independent fields are contained and initialized here, with
 | 
			
		||||
// protocol specifics delegated to all connected sub-protocols.
 | 
			
		||||
type PeerInfo struct {
 | 
			
		||||
	ID      string   `json:"id"`   // Unique node identifier (also the encryption key)
 | 
			
		||||
	Name    string   `json:"name"` // Name of the node, including client type, version, OS, custom data
 | 
			
		||||
	Caps    []string `json:"caps"` // Sum-protocols advertised by this particular peer
 | 
			
		||||
	Network struct {
 | 
			
		||||
		LocalAddress  string `json:"localAddress"`  // Local endpoint of the TCP data connection
 | 
			
		||||
		RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection
 | 
			
		||||
	} `json:"network"`
 | 
			
		||||
	Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Info gathers and returns a collection of metadata known about a peer.
 | 
			
		||||
func (p *Peer) Info() *PeerInfo {
 | 
			
		||||
	// Gather the protocol capabilities
 | 
			
		||||
	var caps []string
 | 
			
		||||
	for _, cap := range p.Caps() {
 | 
			
		||||
		caps = append(caps, cap.String())
 | 
			
		||||
	}
 | 
			
		||||
	// Assemble the generic peer metadata
 | 
			
		||||
	info := &PeerInfo{
 | 
			
		||||
		ID:        p.ID().String(),
 | 
			
		||||
		Name:      p.Name(),
 | 
			
		||||
		Caps:      caps,
 | 
			
		||||
		Protocols: make(map[string]interface{}),
 | 
			
		||||
	}
 | 
			
		||||
	info.Network.LocalAddress = p.LocalAddr().String()
 | 
			
		||||
	info.Network.RemoteAddress = p.RemoteAddr().String()
 | 
			
		||||
 | 
			
		||||
	// Gather all the running protocol infos
 | 
			
		||||
	for _, proto := range p.running {
 | 
			
		||||
		protoInfo := interface{}("unknown")
 | 
			
		||||
		if query := proto.Protocol.PeerInfo; query != nil {
 | 
			
		||||
			if metadata := query(p.ID()); metadata != nil {
 | 
			
		||||
				protoInfo = metadata
 | 
			
		||||
			} else {
 | 
			
		||||
				protoInfo = "handshake"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		info.Protocols[proto.Name] = protoInfo
 | 
			
		||||
	}
 | 
			
		||||
	return info
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,11 @@
 | 
			
		||||
 | 
			
		||||
package p2p
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/ethereum/go-ethereum/p2p/discover"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Protocol represents a P2P subprotocol implementation.
 | 
			
		||||
type Protocol struct {
 | 
			
		||||
@@ -39,6 +43,15 @@ type Protocol struct {
 | 
			
		||||
	// any protocol-level error (such as an I/O error) that is
 | 
			
		||||
	// encountered.
 | 
			
		||||
	Run func(peer *Peer, rw MsgReadWriter) error
 | 
			
		||||
 | 
			
		||||
	// NodeInfo is an optional helper method to retrieve protocol specific metadata
 | 
			
		||||
	// about the host node.
 | 
			
		||||
	NodeInfo func() interface{}
 | 
			
		||||
 | 
			
		||||
	// PeerInfo is an optional helper method to retrieve protocol specific metadata
 | 
			
		||||
	// about a certain peer in the network. If an info retrieval function is set,
 | 
			
		||||
	// but returns nil, it is assumed that the protocol handshake is still running.
 | 
			
		||||
	PeerInfo func(id discover.NodeID) interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p Protocol) cap() Cap {
 | 
			
		||||
 
 | 
			
		||||
@@ -689,3 +689,66 @@ func (srv *Server) runPeer(p *Peer) {
 | 
			
		||||
		NumConnections: srv.PeerCount(),
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NodeInfo represents a short summary of the information known about the host.
 | 
			
		||||
type NodeInfo struct {
 | 
			
		||||
	ID    string `json:"id"`    // Unique node identifier (also the encryption key)
 | 
			
		||||
	Name  string `json:"name"`  // Name of the node, including client type, version, OS, custom data
 | 
			
		||||
	Enode string `json:"enode"` // Enode URL for adding this peer from remote peers
 | 
			
		||||
	IP    string `json:"ip"`    // IP address of the node
 | 
			
		||||
	Ports struct {
 | 
			
		||||
		Discovery int `json:"discovery"` // UDP listening port for discovery protocol
 | 
			
		||||
		Listener  int `json:"listener"`  // TCP listening port for RLPx
 | 
			
		||||
	} `json:"ports"`
 | 
			
		||||
	ListenAddr string                 `json:"listenAddr"`
 | 
			
		||||
	Protocols  map[string]interface{} `json:"protocols"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Info gathers and returns a collection of metadata known about the host.
 | 
			
		||||
func (srv *Server) NodeInfo() *NodeInfo {
 | 
			
		||||
	node := srv.Self()
 | 
			
		||||
 | 
			
		||||
	// Gather and assemble the generic node infos
 | 
			
		||||
	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 = int(node.UDP)
 | 
			
		||||
	info.Ports.Listener = int(node.TCP)
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PeersInfo returns an array of metadata objects describing connected peers.
 | 
			
		||||
func (srv *Server) PeersInfo() []*PeerInfo {
 | 
			
		||||
	// Gather all the generic and sub-protocol specific infos
 | 
			
		||||
	infos := make([]*PeerInfo, 0, srv.PeerCount())
 | 
			
		||||
	for _, peer := range srv.Peers() {
 | 
			
		||||
		if peer != nil {
 | 
			
		||||
			infos = append(infos, peer.Info())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Sort the result array alphabetically by node identifier
 | 
			
		||||
	for i := 0; i < len(infos); i++ {
 | 
			
		||||
		for j := i + 1; j < len(infos); j++ {
 | 
			
		||||
			if infos[i].ID > infos[j].ID {
 | 
			
		||||
				infos[i], infos[j] = infos[j], infos[i]
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return infos
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ import (
 | 
			
		||||
	"github.com/ethereum/go-ethereum/crypto"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/eth"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/logger/glog"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/p2p"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rlp"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/codec"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/rpc/comms"
 | 
			
		||||
@@ -80,15 +81,17 @@ type adminhandler func(*adminApi, *shared.Request) (interface{}, error)
 | 
			
		||||
// admin api provider
 | 
			
		||||
type adminApi struct {
 | 
			
		||||
	xeth     *xeth.XEth
 | 
			
		||||
	network  *p2p.Server
 | 
			
		||||
	ethereum *eth.Ethereum
 | 
			
		||||
	codec    codec.Codec
 | 
			
		||||
	coder    codec.ApiCoder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create a new admin api instance
 | 
			
		||||
func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, codec codec.Codec) *adminApi {
 | 
			
		||||
func NewAdminApi(xeth *xeth.XEth, network *p2p.Server, ethereum *eth.Ethereum, codec codec.Codec) *adminApi {
 | 
			
		||||
	return &adminApi{
 | 
			
		||||
		xeth:     xeth,
 | 
			
		||||
		network:  network,
 | 
			
		||||
		ethereum: ethereum,
 | 
			
		||||
		codec:    codec,
 | 
			
		||||
		coder:    codec.New(nil),
 | 
			
		||||
@@ -137,11 +140,11 @@ func (self *adminApi) AddPeer(req *shared.Request) (interface{}, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *adminApi) Peers(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return self.ethereum.PeersInfo(), nil
 | 
			
		||||
	return self.network.PeersInfo(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *adminApi) NodeInfo(req *shared.Request) (interface{}, error) {
 | 
			
		||||
	return self.ethereum.NodeInfo(), nil
 | 
			
		||||
	return self.network.NodeInfo(), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (self *adminApi) DataDir(req *shared.Request) (interface{}, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -165,7 +165,7 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.
 | 
			
		||||
	for i, name := range names {
 | 
			
		||||
		switch strings.ToLower(strings.TrimSpace(name)) {
 | 
			
		||||
		case shared.AdminApiName:
 | 
			
		||||
			apis[i] = NewAdminApi(xeth, eth, codec)
 | 
			
		||||
			apis[i] = NewAdminApi(xeth, eth.Network(), eth, codec)
 | 
			
		||||
		case shared.DebugApiName:
 | 
			
		||||
			apis[i] = NewDebugApi(xeth, eth, codec)
 | 
			
		||||
		case shared.DbApiName:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user