Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Added peers details to ethcore_netPeers RPC (#2580)
Browse files Browse the repository at this point in the history
* added peers details to ethcore_netPeers RPC

* fixed build (traits autoimplemented)

* - documentation fixes
- spaces -> tabs
- Rust-way Option's handling

* prepare for new protocols in ethcore_netPeers

* commas & documentation
  • Loading branch information
svyatonik authored and arkpar committed Oct 12, 2016
1 parent 693b0ec commit c9ce25c
Show file tree
Hide file tree
Showing 16 changed files with 224 additions and 24 deletions.
5 changes: 4 additions & 1 deletion rpc/src/v1/impls/ethcore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,16 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
fn net_peers(&self) -> Result<Peers, Error> {
try!(self.active());

let sync_status = take_weak!(self.sync).status();
let sync = take_weak!(self.sync);
let sync_status = sync.status();
let net_config = take_weak!(self.net).network_config();
let peers = sync.peers().into_iter().map(Into::into).collect();

Ok(Peers {
active: sync_status.num_active_peers,
connected: sync_status.num_peers,
max: sync_status.current_max_peers(net_config.min_peers, net_config.max_peers),
peers: peers
})
}

Expand Down
27 changes: 26 additions & 1 deletion rpc/src/v1/tests/helpers/sync_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! Test implementation of SyncProvider.
use util::{RwLock, U256};
use ethsync::{SyncProvider, SyncStatus, SyncState};
use ethsync::{SyncProvider, SyncStatus, SyncState, PeerInfo};

/// TestSyncProvider config.
pub struct Config {
Expand Down Expand Up @@ -60,5 +60,30 @@ impl SyncProvider for TestSyncProvider {
fn status(&self) -> SyncStatus {
self.status.read().clone()
}

fn peers(&self) -> Vec<PeerInfo> {
vec![
PeerInfo {
id: Some("node1".to_owned()),
client_version: "Parity/1".to_owned(),
capabilities: vec!["eth/62".to_owned(), "eth/63".to_owned()],
remote_address: "127.0.0.1:7777".to_owned(),
local_address: "127.0.0.1:8888".to_owned(),
eth_version: 62,
eth_difficulty: Some(40.into()),
eth_head: 50.into()
},
PeerInfo {
id: None,
client_version: "Parity/2".to_owned(),
capabilities: vec!["eth/63".to_owned(), "eth/64".to_owned()],
remote_address: "Handshake".to_owned(),
local_address: "127.0.0.1:3333".to_owned(),
eth_version: 64,
eth_difficulty: None,
eth_head: 60.into()
}
]
}
}

7 changes: 6 additions & 1 deletion rpc/src/v1/tests/mocked/ethcore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,12 @@ fn rpc_ethcore_net_peers() {
io.add_delegate(ethcore_client(&client, &miner, &sync, &net).to_delegate());

let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPeers", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"active":0,"connected":120,"max":50},"id":1}"#;
let response = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":120,\"max\":50,\"peers\":[{\"caps\":[\"eth/62\",\"eth/63\"],\
\"id\":\"node1\",\"name\":\"Parity/1\",\"network\":{\"localAddress\":\"127.0.0.1:8888\",\"remoteAddress\":\"127.0.0.1:7777\"}\
,\"protocols\":{\"eth\":{\"difficulty\":\"0x28\",\"head\":\"0000000000000000000000000000000000000000000000000000000000000032\"\
,\"version\":62}}},{\"caps\":[\"eth/63\",\"eth/64\"],\"id\":null,\"name\":\"Parity/2\",\"network\":{\"localAddress\":\
\"127.0.0.1:3333\",\"remoteAddress\":\"Handshake\"},\"protocols\":{\"eth\":{\"difficulty\":null,\"head\":\
\"000000000000000000000000000000000000000000000000000000000000003c\",\"version\":64}}}]},\"id\":1}";

assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/v1/types/mod.rs.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub use self::filter::{Filter, FilterChanges};
pub use self::hash::{H64, H160, H256, H512, H520, H2048};
pub use self::index::Index;
pub use self::log::Log;
pub use self::sync::{SyncStatus, SyncInfo, Peers};
pub use self::sync::{SyncStatus, SyncInfo, Peers, PeerInfo, PeerNetworkInfo, PeerProtocolsInfo, PeerEthereumProtocolInfo};
pub use self::transaction::Transaction;
pub use self::transaction_request::TransactionRequest;
pub use self::receipt::Receipt;
Expand Down
72 changes: 70 additions & 2 deletions rpc/src/v1/types/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use ethsync::PeerInfo as SyncPeerInfo;
use serde::{Serialize, Serializer};
use v1::types::U256;

Expand All @@ -32,14 +33,60 @@ pub struct SyncInfo {
}

/// Peers info
#[derive(Default, Debug, Serialize, PartialEq)]
#[derive(Default, Debug, Serialize)]
pub struct Peers {
/// Number of active peers
pub active: usize,
/// Number of connected peers
pub connected: usize,
/// Max number of peers
pub max: u32,
/// Detailed information on peers
pub peers: Vec<PeerInfo>,
}

/// Peer connection information
#[derive(Default, Debug, Serialize)]
pub struct PeerInfo {
/// Public node id
pub id: Option<String>,
/// Node client ID
pub name: String,
/// Capabilities
pub caps: Vec<String>,
/// Network information
pub network: PeerNetworkInfo,
/// Protocols information
pub protocols: PeerProtocolsInfo,
}

/// Peer network information
#[derive(Default, Debug, Serialize)]
pub struct PeerNetworkInfo {
/// Remote endpoint address
#[serde(rename="remoteAddress")]
pub remote_address: String,
/// Local endpoint address
#[serde(rename="localAddress")]
pub local_address: String,
}

/// Peer protocols information
#[derive(Default, Debug, Serialize)]
pub struct PeerProtocolsInfo {
/// Ethereum protocol information
pub eth: Option<PeerEthereumProtocolInfo>,
}

/// Peer Ethereum protocol information
#[derive(Default, Debug, Serialize)]
pub struct PeerEthereumProtocolInfo {
/// Negotiated ethereum protocol version
pub version: u32,
/// Peer total difficulty if known
pub difficulty: Option<U256>,
/// SHA3 of peer best block hash
pub head: String,
}

/// Sync status
Expand All @@ -61,6 +108,27 @@ impl Serialize for SyncStatus {
}
}

impl From<SyncPeerInfo> for PeerInfo {
fn from(p: SyncPeerInfo) -> PeerInfo {
PeerInfo {
id: p.id,
name: p.client_version,
caps: p.capabilities,
network: PeerNetworkInfo {
remote_address: p.remote_address,
local_address: p.local_address,
},
protocols: PeerProtocolsInfo {
eth: Some(PeerEthereumProtocolInfo {
version: p.eth_version,
difficulty: p.eth_difficulty.map(|d| d.into()),
head: p.eth_head.hex(),
})
},
}
}
}

#[cfg(test)]
mod tests {
use serde_json;
Expand All @@ -77,7 +145,7 @@ mod tests {
fn test_serialize_peers() {
let t = Peers::default();
let serialized = serde_json::to_string(&t).unwrap();
assert_eq!(serialized, r#"{"active":0,"connected":0,"max":0}"#);
assert_eq!(serialized, r#"{"active":0,"connected":0,"max":0,"peers":[]}"#);
}

#[test]
Expand Down
32 changes: 32 additions & 0 deletions sync/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ binary_fixed_size!(SyncStatus);
pub trait SyncProvider: Send + Sync {
/// Get sync status
fn status(&self) -> SyncStatus;

/// Get peers information
fn peers(&self) -> Vec<PeerInfo>;
}

/// Peer connection information
#[derive(Debug, Binary)]
pub struct PeerInfo {
/// Public node id
pub id: Option<String>,
/// Node client ID
pub client_version: String,
/// Capabilities
pub capabilities: Vec<String>,
/// Remote endpoint address
pub remote_address: String,
/// Local endpoint address
pub local_address: String,
/// Ethereum protocol version
pub eth_version: u32,
/// SHA3 of peer best block hash
pub eth_head: H256,
/// Peer total difficulty if known
pub eth_difficulty: Option<U256>,
}

/// Ethereum network protocol handler
Expand Down Expand Up @@ -94,6 +118,14 @@ impl SyncProvider for EthSync {
fn status(&self) -> SyncStatus {
self.handler.sync.write().status()
}

/// Get sync peers
fn peers(&self) -> Vec<PeerInfo> {
self.network.with_context_eval(self.subprotocol_name, |context| {
let sync_io = NetSyncIo::new(context, &*self.handler.chain, &*self.handler.snapshot_service);
self.handler.sync.write().peers(&sync_io)
}).unwrap_or(Vec::new())
}
}

struct SyncProtocolHandler {
Expand Down
22 changes: 21 additions & 1 deletion sync/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ use super::SyncConfig;
use blocks::BlockCollection;
use snapshot::{Snapshot, ChunkType};
use rand::{thread_rng, Rng};
use api::PeerInfo as PeerInfoDigest;

known_heap_size!(0, PeerInfo);

Expand Down Expand Up @@ -346,7 +347,7 @@ impl ChainSync {
}
}

/// @returns Synchonization status
/// Returns synchonization status
pub fn status(&self) -> SyncStatus {
SyncStatus {
state: self.state.clone(),
Expand All @@ -368,6 +369,25 @@ impl ChainSync {
}
}

/// Returns information on peers connections
pub fn peers(&self, io: &SyncIo) -> Vec<PeerInfoDigest> {
self.peers.iter()
.filter_map(|(&peer_id, ref peer_data)|
io.peer_session_info(peer_id).map(|session_info|
PeerInfoDigest {
id: session_info.id.map(|id| id.hex()),
client_version: session_info.client_version,
capabilities: session_info.peer_capabilities.into_iter().map(|c| c.to_string()).collect(),
remote_address: session_info.remote_address,
local_address: session_info.local_address,
eth_version: peer_data.protocol_version,
eth_difficulty: peer_data.difficulty,
eth_head: peer_data.latest_hash,
})
)
.collect()
}

/// Abort all sync activity
pub fn abort(&mut self, io: &mut SyncIo) {
self.restart(io);
Expand Down
2 changes: 1 addition & 1 deletion sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ mod api {
}

pub use api::{EthSync, SyncProvider, SyncClient, NetworkManagerClient, ManageNetwork, SyncConfig,
ServiceConfiguration, NetworkConfiguration};
ServiceConfiguration, NetworkConfiguration, PeerInfo};
pub use chain::{SyncStatus, SyncState};
pub use network::{is_valid_node_url, NonReservedPeerMode, NetworkError};

Expand Down
10 changes: 6 additions & 4 deletions sync/src/sync_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use network::{NetworkContext, PeerId, PacketId, NetworkError};
use network::{NetworkContext, PeerId, PacketId, NetworkError, SessionInfo};
use ethcore::client::BlockChainClient;
use ethcore::snapshot::SnapshotService;

Expand All @@ -34,10 +34,12 @@ pub trait SyncIo {
fn chain(&self) -> &BlockChainClient;
/// Get the snapshot service.
fn snapshot_service(&self) -> &SnapshotService;
/// Returns peer client identifier string
/// Returns peer identifier string
fn peer_info(&self, peer_id: PeerId) -> String {
peer_id.to_string()
}
/// Returns information on p2p session
fn peer_session_info(&self, peer_id: PeerId) -> Option<SessionInfo>;
/// Maximum mutuallt supported ETH protocol version
fn eth_protocol_version(&self, peer_id: PeerId) -> u8;
/// Returns if the chain block queue empty
Expand Down Expand Up @@ -91,8 +93,8 @@ impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> {
self.snapshot_service
}

fn peer_info(&self, peer_id: PeerId) -> String {
self.network.peer_info(peer_id)
fn peer_session_info(&self, peer_id: PeerId) -> Option<SessionInfo> {
self.network.session_info(peer_id)
}

fn is_expired(&self) -> bool {
Expand Down
4 changes: 4 additions & 0 deletions sync/src/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ impl<'p> SyncIo for TestIo<'p> {
self.snapshot_service
}

fn peer_session_info(&self, _peer_id: PeerId) -> Option<SessionInfo> {
None
}

fn eth_protocol_version(&self, _peer: PeerId) -> u8 {
64
}
Expand Down
5 changes: 5 additions & 0 deletions util/network/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ impl Connection {
self.socket.peer_addr().map(|a| a.to_string()).unwrap_or_else(|_| "Unknown".to_owned())
}

/// Get local peer address string
pub fn local_addr_str(&self) -> String {
self.socket.local_addr().map(|a| a.to_string()).unwrap_or_else(|_| "Unknown".to_owned())
}

/// Clone this connection. Clears the receiving buffer of the returned connection.
pub fn try_clone(&self) -> io::Result<Self> {
Ok(Connection {
Expand Down
22 changes: 15 additions & 7 deletions util/network/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use util::hash::*;
use util::Hashable;
use util::version;
use rlp::*;
use session::{Session, SessionData};
use session::{Session, SessionInfo, SessionData};
use error::*;
use io::*;
use {NetworkProtocolHandler, NonReservedPeerMode, PROTOCOL_VERSION};
Expand Down Expand Up @@ -280,12 +280,13 @@ impl<'s> NetworkContext<'s> {
}

/// Returns peer identification string
pub fn peer_info(&self, peer: PeerId) -> String {
let session = self.resolve_session(peer);
if let Some(session) = session {
return session.lock().info.client_version.clone()
}
"unknown".to_owned()
pub fn peer_client_version(&self, peer: PeerId) -> String {
self.resolve_session(peer).map_or("unknown".to_owned(), |s| s.lock().info.client_version.clone())
}

/// Returns information on p2p session
pub fn session_info(&self, peer: PeerId) -> Option<SessionInfo> {
self.resolve_session(peer).map(|s| s.lock().info.clone())
}

/// Returns max version for a given protocol.
Expand Down Expand Up @@ -918,6 +919,13 @@ impl Host {
let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
action(&context);
}

pub fn with_context_eval<F, T>(&self, protocol: ProtocolId, io: &IoContext<NetworkIoMessage>, action: F) -> T where F: Fn(&NetworkContext) -> T {
let reserved = { self.reserved_nodes.read() };

let context = NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved);
action(&context)
}
}

impl IoHandler<NetworkIoMessage> for Host {
Expand Down
1 change: 1 addition & 0 deletions util/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub use host::NetworkIoMessage;
pub use error::NetworkError;
pub use host::NetworkConfiguration;
pub use stats::NetworkStats;
pub use session::SessionInfo;

use io::TimerToken;
pub use node_table::is_valid_node_url;
Expand Down
Loading

0 comments on commit c9ce25c

Please sign in to comment.