peer discovery enhancement for more info about connected peer

This commit is contained in:
romanman 2014-10-23 21:00:39 -05:00
parent 07245866bb
commit 7768107386
14 changed files with 380 additions and 108 deletions

View File

@ -4,7 +4,7 @@ import org.ethereum.core.Transaction;
import org.ethereum.core.Wallet;
import org.ethereum.listener.EthereumListener;
import org.ethereum.net.client.PeerClient;
import org.ethereum.net.peerdiscovery.PeerData;
import org.ethereum.net.peerdiscovery.PeerInfo;
import java.math.BigInteger;
import java.net.InetAddress;
@ -25,7 +25,7 @@ public interface Ethereum {
* @param excludePeer - peer to exclude
* @return online peer if available otherwise null
*/
public PeerData findOnlinePeer(PeerData excludePeer) ;
public PeerInfo findOnlinePeer(PeerInfo excludePeer) ;
/**
* Find an online peer but not from excluded list
@ -33,12 +33,12 @@ public interface Ethereum {
* @param excludePeerSet - peers to exclude
* @return online peer if available otherwise null
*/
public PeerData findOnlinePeer(Set<PeerData> excludePeerSet) ;
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeerSet) ;
/**
* @return online peer if available
*/
public PeerData findOnlinePeer();
public PeerInfo findOnlinePeer();
/**
@ -46,7 +46,7 @@ public interface Ethereum {
*
* @return online peer.
*/
public PeerData waitForOnlinePeer();
public PeerInfo waitForOnlinePeer();
/*
*
@ -59,7 +59,7 @@ public interface Ethereum {
* }
*
*/
public Set<PeerData> getPeers();
public Set<PeerInfo> getPeers();
public void startPeerDiscovery();
public void stopPeerDiscovery();

View File

