eth, p2p, rpc/api: polish protocol info gathering
This commit is contained in:
parent
05f74077fb
commit
e46ab3bdcd
@ -472,62 +472,10 @@ func New(config *Config) (*Ethereum, error) {
|
|||||||
return eth, nil
|
return eth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeInfo struct {
|
// Network retrieves the underlying P2P network server. This should eventually
|
||||||
Name string
|
// be moved out into a protocol independent package, but for now use an accessor.
|
||||||
NodeUrl string
|
func (s *Ethereum) Network() *p2p.Server {
|
||||||
NodeID string
|
return s.net
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
|
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) {
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/pow"
|
"github.com/ethereum/go-ethereum/pow"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
@ -55,6 +56,8 @@ type hashFetcherFn func(common.Hash) error
|
|||||||
type blockFetcherFn func([]common.Hash) error
|
type blockFetcherFn func([]common.Hash) error
|
||||||
|
|
||||||
type ProtocolManager struct {
|
type ProtocolManager struct {
|
||||||
|
networkId int
|
||||||
|
|
||||||
fastSync bool
|
fastSync bool
|
||||||
txpool txPool
|
txpool txPool
|
||||||
blockchain *core.BlockChain
|
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
|
// Create the protocol manager with the base fields
|
||||||
manager := &ProtocolManager{
|
manager := &ProtocolManager{
|
||||||
|
networkId: networkId,
|
||||||
fastSync: fastSync,
|
fastSync: fastSync,
|
||||||
eventMux: mux,
|
eventMux: mux,
|
||||||
txpool: txpool,
|
txpool: txpool,
|
||||||
@ -111,14 +115,23 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool
|
|||||||
// Compatible; initialise the sub-protocol
|
// Compatible; initialise the sub-protocol
|
||||||
version := version // Closure for the run
|
version := version // Closure for the run
|
||||||
manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
|
manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
|
||||||
Name: "eth",
|
Name: ProtocolName,
|
||||||
Version: version,
|
Version: version,
|
||||||
Length: ProtocolLengths[i],
|
Length: ProtocolLengths[i],
|
||||||
Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
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
|
manager.newPeerCh <- peer
|
||||||
return manager.handle(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 {
|
if len(manager.SubProtocols) == 0 {
|
||||||
@ -188,8 +201,8 @@ func (pm *ProtocolManager) Stop() {
|
|||||||
glog.V(logger.Info).Infoln("Ethereum protocol handler stopped")
|
glog.V(logger.Info).Infoln("Ethereum protocol handler stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *ProtocolManager) newPeer(pv, nv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
|
func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
|
||||||
return newPeer(pv, nv, p, newMeteredMsgWriter(rw))
|
return newPeer(pv, p, newMeteredMsgWriter(rw))
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle is the callback invoked to manage the life cycle of an eth peer. When
|
// 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
|
// Execute the Ethereum handshake
|
||||||
td, head, genesis := pm.blockchain.Status()
|
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)
|
glog.V(logger.Debug).Infof("%v: handshake failed: %v", p, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -730,3 +743,22 @@ func (self *ProtocolManager) txBroadcastLoop() {
|
|||||||
self.BroadcastTx(event.Tx.Hash(), event.Tx)
|
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
|
var id discover.NodeID
|
||||||
rand.Read(id[:])
|
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
|
// Start the peer on a new thread
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
|
43
eth/peer.go
43
eth/peer.go
@ -44,16 +44,21 @@ const (
|
|||||||
handshakeTimeout = 5 * time.Second
|
handshakeTimeout = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type peer struct {
|
// PeerInfo represents a short summary of the Ethereum sub-protocol metadata known
|
||||||
*p2p.Peer
|
// 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
|
rw p2p.MsgReadWriter
|
||||||
|
|
||||||
version int // Protocol version negotiated
|
version int // Protocol version negotiated
|
||||||
network int // Network ID being on
|
|
||||||
|
|
||||||
id string
|
|
||||||
|
|
||||||
head common.Hash
|
head common.Hash
|
||||||
td *big.Int
|
td *big.Int
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
@ -62,20 +67,28 @@ type peer struct {
|
|||||||
knownBlocks *set.Set // Set of block hashes known to be known by this peer
|
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()
|
id := p.ID()
|
||||||
|
|
||||||
return &peer{
|
return &peer{
|
||||||
Peer: p,
|
Peer: p,
|
||||||
rw: rw,
|
rw: rw,
|
||||||
version: version,
|
version: version,
|
||||||
network: network,
|
|
||||||
id: fmt.Sprintf("%x", id[:8]),
|
id: fmt.Sprintf("%x", id[:8]),
|
||||||
knownTxs: set.New(),
|
knownTxs: set.New(),
|
||||||
knownBlocks: 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.
|
// Head retrieves a copy of the current head (most recent) hash of the peer.
|
||||||
func (p *peer) Head() (hash common.Hash) {
|
func (p *peer) Head() (hash common.Hash) {
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
@ -268,20 +281,22 @@ func (p *peer) RequestReceipts(hashes []common.Hash) error {
|
|||||||
|
|
||||||
// Handshake executes the eth protocol handshake, negotiating version number,
|
// Handshake executes the eth protocol handshake, negotiating version number,
|
||||||
// network IDs, difficulties, head and genesis blocks.
|
// 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)
|
errc := make(chan error, 2)
|
||||||
var status statusData // safe to read after two values have been received from errc
|
var status statusData // safe to read after two values have been received from errc
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
errc <- p2p.Send(p.rw, StatusMsg, &statusData{
|
errc <- p2p.Send(p.rw, StatusMsg, &statusData{
|
||||||
ProtocolVersion: uint32(p.version),
|
ProtocolVersion: uint32(p.version),
|
||||||
NetworkId: uint32(p.network),
|
NetworkId: uint32(network),
|
||||||
TD: td,
|
TD: td,
|
||||||
CurrentBlock: head,
|
CurrentBlock: head,
|
||||||
GenesisBlock: genesis,
|
GenesisBlock: genesis,
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
errc <- p.readStatus(&status, genesis)
|
errc <- p.readStatus(network, &status, genesis)
|
||||||
}()
|
}()
|
||||||
timeout := time.NewTimer(handshakeTimeout)
|
timeout := time.NewTimer(handshakeTimeout)
|
||||||
defer timeout.Stop()
|
defer timeout.Stop()
|
||||||
@ -299,7 +314,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash) err
|
|||||||
return nil
|
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()
|
msg, err := p.rw.ReadMsg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -317,8 +332,8 @@ func (p *peer) readStatus(status *statusData, genesis common.Hash) (err error) {
|
|||||||
if status.GenesisBlock != genesis {
|
if status.GenesisBlock != genesis {
|
||||||
return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock, genesis)
|
return errResp(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock, genesis)
|
||||||
}
|
}
|
||||||
if int(status.NetworkId) != p.network {
|
if int(status.NetworkId) != network {
|
||||||
return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, p.network)
|
return errResp(ErrNetworkIdMismatch, "%d (!= %d)", status.NetworkId, network)
|
||||||
}
|
}
|
||||||
if int(status.ProtocolVersion) != p.version {
|
if int(status.ProtocolVersion) != p.version {
|
||||||
return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version)
|
return errResp(ErrProtocolVersionMismatch, "%d (!= %d)", status.ProtocolVersion, p.version)
|
||||||
|
@ -33,6 +33,9 @@ const (
|
|||||||
eth63 = 63
|
eth63 = 63
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Official short name of the protocol used during capability negotiation.
|
||||||
|
var ProtocolName = "eth"
|
||||||
|
|
||||||
// Supported versions of the eth protocol (first is primary).
|
// Supported versions of the eth protocol (first is primary).
|
||||||
var ProtocolVersions = []uint{eth63, eth62, eth61}
|
var ProtocolVersions = []uint{eth63, eth62, eth61}
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ func TestFastSyncDisabling(t *testing.T) {
|
|||||||
// Sync up the two peers
|
// Sync up the two peers
|
||||||
io1, io2 := p2p.MsgPipe()
|
io1, io2 := p2p.MsgPipe()
|
||||||
|
|
||||||
go pmFull.handle(pmFull.newPeer(63, NetworkId, p2p.NewPeer(discover.NodeID{}, "empty", nil), io2))
|
go pmFull.handle(pmFull.newPeer(63, p2p.NewPeer(discover.NodeID{}, "empty", nil), io2))
|
||||||
go pmEmpty.handle(pmEmpty.newPeer(63, NetworkId, p2p.NewPeer(discover.NodeID{}, "full", nil), io1))
|
go pmEmpty.handle(pmEmpty.newPeer(63, p2p.NewPeer(discover.NodeID{}, "full", nil), io1))
|
||||||
|
|
||||||
time.Sleep(250 * time.Millisecond)
|
time.Sleep(250 * time.Millisecond)
|
||||||
pmEmpty.synchronise(pmEmpty.peers.BestPeer())
|
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
|
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
|
package p2p
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
|
)
|
||||||
|
|
||||||
// Protocol represents a P2P subprotocol implementation.
|
// Protocol represents a P2P subprotocol implementation.
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
@ -39,6 +43,15 @@ type Protocol struct {
|
|||||||
// any protocol-level error (such as an I/O error) that is
|
// any protocol-level error (such as an I/O error) that is
|
||||||
// encountered.
|
// encountered.
|
||||||
Run func(peer *Peer, rw MsgReadWriter) error
|
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 {
|
func (p Protocol) cap() Cap {
|
||||||
|
@ -689,3 +689,66 @@ func (srv *Server) runPeer(p *Peer) {
|
|||||||
NumConnections: srv.PeerCount(),
|
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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc/codec"
|
"github.com/ethereum/go-ethereum/rpc/codec"
|
||||||
"github.com/ethereum/go-ethereum/rpc/comms"
|
"github.com/ethereum/go-ethereum/rpc/comms"
|
||||||
@ -80,15 +81,17 @@ type adminhandler func(*adminApi, *shared.Request) (interface{}, error)
|
|||||||
// admin api provider
|
// admin api provider
|
||||||
type adminApi struct {
|
type adminApi struct {
|
||||||
xeth *xeth.XEth
|
xeth *xeth.XEth
|
||||||
|
network *p2p.Server
|
||||||
ethereum *eth.Ethereum
|
ethereum *eth.Ethereum
|
||||||
codec codec.Codec
|
codec codec.Codec
|
||||||
coder codec.ApiCoder
|
coder codec.ApiCoder
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new admin api instance
|
// 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{
|
return &adminApi{
|
||||||
xeth: xeth,
|
xeth: xeth,
|
||||||
|
network: network,
|
||||||
ethereum: ethereum,
|
ethereum: ethereum,
|
||||||
codec: codec,
|
codec: codec,
|
||||||
coder: codec.New(nil),
|
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) {
|
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) {
|
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) {
|
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 {
|
for i, name := range names {
|
||||||
switch strings.ToLower(strings.TrimSpace(name)) {
|
switch strings.ToLower(strings.TrimSpace(name)) {
|
||||||
case shared.AdminApiName:
|
case shared.AdminApiName:
|
||||||
apis[i] = NewAdminApi(xeth, eth, codec)
|
apis[i] = NewAdminApi(xeth, eth.Network(), eth, codec)
|
||||||
case shared.DebugApiName:
|
case shared.DebugApiName:
|
||||||
apis[i] = NewDebugApi(xeth, eth, codec)
|
apis[i] = NewDebugApi(xeth, eth, codec)
|
||||||
case shared.DbApiName:
|
case shared.DbApiName:
|
||||||
|
Loading…
Reference in New Issue
Block a user