3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 06:44:16 +00:00

Change NetworkConnection API to separate connect method.

This allows the Peer to close the connection earlier when connect()
takes a long time.

Resolves issue 161.
This commit is contained in:
Miron Cuperman 2012-03-26 15:23:14 -07:00
parent 92398d2c47
commit 9474eaa0d4
6 changed files with 58 additions and 30 deletions

View File

@ -32,6 +32,15 @@ import java.io.IOException;
*/ */
public interface NetworkConnection { public interface NetworkConnection {
/** /**
* Connect to the remote peer.
*
* @param peerAddress the address of the remote peer
* @param connectTimeoutMsec timeout in milliseconds
*/
public void connect(PeerAddress peerAddress, int connectTimeoutMsec)
throws IOException, ProtocolException;
/**
* Sends a "ping" message to the remote node. The protocol doesn't presently use this feature much. * Sends a "ping" message to the remote node. The protocol doesn't presently use this feature much.
* *
* @throws IOException * @throws IOException

View File

@ -154,7 +154,8 @@ public class Peer {
*/ */
public synchronized void connect() throws PeerException { public synchronized void connect() throws PeerException {
try { try {
conn = new TCPNetworkConnection(address, params, CONNECT_TIMEOUT_MSEC, false, versionMessage); conn = new TCPNetworkConnection(params, false, versionMessage);
conn.connect(address, CONNECT_TIMEOUT_MSEC);
} catch (IOException ex) { } catch (IOException ex) {
throw new PeerException(ex); throw new PeerException(ex);
} catch (ProtocolException ex) { } catch (ProtocolException ex) {

View File

@ -40,16 +40,18 @@ public class TCPNetworkConnection implements NetworkConnection {
private static final Logger log = LoggerFactory.getLogger(TCPNetworkConnection.class); private static final Logger log = LoggerFactory.getLogger(TCPNetworkConnection.class);
private final Socket socket; private final Socket socket;
private final OutputStream out; private OutputStream out;
private final InputStream in; private InputStream in;
// The IP address to which we are connecting. // The IP address to which we are connecting.
private final InetAddress remoteIp; private InetAddress remoteIp;
private final NetworkParameters params; private final NetworkParameters params;
private final VersionMessage versionMessage; private VersionMessage versionMessage;
// Given to the BitcoinSerializer to de-duplicate messages. // Given to the BitcoinSerializer to de-duplicate messages.
private static final LinkedHashMap<Sha256Hash, Integer> dedupeList = BitcoinSerializer.createDedupeList(); private static final LinkedHashMap<Sha256Hash, Integer> dedupeList = BitcoinSerializer.createDedupeList();
private BitcoinSerializer serializer = null; private BitcoinSerializer serializer = null;
private VersionMessage myVersionMessage;
private static final Date checksummingProtocolChangeDate = new Date(1329696000000L); private static final Date checksummingProtocolChangeDate = new Date(1329696000000L);
/** /**
@ -65,30 +67,35 @@ public class TCPNetworkConnection implements NetworkConnection {
* @throws IOException if there is a network related failure. * @throws IOException if there is a network related failure.
* @throws ProtocolException if the version negotiation failed. * @throws ProtocolException if the version negotiation failed.
*/ */
public TCPNetworkConnection(PeerAddress peerAddress, NetworkParameters params, public TCPNetworkConnection(NetworkParameters params, boolean dedupe, VersionMessage ver)
int connectTimeoutMsec, boolean dedupe, VersionMessage ver)
throws IOException, ProtocolException { throws IOException, ProtocolException {
this.params = params; this.params = params;
this.remoteIp = peerAddress.getAddr(); this.myVersionMessage = ver;
int port = (peerAddress.getPort() > 0) ? peerAddress.getPort() : params.port; socket = new Socket();
// So pre-Feb 2012, update checkumming property after version is read.
this.serializer = new BitcoinSerializer(this.params, false, dedupe ? dedupeList : null);
this.serializer.setUseChecksumming(Utils.now().after(checksummingProtocolChangeDate));
}
public void connect(PeerAddress peerAddress, int connectTimeoutMsec)
throws IOException, ProtocolException {
remoteIp = peerAddress.getAddr();
int port = (peerAddress.getPort() > 0) ? peerAddress.getPort() : this.params.port;
InetSocketAddress address = new InetSocketAddress(remoteIp, port); InetSocketAddress address = new InetSocketAddress(remoteIp, port);
socket = new Socket();
socket.connect(address, connectTimeoutMsec); socket.connect(address, connectTimeoutMsec);
out = socket.getOutputStream(); out = socket.getOutputStream();
in = socket.getInputStream(); in = socket.getInputStream();
// The version message does not use checksumming, until Feb 2012 when it magically does. // The version message does not use checksumming, until Feb 2012 when it magically does.
// So pre-Feb 2012, update checkumming property after version is read.
this.serializer = new BitcoinSerializer(params, false, dedupe ? dedupeList : null);
this.serializer.setUseChecksumming(Utils.now().after(checksummingProtocolChangeDate));
// Announce ourselves. This has to come first to connect to clients beyond v0.30.20.2 which wait to hear // Announce ourselves. This has to come first to connect to clients beyond v0.30.20.2 which wait to hear
// from us until they send their version message back. // from us until they send their version message back.
log.info("Announcing ourselves as: {}", ver.subVer); log.info("Announcing ourselves as: {}", myVersionMessage.subVer);
writeMessage(ver); writeMessage(myVersionMessage);
// When connecting, the remote peer sends us a version message with various bits of // When connecting, the remote peer sends us a version message with various bits of
// useful data in it. We need to know the peer protocol version before we can talk to it. // useful data in it. We need to know the peer protocol version before we can talk to it.
Message m = readMessage(); Message m = readMessage();
@ -140,15 +147,15 @@ public class TCPNetworkConnection implements NetworkConnection {
* @throws IOException if there is a network related failure. * @throws IOException if there is a network related failure.
* @throws ProtocolException if the version negotiation failed. * @throws ProtocolException if the version negotiation failed.
*/ */
public TCPNetworkConnection(PeerAddress peerAddress, NetworkParameters params, public TCPNetworkConnection(NetworkParameters params,
int bestHeight, int connectTimeoutMsec, boolean dedupe) int bestHeight, boolean dedupe)
throws IOException, ProtocolException { throws IOException, ProtocolException {
this(peerAddress, params, connectTimeoutMsec, dedupe, new VersionMessage(params, bestHeight)); this(params, dedupe, new VersionMessage(params, bestHeight));
} }
public TCPNetworkConnection(InetAddress inetAddress, NetworkParameters params, int bestHeight, int connectTimeout) public TCPNetworkConnection(NetworkParameters params, int bestHeight)
throws IOException, ProtocolException { throws IOException, ProtocolException {
this(new PeerAddress(inetAddress), params, bestHeight, connectTimeout, true); this(params, bestHeight, true);
} }

View File

@ -37,13 +37,13 @@ public class MockNetworkConnection implements NetworkConnection {
private PeerAddress peerAddress; private PeerAddress peerAddress;
public MockNetworkConnection() { public MockNetworkConnection() {
}
public void connect(PeerAddress peerAddress, int connectTimeoutMsec) {
inboundMessageQ = new ArrayBlockingQueue<Object>(10); inboundMessageQ = new ArrayBlockingQueue<Object>(10);
outboundMessageQ = new ArrayBlockingQueue<Message>(10); outboundMessageQ = new ArrayBlockingQueue<Message>(10);
try { this.peerAddress = peerAddress;
peerAddress = new PeerAddress(InetAddress.getLocalHost(), fakePort++);
} catch (UnknownHostException e) {
throw new RuntimeException(e); // Cannot happen.
}
} }
public void ping() throws IOException { public void ping() throws IOException {

View File

@ -21,6 +21,8 @@ import com.google.bitcoin.utils.BriefLogFormatter;
import org.easymock.IMocksControl; import org.easymock.IMocksControl;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import static org.easymock.EasyMock.createStrictControl; import static org.easymock.EasyMock.createStrictControl;
@ -35,6 +37,7 @@ public class TestWithNetworkConnections {
protected Wallet wallet; protected Wallet wallet;
protected ECKey key; protected ECKey key;
protected Address address; protected Address address;
private static int fakePort;
public void setUp() throws Exception { public void setUp() throws Exception {
BriefLogFormatter.init(); BriefLogFormatter.init();
@ -52,7 +55,13 @@ public class TestWithNetworkConnections {
} }
protected MockNetworkConnection createMockNetworkConnection() { protected MockNetworkConnection createMockNetworkConnection() {
return new MockNetworkConnection(); MockNetworkConnection conn = new MockNetworkConnection();
try {
conn.connect(new PeerAddress(InetAddress.getLocalHost(), fakePort++), 0);
} catch (UnknownHostException e) {
throw new RuntimeException(e); // Cannot happen
}
return conn;
} }
protected void runPeer(Peer peer, MockNetworkConnection connection) throws IOException, PeerException { protected void runPeer(Peer peer, MockNetworkConnection connection) throws IOException, PeerException {
@ -65,7 +74,7 @@ public class TestWithNetworkConnections {
} }
} }
protected void runPeerAsync(final Peer peer, MockNetworkConnection connection) throws IOException, PeerException { protected void runPeerAsync(final Peer peer, MockNetworkConnection connection) {
new Thread("Test Peer Thread") { new Thread("Test Peer Thread") {
@Override @Override
public void run() { public void run() {

View File

@ -18,6 +18,7 @@ package com.google.bitcoin.examples;
import com.google.bitcoin.core.NetworkConnection; import com.google.bitcoin.core.NetworkConnection;
import com.google.bitcoin.core.NetworkParameters; import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.PeerAddress;
import com.google.bitcoin.core.TCPNetworkConnection; import com.google.bitcoin.core.TCPNetworkConnection;
import com.google.bitcoin.discovery.DnsDiscovery; import com.google.bitcoin.discovery.DnsDiscovery;
import com.google.bitcoin.discovery.IrcDiscovery; import com.google.bitcoin.discovery.IrcDiscovery;
@ -94,8 +95,9 @@ public class PrintPeers {
pool.submit(new Runnable() { pool.submit(new Runnable() {
public void run() { public void run() {
try { try {
NetworkConnection conn = new TCPNetworkConnection(addr, NetworkConnection conn =
NetworkParameters.prodNet(), 0, 1000); new TCPNetworkConnection(NetworkParameters.prodNet(), 0);
conn.connect(new PeerAddress(addr), 1000);
synchronized (lock) { synchronized (lock) {
long nodeHeight = conn.getVersionMessage().bestHeight; long nodeHeight = conn.getVersionMessage().bestHeight;
long diff = bestHeight[0] - nodeHeight; long diff = bestHeight[0] - nodeHeight;