@ -11,7 +11,7 @@ import org.ethereum.core.Wallet;
import org.ethereum.listener.EthereumListener;
import org.ethereum.manager.WorldManager;
import org.ethereum.net.client.PeerClient;
import org.ethereum.net.peerdiscovery.PeerData;
import org.ethereum.net.peerdiscovery.PeerInfo;
import org.ethereum.net.submit.TransactionExecutor;
import org.ethereum.net.submit.TransactionTask;
import org.ethereum.util.ByteUtil;
@ -39,20 +39,20 @@ public class EthereumImpl implements Ethereum {
* @return online peer
*/
@Override
public PeerData findOnlinePeer(PeerData peer) {
Set<PeerData> excludePeers = new HashSet<>();
public PeerInfo findOnlinePeer(PeerInfo peer) {
Set<PeerInfo> excludePeers = new HashSet<>();
excludePeers.add(peer);
return findOnlinePeer(excludePeers);
}
@Override
public PeerData findOnlinePeer() {
Set<PeerData> excludePeers = new HashSet<>();
public PeerInfo findOnlinePeer() {
Set<PeerInfo> excludePeers = new HashSet<>();
return findOnlinePeer(excludePeers);
}
@Override
public PeerData findOnlinePeer(Set<PeerData> excludePeers) {
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeers) {
logger.info("Looking for online peers...");
final EthereumListener listener = WorldManager.getInstance().getListener();
@ -62,9 +62,9 @@ public class EthereumImpl implements Ethereum {
WorldManager.getInstance().startPeerDiscovery();
final Set<PeerData> peers = WorldManager.getInstance().getPeerDiscovery().getPeers();
final Set<PeerInfo> peers = WorldManager.getInstance().getPeerDiscovery().getPeers();
synchronized (peers) {
for (PeerData peer : peers) { // it blocks until a peer is available.
for (PeerInfo peer : peers) { // it blocks until a peer is available.
if (peer.isOnline() && !excludePeers.contains(peer)) {
logger.info("Found peer: {}", peer.toString());
if (listener != null)
@ -77,8 +77,8 @@ public class EthereumImpl implements Ethereum {
}
@Override
public PeerData waitForOnlinePeer() {
PeerData peer = null;
public PeerInfo waitForOnlinePeer() {
PeerInfo peer = null;
while (peer == null) {
try {
Thread.sleep(100);
@ -91,7 +91,7 @@ public class EthereumImpl implements Ethereum {
}
@Override
public Set<PeerData> getPeers() {
public Set<PeerInfo> getPeers() {
return WorldManager.getInstance().getPeerDiscovery().getPeers();
}

View File

@ -10,15 +10,15 @@ import org.ethereum.manager.WorldManager;
import org.ethereum.net.MessageQueue;
import org.ethereum.net.PeerListener;
import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.eth.StatusMessage;
import org.ethereum.net.p2p.HelloMessage;
import org.ethereum.net.shh.ShhHandler;
import org.ethereum.net.wire.MessageDecoder;
import org.ethereum.net.wire.MessageEncoder;
import org.ethereum.net.p2p.P2pHandler;
import org.ethereum.net.peerdiscovery.PeerData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static org.ethereum.config.SystemProperties.CONFIG;
@ -68,7 +68,7 @@ public class PeerClient {
p2pHandler = new P2pHandler(peerListener, msgQueue);
p2pHandler.activate();
ethHandler = new EthHandler(msgQueue, peerListener);
ethHandler = new EthHandler(msgQueue, peerListener, peerDiscoveryMode);
shhHandler = new ShhHandler(msgQueue, peerListener);
try {
@ -144,4 +144,12 @@ public class PeerClient {
return false;
}
public HelloMessage getHelloHandshake(){
return p2pHandler.getHandshakeHelloMessage();
}
public StatusMessage getStatusHandshake(){
return ethHandler.getHandshakeStatusMessage();
}
}

View File

@ -1,5 +1,6 @@
package org.ethereum.net.eth;
import com.sun.org.apache.xerces.internal.util.Status;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.ethereum.core.Block;
@ -51,13 +52,18 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
private SyncSatus syncStatus = SyncSatus.INIT;
private boolean active = false;
private StatusMessage handshakeStatusMessage = null;
private boolean peerDiscovery = true;
private Timer getBlocksTimer = new Timer("GetBlocksTimer");
//
private Timer getTxTimer = new Timer("GetTransactionsTimer");
public EthHandler(MessageQueue msgQueue, PeerListener peerListener) {
public EthHandler(MessageQueue msgQueue, PeerListener peerListener, boolean peerDiscovery) {
this.peerDiscovery = true;
this.msgQueue = msgQueue;
}
@ -156,7 +162,16 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
* @param msg is the StatusMessage
* @param ctx the ChannelHandlerContext
*/
public void processStatus(StatusMessage msg, ChannelHandlerContext ctx) {
public void processStatus(StatusMessage msg, ChannelHandlerContext ctx) throws InterruptedException {
this.handshakeStatusMessage = msg;
if (peerDiscovery) {
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.REQUESTED));
killTimers();
ctx.close().sync();
ctx.disconnect().sync();
return;
}
Blockchain blockchain = WorldManager.getInstance().getBlockchain();
@ -382,4 +397,8 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
BLOCK_RETRIEVING,
SYNC_DONE;
}
public StatusMessage getHandshakeStatusMessage(){
return handshakeStatusMessage;
}
}

View File

@ -6,12 +6,7 @@ import static org.ethereum.net.message.StaticMessages.HELLO_MESSAGE;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.*;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@ -24,9 +19,9 @@ import org.ethereum.net.client.Capability;
import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.eth.EthMessageCodes;
import org.ethereum.net.eth.TransactionsMessage;
import org.ethereum.net.peerdiscovery.PeerInfo;
import org.ethereum.net.shh.ShhHandler;
import org.ethereum.net.message.*;
import org.ethereum.net.peerdiscovery.PeerData;
import org.ethereum.net.shh.ShhMessageCodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -58,9 +53,10 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
private boolean tearDown = false;
private boolean active = false;
private boolean peerDiscoveryMode = false;
private HelloMessage handshakeHelloMessage = null;
public P2pHandler(MessageQueue msgQueue) {
this.msgQueue = msgQueue;
}
@ -103,8 +99,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
switch (msg.getCommand()) {
case HELLO:
msgQueue.receivedMessage(msg);
if (!peerDiscoveryMode)
setHandshake((HelloMessage) msg, ctx);
setHandshake((HelloMessage) msg, ctx);
sendGetPeers();
break;
case DISCONNECT:
@ -125,7 +120,8 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
msgQueue.receivedMessage(msg);
processPeers(ctx, (PeersMessage) msg);
if (peerDiscoveryMode){
if (peerDiscoveryMode &&
!handshakeHelloMessage.getCapabilities().contains(Capability.ETH)){
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.REQUESTED));
killTimers();
ctx.close().sync();
@ -167,13 +163,21 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
}
private void sendPeers() {
Set<PeerData> peers = WorldManager.getInstance().getPeerDiscovery().getPeers();
PeersMessage msg = new PeersMessage(peers);
Set<PeerInfo> peers = WorldManager.getInstance().getPeerDiscovery().getPeers();
Set<Peer> peerSet = new HashSet<>();
for (PeerInfo peer : peers){
new Peer(peer.getAddress(), peer.getPort(), peer.getPeerId());
}
PeersMessage msg = new PeersMessage(peerSet);
msgQueue.sendMessage(msg);
}
private void setHandshake(HelloMessage msg, ChannelHandlerContext ctx) {
this.handshakeHelloMessage = msg;
if (msg.getP2PVersion() != P2pHandler.VERSION)
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_PROTOCOL));
else {
@ -205,7 +209,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress();
int port = msg.getListenPort();
PeerData confirmedPeer = new PeerData(address, port, msg.getPeerId());
PeerInfo confirmedPeer = new PeerInfo(address, port, msg.getPeerId());
confirmedPeer.setOnline(true);
confirmedPeer.getCapabilities().addAll(msg.getCapabilities());
@ -243,6 +247,10 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
}
}
public HelloMessage getHandshakeHelloMessage() {
return handshakeHelloMessage;
}
private void startTimers() {
// sample for pinging in background
@ -268,4 +276,6 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
msgQueue.close();
}
}

View File

@ -1,4 +1,4 @@
package org.ethereum.net.peerdiscovery;
package org.ethereum.net.p2p;
import org.ethereum.net.client.Capability;
import org.ethereum.util.RLP;
@ -11,7 +11,7 @@ import java.util.List;
/**
* This class models a peer in the network
*/
public class PeerData {
public class Peer {
private InetAddress address;
private int port;
@ -19,10 +19,7 @@ public class PeerData {
private List<Capability> capabilities;
private transient boolean isOnline = false;
private transient long lastCheckTime = 0;
public PeerData(InetAddress ip, int port, String peerId) {
public Peer(InetAddress ip, int port, String peerId) {
this.address = ip;
this.port = port;
this.peerId = peerId;
@ -41,24 +38,6 @@ public class PeerData {
return peerId == null ? "" : peerId;
}
public boolean isOnline() {
if (getCapabilities().size() < 0)
return false;
return isOnline;
}
public void setOnline(boolean online) {
isOnline = online;
}
public long getLastCheckTime() {
return lastCheckTime;
}
public void setLastCheckTime(long lastCheckTime) {
this.lastCheckTime = lastCheckTime;
}
public List<Capability> getCapabilities() {
return capabilities;
}
@ -86,7 +65,7 @@ public class PeerData {
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
PeerData peerData = (PeerData) obj;
Peer peerData = (Peer) obj;
return peerData.peerId.equals(this.peerId)
|| this.getAddress().equals(peerData.getAddress());
}

View File

@ -8,7 +8,7 @@ import java.util.List;
import java.util.Set;
import org.ethereum.net.p2p.P2pMessage;
import org.ethereum.net.peerdiscovery.PeerData;
import org.ethereum.net.p2p.Peer;
import org.ethereum.util.ByteUtil;
import org.ethereum.util.RLP;
import org.ethereum.util.RLPList;
@ -23,13 +23,13 @@ public class PeersMessage extends P2pMessage {
private boolean parsed = false;
private Set<PeerData> peers;
private Set<Peer> peers;
public PeersMessage(byte[] payload) {
super(payload);
}
public PeersMessage(Set<PeerData> peers) {
public PeersMessage(Set<Peer> peers) {
this.peers = peers;
parsed = true;
}
@ -49,7 +49,7 @@ public class PeersMessage extends P2pMessage {
InetAddress address = InetAddress.getByAddress(ipBytes);
String peerId = peerIdRaw == null ? "" : Hex.toHexString(peerIdRaw);
PeerData peer = new PeerData(address, peerPort, peerId);
Peer peer = new Peer(address, peerPort, peerId);
peers.add(peer);
} catch (UnknownHostException e) {
throw new RuntimeException("Malformed ip", e);
@ -61,7 +61,7 @@ public class PeersMessage extends P2pMessage {
private void encode() {
byte[][] encodedByteArrays = new byte[this.peers.size() + 1][];
encodedByteArrays[0] = RLP.encodeByte(this.getCommand().asByte());
List<PeerData> peerList = new ArrayList<>(this.peers);
List<Peer> peerList = new ArrayList<>(this.peers);
for (int i = 0; i < peerList.size(); i++) {
encodedByteArrays[i + 1] = peerList.get(i).getEncoded();
}
@ -74,7 +74,7 @@ public class PeersMessage extends P2pMessage {
return encoded;
}
public Set<PeerData> getPeers() {
public Set<Peer> getPeers() {
if (!parsed) this.parse();
return peers;
}
@ -93,7 +93,7 @@ public class PeersMessage extends P2pMessage {
if (!parsed) this.parse();
StringBuffer sb = new StringBuffer();
for (PeerData peerData : peers) {
for (Peer peerData : peers) {
sb.append("\n ").append(peerData);
}
return "[" + this.getCommand().name() + sb.toString() + "]";

View File

@ -1,5 +1,6 @@
package org.ethereum.net.peerdiscovery;
import org.ethereum.net.p2p.Peer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -19,7 +20,7 @@ public class PeerDiscovery {
private static final Logger logger = LoggerFactory.getLogger("peerdiscovery");
private final Set<PeerData> peers = Collections.synchronizedSet(new HashSet<PeerData>());
private final Set<PeerInfo> peers = Collections.synchronizedSet(new HashSet<PeerInfo>());
private PeerMonitorThread monitor;
private ThreadFactory threadFactory;
@ -47,10 +48,10 @@ public class PeerDiscovery {
monitorThread.start();
// Initialize PeerData
List<PeerData> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
List<PeerInfo> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
peers.addAll(peerDataList);
for (PeerData peerData : this.peers) {
for (PeerInfo peerData : this.peers) {
executorPool.execute(new WorkerThread(peerData, executorPool));
}
@ -67,7 +68,7 @@ public class PeerDiscovery {
return started.get();
}
public Set<PeerData> getPeers() {
public Set<PeerInfo> getPeers() {
return peers;
}
@ -77,26 +78,28 @@ public class PeerDiscovery {
*
* @param newPeers to be added to the list of known peers
*/
public void addPeers(final Set<PeerData> newPeers) {
public void addPeers(Set<Peer> newPeers) {
synchronized (peers) {
for (final PeerData newPeer : newPeers) {
if (started.get() && !peers.contains(newPeer)){
startWorker(newPeer);
for (final Peer newPeer : newPeers) {
PeerInfo peerInfo =
new PeerInfo(newPeer.getAddress(), newPeer.getPort(), newPeer.getPeerId());
if (started.get() && !peers.contains(peerInfo )){
startWorker(peerInfo);
}
peers.add(newPeer);
peers.add(peerInfo);
}
}
}
private void startWorker(PeerData peer) {
private void startWorker(PeerInfo peer) {
logger.debug("Add new peer for discovery: {}", peer);
executorPool.execute(new WorkerThread(peer, executorPool));
}
public List<PeerData> parsePeerDiscoveryIpList(final String peerDiscoveryIpList){
public List<PeerInfo> parsePeerDiscoveryIpList(final String peerDiscoveryIpList){
final List<String> ipList = Arrays.asList( peerDiscoveryIpList.split(",") );
final List<PeerData> peers = new ArrayList<>();
final List<PeerInfo> peers = new ArrayList<>();
for (String ip : ipList){
String[] addr = ip.trim().split(":");
@ -107,7 +110,7 @@ public class PeerDiscovery {
InetAddress iAddr = InetAddress.getByName(ip_trim);
int port = Integer.parseInt(port_trim);
PeerData peerData = new PeerData(iAddr, port, "");
PeerInfo peerData = new PeerInfo(iAddr, port, "");
peers.add(peerData);
} catch (UnknownHostException e) {
e.printStackTrace();

View File

@ -0,0 +1,113 @@
package org.ethereum.net.peerdiscovery;
import org.ethereum.net.client.Capability;
import org.ethereum.net.eth.StatusMessage;
import org.ethereum.net.p2p.HelloMessage;
import org.ethereum.util.RLP;
import org.spongycastle.util.encoders.Hex;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
/**
* This class models a peer in the network
*/
public class PeerInfo {
private InetAddress address;
private int port;
private String peerId;
private List<Capability> capabilities;
private HelloMessage handshakeHelloMessage;
private StatusMessage statusMessage;
private transient boolean isOnline = false;
private transient long lastCheckTime = 0;
public PeerInfo(InetAddress ip, int port, String peerId) {
this.address = ip;
this.port = port;
this.peerId = peerId;
this.capabilities = new ArrayList<>();
}
public InetAddress getAddress() {
return address;
}
public int getPort() {
return port;
}
public String getPeerId() {
return peerId == null ? "" : peerId;
}
public boolean isOnline() {
if (getCapabilities().size() < 0)
return false;
return isOnline;
}
public void setOnline(boolean online) {
isOnline = online;
}
public long getLastCheckTime() {
return lastCheckTime;
}
public void setLastCheckTime(long lastCheckTime) {
this.lastCheckTime = lastCheckTime;
}
public List<Capability> getCapabilities() {
return capabilities;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PeerInfo: [ ip=").append(getAddress().getHostAddress())
.append(" port=").append(getPort())
.append(" peerId=").append(getPeerId()).append("] \n")
.append(this.handshakeHelloMessage == null ? "" : handshakeHelloMessage + "\n")
.append(this.statusMessage == null ? "" : statusMessage + "\n");
return sb.toString();
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
PeerInfo peerData = (PeerInfo) obj;
return peerData.peerId.equals(this.peerId)
|| this.getAddress().equals(peerData.getAddress());
}
@Override
public int hashCode() {
return -1; // override for equals function
}
public HelloMessage getHandshakeHelloMessage() {
return handshakeHelloMessage;
}
public void setHandshakeHelloMessage(HelloMessage handshakeHelloMessage) {
this.handshakeHelloMessage = handshakeHelloMessage;
}
public StatusMessage getStatusMessage() {
return statusMessage;
}
public void setStatusMessage(StatusMessage statusMessage) {
this.statusMessage = statusMessage;
}
}

View File

@ -1,7 +1,6 @@
package org.ethereum.net.peerdiscovery;
import org.ethereum.net.client.PeerClient;
import org.ethereum.net.peerdiscovery.PeerData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -15,12 +14,12 @@ public class WorkerThread implements Runnable {
private final static Logger logger = LoggerFactory.getLogger("peerdiscovery");
private PeerData peer;
private PeerInfo peerInfo;
private PeerClient clientPeer;
private ThreadPoolExecutor poolExecutor;
public WorkerThread(PeerData peer, ThreadPoolExecutor poolExecutor) {
this.peer = peer;
public WorkerThread(PeerInfo peer, ThreadPoolExecutor poolExecutor) {
this.peerInfo = peer;
this.poolExecutor = poolExecutor;
}
@ -37,26 +36,29 @@ public class WorkerThread implements Runnable {
try {
clientPeer = new PeerClient(true);
clientPeer.connect(peer.getAddress().getHostAddress(), peer.getPort());
peer.setOnline(true);
logger.info("Peer is online: [{}] ", peer
.getAddress().getHostAddress());
clientPeer.connect(peerInfo.getAddress().getHostAddress(), peerInfo.getPort());
peerInfo.setOnline(true);
peerInfo.setHandshakeHelloMessage(clientPeer.getHelloHandshake());
peerInfo.setStatusMessage( clientPeer.getStatusHandshake() );
logger.info("Peer is online: [{}] ", peerInfo);
} catch (Throwable e) {
if (peer.isOnline())
logger.info("Peer: [{}] went offline, due to: [{}]", peer
if (peerInfo.isOnline())
logger.info("Peer: [{}] went offline, due to: [{}]", peerInfo
.getAddress().getHostAddress(), e);
peer.setOnline(false);
peerInfo.setOnline(false);
} finally {
logger.info("Peer: " + peer.toString() + " is "
+ (peer.isOnline() ? "online" : "offline"));
peer.setLastCheckTime(System.currentTimeMillis());
logger.info("Peer: " + peerInfo.toString() + " is "
+ (peerInfo.isOnline() ? "online" : "offline"));
peerInfo.setLastCheckTime(System.currentTimeMillis());
}
}
@Override
public String toString() {
return "Worker for: " + this.peer.toString();
return "Worker for: " + this.peerInfo.toString();
}
}

View File

@ -10,8 +10,9 @@ import java.util.Set;
import org.ethereum.net.p2p.GetPeersMessage;
import org.ethereum.net.p2p.P2pMessageCodes;
import org.ethereum.net.p2p.Peer;
import org.ethereum.net.p2p.PeersMessage;
import org.ethereum.net.peerdiscovery.PeerData;
import org.ethereum.net.peerdiscovery.PeerInfo;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
@ -51,8 +52,8 @@ public class PeersMessageTest {
assertEquals(2, peersMessage.getPeers().size());
Iterator<PeerData> it = peersMessage.getPeers().iterator(); it.next();
PeerData peer = it.next();
Iterator<Peer> it = peersMessage.getPeers().iterator(); it.next();
Peer peer = it.next();
assertEquals(P2pMessageCodes.PEERS, peersMessage.getCommand());
assertEquals("/81.99.225.18", peer.getAddress().toString());
@ -63,9 +64,9 @@ public class PeersMessageTest {
@Test /* PeersMessage 2 from constructor */
public void testPeers_2() throws UnknownHostException {
Set<PeerData> peers = new HashSet<>();
peers.add(new PeerData(InetAddress.getByName("82.217.72.169"), 30303, "585764a3c49a3838c69ad0855abfeb5672f71b072af62082b5679961781100814b8de88a8fbc1da7c73791f88159d73b5d2a13a5579535d603e045c3db5cbb75"));
peers.add(new PeerData(InetAddress.getByName("192.168.1.193"), 30303, ""));
Set<Peer> peers = new HashSet<>();
peers.add(new Peer(InetAddress.getByName("82.217.72.169"), 30303, "585764a3c49a3838c69ad0855abfeb5672f71b072af62082b5679961781100814b8de88a8fbc1da7c73791f88159d73b5d2a13a5579535d603e045c3db5cbb75"));
peers.add(new Peer(InetAddress.getByName("192.168.1.193"), 30303, ""));
PeersMessage peersMessage = new PeersMessage(peers);
System.out.println(peersMessage.toString());

View File

@ -0,0 +1,91 @@
package org.ethereum.gui;
import org.ethereum.config.SystemProperties;
import org.ethereum.net.PeerListener;
import org.ethereum.net.client.PeerClient;
import org.fife.ui.rsyntaxtextarea.*;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static org.ethereum.config.SystemProperties.CONFIG;
/**
* A simple example showing how to modify the fonts and colors used in an
* RSyntaxTextArea. There are two methods to do this - via the Java API, and via
* an XML file. The latter method is preferred since it's more modular, and
* provides a way for your users to customize RSTA in your application.<p>
*
* This example uses RSyntaxTextArea 2.0.1.<p>
*
* Project Home: http://fifesoft.com/rsyntaxtextarea<br>
* Downloads: https://sourceforge.net/projects/rsyntaxtextarea
*/
public class PeerInfoWindow extends JFrame {
private static final long serialVersionUID = 1L;
private boolean autoScroll = false;
private RSyntaxTextArea textArea;
private ToolBar toolBar = null;
/**
* ERROR (exceptions) WARN (when something happens that's not supposed to)
* INFO (wire output)
* DEBUG (test/displaying intermediate values),
* TRACE (start/end method)
*/
public PeerInfoWindow(PeersTableModel.PeerInfo peerInfo) {
final PeerInfoWindow thisConsole = this;
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage(img);
addCloseAction();
JPanel cp = new JPanel(new BorderLayout());
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance();
atmf.putMapping("text/console", "org.ethereum.gui.ConsoleTokenMaker");
textArea = new RSyntaxTextArea(16, 44);
textArea.setSyntaxEditingStyle("text/console");
// textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_LISP);
textArea.setCodeFoldingEnabled(true);
textArea.setAntiAliasingEnabled(true);
RTextScrollPane sp = new RTextScrollPane(textArea);
textArea.setText(peerInfo.toString());
cp.add(sp);
setContentPane(cp);
setTitle("Connection Console");
// setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setLocation(802, 460);
if (CONFIG.peerDiscovery())
UIEthereumManager.ethereum.startPeerDiscovery();
}
public void addCloseAction() {
this.addWindowListener(new WindowAdapter() {
});
}
public static void main(String[] args) {
// Start all Swing applications on the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new PeerInfoWindow(null).setVisible(true);
}
});
}
}

View File

@ -10,7 +10,10 @@ import javax.swing.table.AbstractTableModel;
import org.ethereum.geo.IpGeoDB;
import org.ethereum.net.peerdiscovery.PeerData;
import org.ethereum.net.eth.StatusMessage;
import org.ethereum.net.p2p.HelloMessage;
import org.ethereum.net.peerdiscovery.PeerInfo;
import org.ethereum.util.Utils;
import com.maxmind.geoip.Location;
@ -110,29 +113,37 @@ public class PeersTableModel extends AbstractTableModel {
synchronized (peerInfoList) {
peerInfoList.clear();
final Set<PeerData> peers = UIEthereumManager.ethereum.getPeers();
final Set<org.ethereum.net.peerdiscovery.PeerInfo> peers = UIEthereumManager.ethereum.getPeers();
synchronized (peers){
for (PeerData peer : peers) {
for (org.ethereum.net.peerdiscovery.PeerInfo peer : peers) {
InetAddress addr = peer.getAddress();
Location cr = IpGeoDB.getLocationForIp(addr);
peerInfoList.add(new PeerInfo(cr, addr, peer.isOnline(), peer.getLastCheckTime()));
peerInfoList.add(new PeerInfo(cr, addr, peer.isOnline(), peer.getLastCheckTime(),
peer.getHandshakeHelloMessage(), peer.getStatusMessage()));
}
}
}
}
private class PeerInfo {
public PeerInfo getPeerInfo(int index){
return peerInfoList.get(index);
}
public class PeerInfo {
Location location;
InetAddress ip;
boolean connected;
long lastAccessed = 0;
HelloMessage handshakeHelloMessage;
StatusMessage handshakeStatusMessage;
private PeerInfo(Location location, InetAddress ip,
boolean isConnected, long lastAccessed) {
boolean isConnected, long lastAccessed, HelloMessage helloMessage, StatusMessage statusMessage) {
if (location == null)
this.location = new Location();
@ -142,6 +153,8 @@ public class PeersTableModel extends AbstractTableModel {
this.ip = ip;
this.connected = isConnected;
this.lastAccessed = lastAccessed;
this.handshakeHelloMessage = helloMessage;
this.handshakeStatusMessage = statusMessage;
}
private Location getLocation() {
@ -159,6 +172,17 @@ public class PeersTableModel extends AbstractTableModel {
public long getLastAccessed() {
return lastAccessed;
}
@Override
public String toString() {
return "PeerInfo{" +
"location=" + location.city +
", ip=" + ip +
", connected=" + connected +
", lastAccessed=" + lastAccessed +
'}' + "\n -->" + (handshakeHelloMessage == null ?"": handshakeHelloMessage.toString())
+ "\n -->" + (handshakeStatusMessage == null?"": handshakeStatusMessage.toString());
}
}
}

View File

@ -1,6 +1,10 @@
package org.ethereum.gui;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Timer;
@ -55,6 +59,24 @@ public class PeersTableWindow extends JFrame {
table = new JTable();
table.setModel(new PeersTableModel());
table.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
JTable table =(JTable) me.getSource();
Point p = me.getPoint();
int row = table.rowAtPoint(p);
PeersTableModel model = (PeersTableModel) table.getModel();
if (me.getClickCount() == 2) {
final PeersTableModel.PeerInfo peerInfo = model.getPeerInfo(row);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new PeerInfoWindow(peerInfo).setVisible(true);
}
});
System.out.println(peerInfo);
}
}
});
table.setFont(new Font("Courier New", Font.PLAIN, 15));
table.setForeground(Color.GRAY);
table.setTableHeader(null);