From 3a1218283846c44fbc06591aba97dc9089110178 Mon Sep 17 00:00:00 2001 From: zzz Date: Thu, 2 Apr 2009 20:33:54 +0000 Subject: [PATCH] Transport: - Maintain a router hash -> IP map in transport, to support additional IP checks (unused for now) - Catch error on pre-2.6 kernels - Some concurrent conversion - Fix an HTML error on peers.jsp --- .../transport/CommSystemFacadeImpl.java | 4 +++ .../i2p/router/transport/TransportImpl.java | 34 ++++++++++++------- .../router/transport/TransportManager.java | 15 +++++++- .../router/transport/ntcp/EstablishState.java | 6 +++- .../router/transport/ntcp/EventPumper.java | 11 +++--- .../router/transport/ntcp/NTCPTransport.java | 7 +++- .../transport/udp/EstablishmentManager.java | 2 ++ .../router/transport/udp/UDPTransport.java | 3 ++ 8 files changed, 62 insertions(+), 20 deletions(-) diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index c94178004..0eafb8fa9 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -133,6 +133,10 @@ public class CommSystemFacadeImpl extends CommSystemFacade { return _manager.wasUnreachable(dest); } + public byte[] getIP(Hash dest) { + return _manager.getIP(dest); + } + public List getMostRecentErrorMessages() { return _manager.getMostRecentErrorMessages(); } diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java index 04a2cde91..1dffde799 100644 --- a/router/java/src/net/i2p/router/transport/TransportImpl.java +++ b/router/java/src/net/i2p/router/transport/TransportImpl.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; import net.i2p.data.Hash; import net.i2p.data.RouterAddress; @@ -34,6 +35,7 @@ import net.i2p.router.OutNetMessage; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; +import net.i2p.util.ConcurrentHashSet; import net.i2p.util.Log; /** @@ -47,8 +49,10 @@ public abstract class TransportImpl implements Transport { private List _sendPool; protected RouterContext _context; /** map from routerIdentHash to timestamp (Long) that the peer was last unreachable */ - private Map _unreachableEntries; - private Set _wasUnreachableEntries; + private Map _unreachableEntries; + private Set _wasUnreachableEntries; + /** global router ident -> IP */ + private static Map _IPMap = new ConcurrentHashMap(128); /** * Initialize the new transport @@ -67,7 +71,7 @@ public abstract class TransportImpl implements Transport { _context.statManager().createRateStat("transport.expiredOnQueueLifetime", "How long a message that expires on our outbound queue is processed", "Transport", new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000l } ); _sendPool = new ArrayList(16); _unreachableEntries = new HashMap(16); - _wasUnreachableEntries = new HashSet(16); + _wasUnreachableEntries = new ConcurrentHashSet(16); _currentAddress = null; } @@ -483,10 +487,8 @@ public abstract class TransportImpl implements Transport { * This is NOT reset if the peer contacts us and it is never expired. */ public boolean wasUnreachable(Hash peer) { - synchronized (_wasUnreachableEntries) { - if (_wasUnreachableEntries.contains(peer)) - return true; - } + if (_wasUnreachableEntries.contains(peer)) + return true; RouterInfo ri = _context.netDb().lookupRouterInfoLocally(peer); if (ri == null) return false; @@ -496,16 +498,22 @@ public abstract class TransportImpl implements Transport { * Maintain the WasUnreachable list */ public void markWasUnreachable(Hash peer, boolean yes) { - synchronized (_wasUnreachableEntries) { - if (yes) - _wasUnreachableEntries.add(peer); - else - _wasUnreachableEntries.remove(peer); - } + if (yes) + _wasUnreachableEntries.add(peer); + else + _wasUnreachableEntries.remove(peer); if (_log.shouldLog(Log.WARN)) _log.warn(this.getStyle() + " setting wasUnreachable to " + yes + " for " + peer); } + public static void setIP(Hash peer, byte[] ip) { + _IPMap.put(peer, ip); + } + + public static byte[] getIP(Hash peer) { + return _IPMap.get(peer); + } + public static boolean isPubliclyRoutable(byte addr[]) { if (addr.length == 4) { if ((addr[0]&0xFF) == 127) return false; diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index bade75913..112f51efa 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -33,7 +33,7 @@ import net.i2p.util.Log; public class TransportManager implements TransportEventListener { private Log _log; - private List _transports; + private List _transports; private RouterContext _context; private final static String PROP_ENABLE_UDP = "i2np.udp.enable"; @@ -229,6 +229,19 @@ public class TransportManager implements TransportEventListener { return true; } + /** + * IP of the peer from the last connection (in or out, any transport). + * This may be different from that advertised in the netDb, + * as the peer may be hidden, or connect from a different IP, or + * change his netDb later, in an attempt to avoid restrictions. + * + * For blocking purposes, etc. it's worth checking both + * the netDb addresses and this address. + */ + public byte[] getIP(Hash dest) { + return TransportImpl.getIP(dest); + } + Map getAddresses() { Map rv = new HashMap(_transports.size()); for (int i = 0; i < _transports.size(); i++) { diff --git a/router/java/src/net/i2p/router/transport/ntcp/EstablishState.java b/router/java/src/net/i2p/router/transport/ntcp/EstablishState.java index d18cc1ad3..942d6cbc9 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/EstablishState.java +++ b/router/java/src/net/i2p/router/transport/ntcp/EstablishState.java @@ -472,6 +472,8 @@ public class EstablishState { byte nextReadIV[] = new byte[16]; System.arraycopy(_e_bobSig, _e_bobSig.length-16, nextReadIV, 0, nextReadIV.length); _con.finishOutboundEstablishment(_dh.getSessionKey(), (_tsA-_tsB), nextWriteIV, nextReadIV); // skew in seconds + _transport.setIP(_con.getRemotePeer().calculateHash(), + _con.getChannel().socket().getInetAddress().getAddress()); return; } } @@ -546,15 +548,17 @@ public class EstablishState { Signature sig = new Signature(s); _verified = _context.dsa().verifySignature(sig, toVerify, alice.getSigningPublicKey()); if (_verified) { + byte[] ip = _con.getChannel().socket().getInetAddress().getAddress(); if (_context.shitlist().isShitlistedForever(alice.calculateHash())) { if (_log.shouldLog(Log.WARN)) _log.warn("Dropping inbound connection from permanently shitlisted peer: " + alice.calculateHash().toBase64()); // So next time we will not accept the con from this IP, // rather than doing the whole handshake - _context.blocklist().add(_con.getChannel().socket().getInetAddress().getAddress()); + _context.blocklist().add(ip); fail("Peer is shitlisted forever: " + alice.calculateHash().toBase64()); return; } + _transport.setIP(alice.calculateHash(), ip); if (_log.shouldLog(Log.DEBUG)) _log.debug(prefix() + "verification successful for " + _con); diff --git a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java index 9c75f5328..0c062fa6c 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java +++ b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java @@ -66,22 +66,25 @@ public class EventPumper implements Runnable { public void startPumping() { if (_log.shouldLog(Log.INFO)) _log.info("Starting pumper"); - _alive = true; _wantsRead = new ArrayList(16); _wantsWrite = new ArrayList(4); _wantsRegister = new ArrayList(1); _wantsConRegister = new ArrayList(4); try { _selector = Selector.open(); + _alive = true; + new I2PThread(this, "NTCP Pumper", true).start(); } catch (IOException ioe) { - _log.error("Error opening the selector", ioe); + _log.log(Log.CRIT, "Error opening the NTCP selector", ioe); + } catch (java.lang.InternalError jlie) { + // "unable to get address of epoll functions, pre-2.6 kernel?" + _log.log(Log.CRIT, "Error opening the NTCP selector", jlie); } - new I2PThread(this, "NTCP Pumper", true).start(); } public void stopPumping() { _alive = false; - if (_selector.isOpen()) + if (_selector != null && _selector.isOpen()) _selector.wakeup(); } diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java index c23245bae..103b46b15 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java @@ -241,6 +241,8 @@ public class NTCPTransport extends TransportImpl { super.afterSend(msg, sendSuccessful, allowRequeue, msToSend); } public TransportBid bid(RouterInfo toAddress, long dataSize) { + if (!isAlive()) + return null; Hash peer = toAddress.getIdentity().calculateHash(); if (_context.shitlist().isShitlisted(peer, STYLE)) { // we aren't shitlisted in general (since we are trying to get a bid), but we have @@ -591,7 +593,10 @@ public class NTCPTransport extends TransportImpl { for (Iterator iter = peers.iterator(); iter.hasNext(); ) { NTCPConnection con = (NTCPConnection)iter.next(); String name = con.getRemotePeer().calculateHash().toBase64().substring(0,6); - buf.append("").append(name); + buf.append("").append(name).append(""); + //byte[] ip = getIP(con.getRemotePeer().calculateHash()); + //if (ip != null) + // buf.append(' ').append(_context.blocklist().toStr(ip)); buf.append(""); if (con.isInbound()) buf.append("in"); diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index 896fe1ce4..c5b654b90 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -450,6 +450,7 @@ public class EstablishmentManager { _transport.addRemotePeerState(peer); _transport.inboundConnectionReceived(); + _transport.setIP(remote.calculateHash(), state.getSentIP()); _context.statManager().addRateData("udp.inboundEstablishTime", state.getLifetime(), 0); sendInboundComplete(peer); @@ -531,6 +532,7 @@ public class EstablishmentManager { _transport.addRemotePeerState(peer); + _transport.setIP(remote.calculateHash(), state.getSentIP()); _context.statManager().addRateData("udp.outboundEstablishTime", state.getLifetime(), 0); sendOurInfo(peer, false); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index e5185defa..289e42ba3 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -1762,6 +1762,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority buf.append(" [shitlisted]"); appended = true; } + //byte[] ip = getIP(peer.getRemotePeer()); + //if (ip != null) + // buf.append(' ').append(_context.blocklist().toStr(ip)); buf.append(""); long idleIn = (now-peer.getLastReceiveTime())/1000;