diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index a57377bee..8479e9f44 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -2,6 +2,7 @@ package ethchain import ( "bytes" + "container/list" "fmt" "github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethwire" @@ -14,6 +15,16 @@ type BlockProcessor interface { ProcessBlock(block *Block) } +type Peer interface { + Inbound() bool + LastSend() time.Time + LastPong() int64 + Host() []byte + Port() uint16 + Version() string + Connected() *int32 +} + type EthManager interface { StateManager() *StateManager BlockChain() *BlockChain @@ -23,6 +34,7 @@ type EthManager interface { PeerCount() int IsMining() bool IsListening() bool + Peers() *list.List } type StateManager struct { diff --git a/ethpub/pub.go b/ethpub/pub.go index a9a962f14..6d4c230ad 100644 --- a/ethpub/pub.go +++ b/ethpub/pub.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/eth-go/ethutil" "math/big" "strings" + "sync/atomic" ) type PEthereum struct { @@ -51,6 +52,18 @@ func (lib *PEthereum) GetPeerCount() int { return lib.manager.PeerCount() } +func (lib *PEthereum) GetPeers() []PPeer { + var peers []PPeer + for peer := lib.manager.Peers().Front(); peer != nil; peer = peer.Next() { + p := peer.Value.(ethchain.Peer) + if atomic.LoadInt32(p.Connected()) != 0 { + peers = append(peers, *NewPPeer(p)) + } + } + + return peers +} + func (lib *PEthereum) GetIsMining() bool { return lib.manager.IsMining() } diff --git a/ethpub/types.go b/ethpub/types.go index 4e7c44ed4..1079f09b4 100644 --- a/ethpub/types.go +++ b/ethpub/types.go @@ -3,12 +3,40 @@ package ethpub import ( "encoding/hex" "encoding/json" + "fmt" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" - _ "log" "strings" ) +// Peer interface exposed to QML + +type PPeer struct { + ref *ethchain.Peer + Inbound bool `json:"isInbound"` + LastSend int64 `json:"lastSend"` + LastPong int64 `json:"lastPong"` + Ip string `json:"ip"` + Port int `json:"port"` + Version string `json:"version"` + LastResponse string `json:"lastResponse"` +} + +func NewPPeer(peer ethchain.Peer) *PPeer { + if peer == nil { + return nil + } + + // TODO: There must be something build in to do this? + var ip []string + for _, i := range peer.Host() { + ip = append(ip, fmt.Sprintf("%d", i)) + } + ipAddress := strings.Join(ip, ".") + + return &PPeer{ref: &peer, Inbound: peer.Inbound(), LastSend: peer.LastSend().Unix(), LastPong: peer.LastPong(), Version: peer.Version(), Ip: ipAddress, Port: int(peer.Port())} +} + // Block interface exposed to QML type PBlock struct { ref *ethchain.Block diff --git a/peer.go b/peer.go index 6853a949d..71ad91461 100644 --- a/peer.go +++ b/peer.go @@ -129,7 +129,7 @@ type Peer struct { diverted bool blocksRequested int - Version string + version string } func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer { @@ -160,7 +160,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer { connected: 0, disconnect: 0, caps: caps, - Version: ethutil.Config.ClientString, + version: ethutil.Config.ClientString, } // Set up the connection in another goroutine so we don't block the main thread @@ -184,6 +184,34 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer { return p } +// Getters +func (p *Peer) Inbound() bool { + return p.inbound +} +func (p *Peer) LastSend() time.Time { + return p.lastSend +} +func (p *Peer) LastPong() int64 { + return p.lastPong +} +func (p *Peer) Host() []byte { + return p.host +} +func (p *Peer) Port() uint16 { + return p.port +} +func (p *Peer) Version() string { + return p.version +} +func (p *Peer) Connected() *int32 { + return &p.connected +} + +// Setters +func (p *Peer) SetVersion(version string) { + p.version = version +} + // Outputs any RLP encoded data to the peer func (p *Peer) QueueMessage(msg *ethwire.Msg) { if atomic.LoadInt32(&p.connected) != 1 { @@ -531,7 +559,7 @@ func (p *Peer) pushHandshake() error { pubkey := keyRing.PublicKey msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{ - uint32(ProtocolVersion), uint32(0), p.Version, byte(p.caps), p.port, pubkey[1:], + uint32(ProtocolVersion), uint32(0), p.version, byte(p.caps), p.port, pubkey[1:], }) p.QueueMessage(msg) @@ -588,8 +616,12 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { // Set the peer's caps p.caps = Caps(c.Get(3).Byte()) + // Get a reference to the peers version - p.Version = c.Get(2).Str() + versionString := c.Get(2).Str() + if len(versionString) > 0 { + p.SetVersion(c.Get(2).Str()) + } // Catch up with the connected peer if !p.ethereum.IsUpToDate() { @@ -615,7 +647,7 @@ func (p *Peer) String() string { strConnectType = "disconnected" } - return fmt.Sprintf("[%s] (%s) %v %s [%s]", strConnectType, strBoundType, p.conn.RemoteAddr(), p.Version, p.caps) + return fmt.Sprintf("[%s] (%s) %v %s [%s]", strConnectType, strBoundType, p.conn.RemoteAddr(), p.version, p.caps) } func (p *Peer) SyncWithPeerToLastKnown() {