diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index c0c272ae79db5a7384c7b957810f2c9665f71acc..ef194ac3f4516437cf17a516eff75e28b23d5768 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -14,11 +14,13 @@ import java.util.StringTokenizer; import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.I2PSession; +import net.i2p.client.I2PSessionException; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocketEepGet; import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManagerFactory; +import net.i2p.data.Base32; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; import net.i2p.data.Hash; @@ -341,21 +343,44 @@ public class I2PSnarkUtil { } } + private static final int BASE32_HASH_LENGTH = 52; // 1 + Hash.HASH_LENGTH * 8 / 5 + /** Base64 Hash or Hash.i2p or name.i2p using naming service */ Destination getDestination(String ip) { if (ip == null) return null; if (ip.endsWith(".i2p")) { if (ip.length() < 520) { // key + ".i2p" - Destination dest = _context.namingService().lookup(ip); - if (dest != null) - return dest; + if (_manager != null && ip.length() == BASE32_HASH_LENGTH + 8 && ip.endsWith(".b32.i2p")) { + // Use existing I2PSession for b32 lookups if we have it + // This is much more efficient than using the naming service + I2PSession sess = _manager.getSession(); + if (sess != null) { + byte[] b = Base32.decode(ip.substring(0, BASE32_HASH_LENGTH)); + if (b != null) { + Hash h = new Hash(b); + if (_log.shouldLog(Log.INFO)) + _log.info("Using existing session for lookup of " + ip); + try { + return sess.lookupDest(h); + } catch (I2PSessionException ise) { + } + } + } + } + if (_log.shouldLog(Log.INFO)) + _log.info("Using naming service for lookup of " + ip); + return _context.namingService().lookup(ip); } + if (_log.shouldLog(Log.INFO)) + _log.info("Creating Destination for " + ip); try { return new Destination(ip.substring(0, ip.length()-4)); // sans .i2p } catch (DataFormatException dfe) { return null; } } else { + if (_log.shouldLog(Log.INFO)) + _log.info("Creating Destination for " + ip); try { return new Destination(ip); } catch (DataFormatException dfe) { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java index 7cd2c8cb712f63e4d8a087d30e2e14d5b4ac5179..4ce5c5b99ac476dc09fc332c5e953deb5e918e56 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java @@ -2,8 +2,6 @@ package net.i2p.router.web; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; @@ -13,7 +11,7 @@ import java.util.TreeSet; import net.i2p.router.client.ClientManagerFacadeImpl; import net.i2p.router.startup.ClientAppConfig; -import net.i2p.router.transport.Addresses; +import net.i2p.util.Addresses; public class ConfigClientsHelper extends HelperBase { private String _edit; @@ -67,22 +65,8 @@ public class ConfigClientsHelper extends HelperBase { /** @since 0.8.3 */ public String[] intfcAddresses() { - String[] addrs = Addresses.getAllAddresses(); - List<String> aList = new ArrayList(); - aList.addAll(Arrays.asList(addrs)); - boolean ipv6 = false; - for (String a : aList) { - if (a.indexOf(':') >= 0) { - ipv6 = true; - break; - } - } - if (!aList.contains("0.0.0.0")) - aList.add("0.0.0.0"); - if (ipv6 && !aList.contains("0:0:0:0:0:0:0:0")) - aList.add("0:0:0:0:0:0:0:0"); // we could do "::" but all the other ones are probably in long form - Collections.sort(aList); - return aList.toArray(addrs); + ArrayList<String> al = new ArrayList(Addresses.getAllAddresses()); + return al.toArray(new String[al.size()]); } /** @since 0.8.3 */ diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java index 512b515938b01686ef2febd6ad31cf1b1e5c41c2..9388d06d2a45fc2ed5669b755d5f91e8ce9197fc 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -1,14 +1,16 @@ package net.i2p.router.web; +import java.util.ArrayList; + import net.i2p.data.DataHelper; import net.i2p.data.RouterAddress; import net.i2p.router.CommSystemFacade; import net.i2p.router.Router; -import net.i2p.router.transport.Addresses; import net.i2p.router.transport.TransportManager; import net.i2p.router.transport.udp.UDPAddress; import net.i2p.router.transport.udp.UDPTransport; import net.i2p.time.Timestamper; +import net.i2p.util.Addresses; public class ConfigNetHelper extends HelperBase { public ConfigNetHelper() {} @@ -147,7 +149,8 @@ public class ConfigNetHelper extends HelperBase { } public String[] getAddresses() { - return Addresses.getAddresses(); + ArrayList<String> al = new ArrayList(Addresses.getAddresses()); + return al.toArray(new String[al.size()]); } public String getInboundRate() { diff --git a/core/java/src/net/i2p/client/DestReplyMessageHandler.java b/core/java/src/net/i2p/client/DestReplyMessageHandler.java index 573389cfb2679475fd0f4cce1dccf674afb07323..8d5527d59b4e7d4c4d65f6687e702b920615f515 100644 --- a/core/java/src/net/i2p/client/DestReplyMessageHandler.java +++ b/core/java/src/net/i2p/client/DestReplyMessageHandler.java @@ -10,6 +10,9 @@ import net.i2p.data.i2cp.I2CPMessage; import net.i2p.data.i2cp.DestReplyMessage; import net.i2p.util.Log; +import net.i2p.data.Destination; +import net.i2p.data.Hash; + /** * Handle I2CP dest replies from the router */ @@ -22,6 +25,12 @@ class DestReplyMessageHandler extends HandlerImpl { if (_log.shouldLog(Log.DEBUG)) _log.debug("Handle message " + message); DestReplyMessage msg = (DestReplyMessage) message; - ((I2PSimpleSession)session).destReceived(msg.getDestination()); + Destination d = msg.getDestination(); + if (d != null) + session.destReceived(d); + Hash h = msg.getHash(); + if (h != null) + session.destLookupFailed(h); + // else let it time out } } diff --git a/core/java/src/net/i2p/client/I2PClientMessageHandlerMap.java b/core/java/src/net/i2p/client/I2PClientMessageHandlerMap.java index 6f0d950514db09e3187743e67d87b2c8006b5a5e..76350cbb219df7fc5c2a5e5dd30d6e4d361e006a 100644 --- a/core/java/src/net/i2p/client/I2PClientMessageHandlerMap.java +++ b/core/java/src/net/i2p/client/I2PClientMessageHandlerMap.java @@ -10,6 +10,8 @@ package net.i2p.client; */ import net.i2p.I2PAppContext; +import net.i2p.data.i2cp.BandwidthLimitsMessage; +import net.i2p.data.i2cp.DestReplyMessage; import net.i2p.data.i2cp.DisconnectMessage; import net.i2p.data.i2cp.MessagePayloadMessage; import net.i2p.data.i2cp.MessageStatusMessage; @@ -36,6 +38,8 @@ class I2PClientMessageHandlerMap { highest = Math.max(highest, MessagePayloadMessage.MESSAGE_TYPE); highest = Math.max(highest, MessageStatusMessage.MESSAGE_TYPE); highest = Math.max(highest, SetDateMessage.MESSAGE_TYPE); + highest = Math.max(highest, DestReplyMessage.MESSAGE_TYPE); + highest = Math.max(highest, BandwidthLimitsMessage.MESSAGE_TYPE); _handlers = new I2CPMessageHandler[highest+1]; _handlers[DisconnectMessage.MESSAGE_TYPE] = new DisconnectMessageHandler(context); @@ -44,6 +48,8 @@ class I2PClientMessageHandlerMap { _handlers[MessagePayloadMessage.MESSAGE_TYPE] = new MessagePayloadMessageHandler(context); _handlers[MessageStatusMessage.MESSAGE_TYPE] = new MessageStatusMessageHandler(context); _handlers[SetDateMessage.MESSAGE_TYPE] = new SetDateMessageHandler(context); + _handlers[DestReplyMessage.MESSAGE_TYPE] = new DestReplyMessageHandler(context); + _handlers[BandwidthLimitsMessage.MESSAGE_TYPE] = new BWLimitsMessageHandler(context); } public I2CPMessageHandler getHandler(int messageTypeId) { diff --git a/core/java/src/net/i2p/client/I2PSession.java b/core/java/src/net/i2p/client/I2PSession.java index 1998dad55a737a016d558e456ae2f632eff13e6c..cd20cfc2d655ef86580e18c1faaf248421d5e33d 100644 --- a/core/java/src/net/i2p/client/I2PSession.java +++ b/core/java/src/net/i2p/client/I2PSession.java @@ -138,13 +138,21 @@ public interface I2PSession { public SigningPrivateKey getPrivateKey(); /** - * Lookup up a Hash - * + * Lookup a Destination by Hash. + * Blocking. Waits a max of 10 seconds by default. */ public Destination lookupDest(Hash h) throws I2PSessionException; /** - * Get the current bandwidth limits + * Blocking. + * @param maxWait ms + * @since 0.8.3 + * @return null on failure + */ + public Destination lookupDest(Hash h, long maxWait) throws I2PSessionException; + + /** + * Get the current bandwidth limits. Blocking. */ public int[] bandwidthLimits() throws I2PSessionException; diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index 8090e0eaed88e65144a23f521edc75e650cd672b..e101ff7252c06a28601f94a07949b6a22b3ecddb 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -15,7 +15,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; -import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; @@ -23,6 +22,8 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; import net.i2p.I2PAppContext; import net.i2p.data.DataFormatException; @@ -33,6 +34,8 @@ import net.i2p.data.PrivateKey; import net.i2p.data.SessionKey; import net.i2p.data.SessionTag; import net.i2p.data.SigningPrivateKey; +import net.i2p.data.i2cp.DestLookupMessage; +import net.i2p.data.i2cp.GetBandwidthLimitsMessage; import net.i2p.data.i2cp.GetDateMessage; import net.i2p.data.i2cp.I2CPMessage; import net.i2p.data.i2cp.I2CPMessageException; @@ -95,6 +98,11 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa protected I2CPMessageProducer _producer; /** map of Long --> MessagePayloadMessage */ protected Map<Long, MessagePayloadMessage> _availableMessages; + + /** hashes of lookups we are waiting for */ + protected final LinkedBlockingQueue<LookupWaiter> _pendingLookups = new LinkedBlockingQueue(); + protected final Object _bwReceivedLock = new Object(); + protected int[] _bwLimits; protected I2PClientMessageHandlerMap _handlerMap; @@ -786,12 +794,104 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa return buf.toString(); } + /** called by the message handler */ + void destReceived(Destination d) { + Hash h = d.calculateHash(); + for (LookupWaiter w : _pendingLookups) { + if (w.hash.equals(h)) { + w.destination = d; + synchronized (w) { + w.notifyAll(); + } + } + } + } + + /** called by the message handler */ + void destLookupFailed(Hash h) { + for (LookupWaiter w : _pendingLookups) { + if (w.hash.equals(h)) { + synchronized (w) { + w.notifyAll(); + } + } + } + } + + /** called by the message handler */ + void bwReceived(int[] i) { + _bwLimits = i; + synchronized (_bwReceivedLock) { + _bwReceivedLock.notifyAll(); + } + } + + /** + * Simple object to wait for lookup replies + * @since 0.8.3 + */ + private static class LookupWaiter { + /** the request */ + public final Hash hash; + /** the reply */ + public Destination destination; + + public LookupWaiter(Hash h) { + this.hash = h; + } + } + + /** + * Blocking. Waits a max of 10 seconds by default. + * See lookupDest with maxWait parameter to change. + * Implemented in 0.8.3 in I2PSessionImpl; + * previously was available only in I2PSimpleSession. + * Multiple outstanding lookups are now allowed. + * @return null on failure + */ public Destination lookupDest(Hash h) throws I2PSessionException { - return null; + return lookupDest(h, 10*1000); + } + + /** + * Blocking. + * @param maxWait ms + * @since 0.8.3 + * @return null on failure + */ + public Destination lookupDest(Hash h, long maxWait) throws I2PSessionException { + if (_closed) + return null; + LookupWaiter waiter = new LookupWaiter(h); + _pendingLookups.offer(waiter); + sendMessage(new DestLookupMessage(h)); + try { + synchronized (waiter) { + waiter.wait(maxWait); + } + } catch (InterruptedException ie) {} + _pendingLookups.remove(waiter); + return waiter.destination; } + /** + * Blocking. Waits a max of 5 seconds. + * But shouldn't take long. + * Implemented in 0.8.3 in I2PSessionImpl; + * previously was available only in I2PSimpleSession. + * Multiple outstanding lookups are now allowed. + * @return null on failure + */ public int[] bandwidthLimits() throws I2PSessionException { - return null; + if (_closed) + return null; + sendMessage(new GetBandwidthLimitsMessage()); + try { + synchronized (_bwReceivedLock) { + _bwReceivedLock.wait(5*1000); + } + } catch (InterruptedException ie) {} + return _bwLimits; } protected void updateActivity() { diff --git a/core/java/src/net/i2p/client/I2PSimpleSession.java b/core/java/src/net/i2p/client/I2PSimpleSession.java index ed9ec5cc369e1a492bc4e0c80b0cb1d6c60f0b2b..e984b6d30712e00b93afd0d3542aac41f28634ef 100644 --- a/core/java/src/net/i2p/client/I2PSimpleSession.java +++ b/core/java/src/net/i2p/client/I2PSimpleSession.java @@ -33,12 +33,6 @@ import net.i2p.util.I2PAppThread; * @author zzz */ class I2PSimpleSession extends I2PSessionImpl2 { - private boolean _destReceived; - private /* FIXME final FIXME */ Object _destReceivedLock; - private Destination _destination; - private boolean _bwReceived; - private /* FIXME final FIXME */ Object _bwReceivedLock; - private int[] _bwLimits; /** * Create a new session for doing naming and bandwidth queries only. Do not create a destination. @@ -104,57 +98,6 @@ class I2PSimpleSession extends I2PSessionImpl2 { } } - /** called by the message handler */ - void destReceived(Destination d) { - _destReceived = true; - _destination = d; - synchronized (_destReceivedLock) { - _destReceivedLock.notifyAll(); - } - } - - void bwReceived(int[] i) { - _bwReceived = true; - _bwLimits = i; - synchronized (_bwReceivedLock) { - _bwReceivedLock.notifyAll(); - } - } - - @Override - public Destination lookupDest(Hash h) throws I2PSessionException { - if (_closed) - return null; - _destReceivedLock = new Object(); - sendMessage(new DestLookupMessage(h)); - for (int i = 0; i < 10 && !_destReceived; i++) { - try { - synchronized (_destReceivedLock) { - _destReceivedLock.wait(1000); - } - } catch (InterruptedException ie) {} - } - _destReceived = false; - return _destination; - } - - @Override - public int[] bandwidthLimits() throws I2PSessionException { - if (_closed) - return null; - _bwReceivedLock = new Object(); - sendMessage(new GetBandwidthLimitsMessage()); - for (int i = 0; i < 5 && !_bwReceived; i++) { - try { - synchronized (_bwReceivedLock) { - _bwReceivedLock.wait(1000); - } - } catch (InterruptedException ie) {} - } - _bwReceived = false; - return _bwLimits; - } - /** * Only map message handlers that we will use */ diff --git a/core/java/src/net/i2p/client/naming/LookupDest.java b/core/java/src/net/i2p/client/naming/LookupDest.java index c90b4a6738dc87ff1b87c83d057474ab2d6987cf..d131efade8ee02a3e2562ab0171efc080c1dc30b 100644 --- a/core/java/src/net/i2p/client/naming/LookupDest.java +++ b/core/java/src/net/i2p/client/naming/LookupDest.java @@ -22,6 +22,13 @@ import net.i2p.data.Hash; * * All calls are blocking and return null on failure. * Timeout is set to 10 seconds in I2PSimpleSession. + * + * As of 0.8.3, standard I2PSessions support lookups, + * including multiple lookups in parallel, and overriding + * the default timeout. + * Using an existing I2PSession is much more efficient and + * flexible than using this class. + * */ class LookupDest { diff --git a/core/java/src/net/i2p/data/i2cp/DestReplyMessage.java b/core/java/src/net/i2p/data/i2cp/DestReplyMessage.java index d3b2df9e10277c180147d23dbdade842408ef048..7aaba9c8923a83e70f33e71b4e91073bf4ae48eb 100644 --- a/core/java/src/net/i2p/data/i2cp/DestReplyMessage.java +++ b/core/java/src/net/i2p/data/i2cp/DestReplyMessage.java @@ -13,14 +13,18 @@ import java.io.InputStream; import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; import net.i2p.data.Destination; +import net.i2p.data.Hash; /** - * Response to DestLookupMessage - * + * Response to DestLookupMessage. + * As of 0.8.3, the response may include the hash from the request, indicating + * a failure for a specific request. + * Payload may be empty (failure), a Hash (failure), or a Destination. */ public class DestReplyMessage extends I2CPMessageImpl { public final static int MESSAGE_TYPE = 35; private Destination _dest; + private Hash _hash; public DestReplyMessage() { super(); @@ -30,23 +34,52 @@ public class DestReplyMessage extends I2CPMessageImpl { _dest = d; } + /** + * @param h non-null with non-null data + * @since 0.8.3 + */ + public DestReplyMessage(Hash h) { + _hash = h; + } + public Destination getDestination() { return _dest; } + /** + * @since 0.8.3 + */ + public Hash getHash() { + return _hash; + } + protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException { - try { - Destination d = new Destination(); - d.readBytes(in); - _dest = d; - } catch (DataFormatException dfe) { - _dest = null; // null dest allowed + if (size == 0) { + _dest = null; + _hash = null; + } else { + try { + if (size == Hash.HASH_LENGTH) { + Hash h = new Hash(); + h.readBytes(in); + _hash = h; + } else { + Destination d = new Destination(); + d.readBytes(in); + _dest = d; + } + } catch (DataFormatException dfe) { + _dest = null; + _hash = null; + } } } protected byte[] doWriteMessage() throws I2CPMessageException, IOException { - if (_dest == null) + if (_dest == null && _hash == null) return new byte[0]; // null response allowed + if (_dest == null && _hash != null) + return _hash.getData(); ByteArrayOutputStream os = new ByteArrayOutputStream(_dest.size()); try { _dest.writeBytes(os); @@ -65,7 +98,8 @@ public class DestReplyMessage extends I2CPMessageImpl { public boolean equals(Object object) { if ((object != null) && (object instanceof DestReplyMessage)) { DestReplyMessage msg = (DestReplyMessage) object; - return DataHelper.eq(getDestination(), msg.getDestination()); + return DataHelper.eq(getDestination(), msg.getDestination()) && + DataHelper.eq(getHash(), msg.getHash()); } return false; } @@ -75,6 +109,7 @@ public class DestReplyMessage extends I2CPMessageImpl { StringBuilder buf = new StringBuilder(); buf.append("[DestReplyMessage: "); buf.append("\n\tDestination: ").append(_dest); + buf.append("\n\tHash: ").append(_hash); buf.append("]"); return buf.toString(); } diff --git a/core/java/src/net/i2p/util/Addresses.java b/core/java/src/net/i2p/util/Addresses.java new file mode 100644 index 0000000000000000000000000000000000000000..3af5ea65a03ae710c5254a57a2800e4d63547212 --- /dev/null +++ b/core/java/src/net/i2p/util/Addresses.java @@ -0,0 +1,125 @@ +package net.i2p.util; + +/* + * public domain + */ + +import java.net.InetAddress; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + + +/** + * Get the local addresses + * + * @since 0.8.3 moved to core + * @author zzz + */ +public abstract class Addresses { + + /** @return the first non-local address it finds, or null */ + public static String getAnyAddress() { + SortedSet<String> a = getAddresses(); + if (!a.isEmpty()) + return a.first(); + return null; + } + + /** + * @return a sorted set of all addresses, excluding + * IPv6, local, broadcast, multicast, etc. + */ + public static SortedSet<String> getAddresses() { + return getAddresses(false, false); + } + + /** + * @return a sorted set of all addresses, excluding + * only link local and multicast + * @since 0.8.3 + */ + public static SortedSet<String> getAllAddresses() { + return getAddresses(true, true); + } + + /** + * @return a sorted array of all addresses + * @param whether to exclude IPV6 and local + * @return an array of all addresses + * @since 0.8.3 + */ + public static SortedSet<String> getAddresses(boolean includeLocal, boolean includeIPv6) { + SortedSet<String> rv = new TreeSet(); + try { + InetAddress localhost = InetAddress.getLocalHost(); + InetAddress[] allMyIps = InetAddress.getAllByName(localhost.getCanonicalHostName()); + if (allMyIps != null) { + for (int i = 0; i < allMyIps.length; i++) { + if (shouldInclude(allMyIps[i], includeLocal, includeIPv6)) + rv.add(allMyIps[i].getHostAddress()); + } + } + } catch (UnknownHostException e) {} + + try { + for(Enumeration<NetworkInterface> ifcs = NetworkInterface.getNetworkInterfaces(); ifcs.hasMoreElements();) { + NetworkInterface ifc = ifcs.nextElement(); + for(Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements();) { + InetAddress addr = addrs.nextElement(); + if (shouldInclude(addr, includeLocal, includeIPv6)) + rv.add(addr.getHostAddress()); + } + } + } catch (SocketException e) {} + + if (includeLocal) + rv.add("0.0.0.0"); + if (includeLocal && includeIPv6) { + boolean ipv6 = false; + for (String a : rv) { + if (a.indexOf(':') >= 0) { + ipv6 = true; + break; + } + } + if (ipv6) + rv.add("0:0:0:0:0:0:0:0"); // we could do "::" but all the other ones are probably in long form + } + return rv; + } + + private static boolean shouldInclude(InetAddress ia, boolean includeLocal, boolean includeIPv6) { + return + (!ia.isLinkLocalAddress()) && + (!ia.isMulticastAddress()) && + (includeLocal || + ((!ia.isAnyLocalAddress()) && + (!ia.isLoopbackAddress()) && + (!ia.isSiteLocalAddress()))) && + // Hamachi 5/8 allocated to RIPE (30 November 2010) + // Removed from TransportImpl.isPubliclyRoutable() + // Check moved to here, for now, but will eventually need to + // remove it from here also. + (includeLocal || + (!ia.getHostAddress().startsWith("5."))) && + (includeIPv6 || + (ia instanceof Inet4Address)); + } + + public static void main(String[] args) { + System.err.println("External Addresses:"); + Set<String> a = getAddresses(false, false); + for (String s : a) + System.err.println(s); + System.err.println("All addresses:"); + a = getAddresses(true, true); + for (String s : a) + System.err.println(s); + } +} diff --git a/router/java/src/net/i2p/router/transport/Addresses.java b/router/java/src/net/i2p/router/transport/Addresses.java deleted file mode 100644 index 5200e1173dfd5f375a721be86b1c989af50e4769..0000000000000000000000000000000000000000 --- a/router/java/src/net/i2p/router/transport/Addresses.java +++ /dev/null @@ -1,121 +0,0 @@ -package net.i2p.router.transport; - -/* - * public domain - */ - -import java.net.InetAddress; -import java.net.Inet4Address; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; - - -/** - * Get the local addresses - * - * @author zzz - */ -public class Addresses { - - /** @return the first non-local address it finds, or null */ - public static String getAnyAddress() { - String[] a = getAddresses(); - if (a.length > 0) - return a[0]; - return null; - } - - /** - * @return a sorted array of all addresses, excluding - * IPv6, local, broadcast, multicast, etc. - */ - public static String[] getAddresses() { - return getAddresses(false); - } - - /** - * @return a sorted array of all addresses, excluding - * only link local and multicast - * @since 0.8.3 - */ - public static String[] getAllAddresses() { - return getAddresses(true); - } - - /** - * @return a sorted array of all addresses - * @param whether to exclude IPV6 and local - * @return an array of all addresses - * @since 0.8.3 - */ - public static String[] getAddresses(boolean all) { - Set<String> rv = new HashSet(4); - try { - InetAddress localhost = InetAddress.getLocalHost(); - InetAddress[] allMyIps = InetAddress.getAllByName(localhost.getCanonicalHostName()); - if (allMyIps != null) { - for (int i = 0; i < allMyIps.length; i++) { - if (all) - addAll(rv, allMyIps[i]); - else - add(rv, allMyIps[i]); - } - } - } catch (UnknownHostException e) {} - - try { - for(Enumeration<NetworkInterface> ifcs = NetworkInterface.getNetworkInterfaces(); ifcs.hasMoreElements();) { - NetworkInterface ifc = ifcs.nextElement(); - for(Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements();) { - InetAddress addr = addrs.nextElement(); - if (all) - addAll(rv, addr); - else - add(rv, addr); - } - } - } catch (SocketException e) {} - - String[] rva = rv.toArray(new String[rv.size()]); - Arrays.sort(rva); - return rva; - } - - private static void add(Set<String> set, InetAddress ia) { - if (ia.isAnyLocalAddress() || - ia.isLinkLocalAddress() || - ia.isLoopbackAddress() || - ia.isMulticastAddress() || - ia.isSiteLocalAddress() || - // Hamachi 5/8 allocated to RIPE (30 November 2010) - // Removed from TransportImpl.isPubliclyRoutable() - // Check moved to here, for now, but will eventually need to - // remove it from here also. - ia.getHostAddress().startsWith("5.") || - !(ia instanceof Inet4Address)) { -// System.err.println("Skipping: " + ia.getHostAddress()); - return; - } - String ip = ia.getHostAddress(); - set.add(ip); - } - - private static void addAll(Set<String> set, InetAddress ia) { - if (ia.isLinkLocalAddress() || - ia.isMulticastAddress()) - return; - String ip = ia.getHostAddress(); - set.add(ip); - } - - public static void main(String[] args) { - String[] a = getAddresses(true); - for (String s : a) - System.err.println("Address: " + s); - } -} diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index cf21af11d9275b5ae750756487c4598c5e32184c..a682840b1780fa28749d2e0d52870fa4f36983eb 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -32,6 +32,7 @@ import net.i2p.router.OutNetMessage; import net.i2p.router.RouterContext; import net.i2p.router.transport.ntcp.NTCPTransport; import net.i2p.router.transport.udp.UDPTransport; +import net.i2p.util.Addresses; import net.i2p.util.Log; import net.i2p.util.Translate;