Use the new TCPNetworkConnection.connectTo API in PrintPeers, act as an example of the Guava futures API too.

This commit is contained in:
Mike Hearn 2012-08-30 23:16:37 +02:00
parent 8453654b85
commit 2961f65594

View File

@ -16,24 +16,22 @@
package com.google.bitcoin.examples;
import com.google.bitcoin.core.Message;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.TCPNetworkConnection;
import com.google.bitcoin.core.VersionMessage;
import com.google.bitcoin.discovery.DnsDiscovery;
import com.google.bitcoin.discovery.IrcDiscovery;
import com.google.bitcoin.discovery.PeerDiscoveryException;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.List;
/**
* Prints a list of IP addresses connected to the rendezvous point on the LFnet IRC channel.
@ -55,7 +53,7 @@ public class PrintPeers {
private static void printIRC() throws PeerDiscoveryException {
long start = System.currentTimeMillis();
IrcDiscovery d = new IrcDiscovery("#bitcoinTEST") {
IrcDiscovery d = new IrcDiscovery("#bitcoin") {
@Override
protected void onIRCReceive(String message) {
System.out.println("<- " + message);
@ -80,67 +78,54 @@ public class PrintPeers {
}
public static void main(String[] args) throws Exception {
BriefLogFormatter.init();
System.out.println("=== IRC ===");
printIRC();
System.out.println("=== DNS ===");
printDNS();
System.out.println("=== Version/chain heights ===");
ExecutorService pool = Executors.newFixedThreadPool(100);
ArrayList<InetAddress> addrs = new ArrayList<InetAddress>();
for (InetSocketAddress peer : dnsPeers) addrs.add(peer.getAddress());
for (InetSocketAddress peer : ircPeers) addrs.add(peer.getAddress());
System.out.println("Scanning " + addrs.size() + " peers:");
final NetworkParameters params = NetworkParameters.testNet();
final NetworkParameters params = NetworkParameters.prodNet();
final Object lock = new Object();
final long[] bestHeight = new long[1];
final ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
for (final InetAddress addr : addrs) {
pool.submit(new Runnable() {
public void run() {
try {
ChannelPipeline pipeline = Channels.pipeline();
final CountDownLatch latch = new CountDownLatch(1);
TCPNetworkConnection conn =
new TCPNetworkConnection(params, new VersionMessage(params, 0));
pipeline.addLast("codec", conn.getHandler());
pipeline.addLast("peer", new SimpleChannelHandler() {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Message m = (Message)e.getMessage();
if (m instanceof VersionMessage) {
VersionMessage ver = (VersionMessage)m;
long nodeHeight = ver.bestHeight;
synchronized (lock) {
long diff = bestHeight[0] - nodeHeight;
if (diff > 0) {
System.out.println("Node is behind by " + diff + " blocks: " + addr.toString());
} else {
bestHeight[0] = nodeHeight;
}
}
e.getChannel().close();
latch.countDown();
}
};
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.err.println(addr.toString() + " : " + e.getCause().getMessage());
latch.countDown();
};
});
bootstrap.setPipeline(pipeline);
bootstrap.connect(new InetSocketAddress(addr, params.port));
latch.await();
} catch (Exception e) {
List<ListenableFuture<TCPNetworkConnection>> futures = Lists.newArrayList();
for (final InetAddress addr : addrs) {
final ListenableFuture<TCPNetworkConnection> future =
TCPNetworkConnection.connectTo(params, new InetSocketAddress(addr, params.port), 1000 /* timeout */);
futures.add(future);
// Once the connection has completed version handshaking ...
Futures.addCallback(future, new FutureCallback<TCPNetworkConnection>() {
public void onSuccess(TCPNetworkConnection conn) {
// Check the chain height it claims to have.
VersionMessage ver = conn.getVersionMessage();
long nodeHeight = ver.bestHeight;
synchronized (lock) {
long diff = bestHeight[0] - nodeHeight;
if (diff > 0) {
System.out.println("Node is behind by " + diff + " blocks: " + addr);
} else if (diff == 0) {
System.out.println("Node " + addr + " has " + nodeHeight + " blocks");
bestHeight[0] = nodeHeight;
} else if (diff < 0) {
System.out.println("Node is ahead by " + Math.abs(diff) + " blocks: " + addr);
bestHeight[0] = nodeHeight;
}
}
conn.close();
}
public void onFailure(Throwable throwable) {
System.out.println("Failed to talk to " + addr + ": " + throwable.getMessage());
}
});
}
pool.awaitTermination(3600 * 24, TimeUnit.SECONDS); // 1 Day
// Wait for every tried connection to finish.
Futures.successfulAsList(futures).get();
}
}