diff --git a/core/java/src/net/i2p/client/ClientWriterRunner.java b/core/java/src/net/i2p/client/ClientWriterRunner.java index ffb30f5e6..35ecce19d 100644 --- a/core/java/src/net/i2p/client/ClientWriterRunner.java +++ b/core/java/src/net/i2p/client/ClientWriterRunner.java @@ -33,7 +33,7 @@ class ClientWriterRunner implements Runnable { private static final long MAX_SEND_WAIT = 10*1000; /** - * As of 0.9.10 does not start the thread, caller must call startWriting() + * As of 0.9.11 does not start the thread, caller must call startWriting() */ public ClientWriterRunner(OutputStream out, I2PSessionImpl session) { _out = new BufferedOutputStream(out); @@ -42,7 +42,7 @@ class ClientWriterRunner implements Runnable { } /** - * @since 0.9.10 + * @since 0.9.11 */ public void startWriting() { Thread t = new I2PAppThread(this, "I2CP Client Writer " + __Id.incrementAndGet(), true); diff --git a/core/java/src/net/i2p/client/HostReplyMessageHandler.java b/core/java/src/net/i2p/client/HostReplyMessageHandler.java index 5b10637b8..94cce4758 100644 --- a/core/java/src/net/i2p/client/HostReplyMessageHandler.java +++ b/core/java/src/net/i2p/client/HostReplyMessageHandler.java @@ -15,7 +15,7 @@ import net.i2p.data.Destination; /** * Handle I2CP dest replies from the router * - * @since 0.9.10 + * @since 0.9.11 */ class HostReplyMessageHandler extends HandlerImpl { diff --git a/core/java/src/net/i2p/client/I2PSession.java b/core/java/src/net/i2p/client/I2PSession.java index ffad99ee1..d70e4041f 100644 --- a/core/java/src/net/i2p/client/I2PSession.java +++ b/core/java/src/net/i2p/client/I2PSession.java @@ -268,10 +268,10 @@ public interface I2PSession { * } * * - * Requires router side to be 0.9.10 or higher. If the router is older, + * Requires router side to be 0.9.11 or higher. If the router is older, * this will return null immediately. * - * @since 0.9.10 + * @since 0.9.11 */ public Destination lookupDest(String name) throws I2PSessionException; @@ -279,7 +279,7 @@ public interface I2PSession { * Ask the router to lookup a Destination by host name. * Blocking. See above for details. * @param maxWait ms - * @since 0.9.10 + * @since 0.9.11 * @return null on failure */ public Destination lookupDest(String name, long maxWait) throws I2PSessionException; diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index 7a23213b6..293bc9163 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -120,7 +120,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa */ protected enum State { OPENING, - /** @since 0.9.10 */ + /** @since 0.9.11 */ GOTDATE, OPEN, CLOSING, @@ -145,11 +145,11 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa private volatile boolean _routerSupportsHostLookup; /** - * Since 0.9.10, key is either a Hash or a String + * Since 0.9.11, key is either a Hash or a String * @since 0.8.9 */ private static final Map _lookupCache = new LHMCache(16); - private static final String MIN_HOST_LOOKUP_VERSION = "0.9.10"; + private static final String MIN_HOST_LOOKUP_VERSION = "0.9.11"; private static final boolean TEST_LOOKUP = false; /** SSL interface (only) @since 0.8.3 */ @@ -483,7 +483,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Before getDate"); Properties auth = null; if ((!_context.isRouterContext()) && _options.containsKey(PROP_USER) && _options.containsKey(PROP_PW)) { - // Only supported by routers 0.9.10 or higher, but we don't know the version yet. + // Only supported by routers 0.9.11 or higher, but we don't know the version yet. // Auth will also be sent in the SessionConfig. auth = new OrderedProperties(); auth.setProperty(PROP_USER, _options.getProperty(PROP_USER)); @@ -541,7 +541,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa } /** - * @since 0.9.10 moved from connect() + * @since 0.9.11 moved from connect() */ protected void waitForDate() throws InterruptedException, IOException { if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "After getDate / begin waiting for a response"); @@ -1040,7 +1040,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** * Called by the message handler * on reception of HostReplyMessage - * @since 0.9.10 + * @since 0.9.11 */ void destReceived(long nonce, Destination d) { // notify by hash @@ -1064,7 +1064,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** * Called by the message handler * on reception of HostReplyMessage - * @since 0.9.10 + * @since 0.9.11 */ void destLookupFailed(long nonce) { for (LookupWaiter w : _pendingLookups) { @@ -1102,14 +1102,14 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa this(h, -1); } - /** @since 0.9.10 */ + /** @since 0.9.11 */ public LookupWaiter(Hash h, long nonce) { this.hash = h; this.name = null; this.nonce = nonce; } - /** @since 0.9.10 */ + /** @since 0.9.11 */ public LookupWaiter(String name, long nonce) { this.hash = null; this.name = name; @@ -1160,7 +1160,10 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa if (_routerSupportsHostLookup) { if (_log.shouldLog(Log.INFO)) _log.info("Sending HostLookup for " + h); - sendMessage(new HostLookupMessage(h, nonce, maxWait)); + SessionId id = _sessionId; + if (id == null) + id = new SessionId(65535); + sendMessage(new HostLookupMessage(id, h, nonce, maxWait)); } else { if (_log.shouldLog(Log.INFO)) _log.info("Sending DestLookup for " + h); @@ -1192,10 +1195,10 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa * * See interface for suggested implementation. * - * Requires router side to be 0.9.10 or higher. If the router is older, + * Requires router side to be 0.9.11 or higher. If the router is older, * this will return null immediately. * - * @since 0.9.10 + * @since 0.9.11 */ public Destination lookupDest(String name) throws I2PSessionException { return lookupDest(name, 10*1000); @@ -1205,7 +1208,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa * Ask the router to lookup a Destination by host name. * Blocking. See above for details. * @param maxWait ms - * @since 0.9.10 + * @since 0.9.11 * @return null on failure */ public Destination lookupDest(String name, long maxWait) throws I2PSessionException { @@ -1247,7 +1250,10 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa try { if (_log.shouldLog(Log.INFO)) _log.info("Sending HostLookup for " + name); - sendMessage(new HostLookupMessage(name, nonce, maxWait)); + SessionId id = _sessionId; + if (id == null) + id = new SessionId(65535); + sendMessage(new HostLookupMessage(id, name, nonce, maxWait)); try { synchronized (waiter) { waiter.wait(maxWait); diff --git a/core/java/src/net/i2p/client/I2PSimpleSession.java b/core/java/src/net/i2p/client/I2PSimpleSession.java index 4737c4716..b6f8bb7eb 100644 --- a/core/java/src/net/i2p/client/I2PSimpleSession.java +++ b/core/java/src/net/i2p/client/I2PSimpleSession.java @@ -103,8 +103,8 @@ class I2PSimpleSession extends I2PSessionImpl2 { if (!_context.isRouterContext()) { Properties opts = getOptions(); // Send auth message if required - // Auth was not enforced on a simple session until 0.9.10 - // We will get disconnected for router version < 0.9.10 since it doesn't + // Auth was not enforced on a simple session until 0.9.11 + // We will get disconnected for router version < 0.9.11 since it doesn't // support the AuthMessage if ((!opts.containsKey(PROP_USER)) && (!opts.containsKey(PROP_PW))) { // auto-add auth if not set in the options diff --git a/core/java/src/net/i2p/data/i2cp/HostLookupMessage.java b/core/java/src/net/i2p/data/i2cp/HostLookupMessage.java index 0b87c8595..570858d5f 100644 --- a/core/java/src/net/i2p/data/i2cp/HostLookupMessage.java +++ b/core/java/src/net/i2p/data/i2cp/HostLookupMessage.java @@ -17,7 +17,7 @@ import net.i2p.data.Hash; * Request the router look up the dest for a hash * or a host. Replaces DestLookupMessage. * - * @since 0.9.10; do not send to routers older than 0.9.10. + * @since 0.9.11; do not send to routers older than 0.9.11. */ public class HostLookupMessage extends I2CPMessageImpl { public final static int MESSAGE_TYPE = 38; @@ -27,6 +27,7 @@ public class HostLookupMessage extends I2CPMessageImpl { private int _lookupType; private Hash _hash; private String _host; + private SessionId _sessionId; public static final int LOOKUP_HASH = 0; public static final int LOOKUP_HOST = 1; @@ -39,7 +40,9 @@ public class HostLookupMessage extends I2CPMessageImpl { * @param reqID 0 to 2**32 - 1 * @param timeout ms 1 to 2**32 - 1 */ - public HostLookupMessage(Hash h, long reqID, long timeout) { + public HostLookupMessage(SessionId id, Hash h, long reqID, long timeout) { + if (id == null || h == null) + throw new IllegalArgumentException(); if (reqID < 0 || reqID > MAX_INT) throw new IllegalArgumentException(); if (timeout <= 0 || timeout > MAX_INT) @@ -54,7 +57,9 @@ public class HostLookupMessage extends I2CPMessageImpl { * @param reqID 0 to 2**32 - 1 * @param timeout ms 1 to 2**32 - 1 */ - public HostLookupMessage(String host, long reqID, long timeout) { + public HostLookupMessage(SessionId id, String host, long reqID, long timeout) { + if (id == null || host == null) + throw new IllegalArgumentException(); if (reqID < 0 || reqID > MAX_INT) throw new IllegalArgumentException(); if (timeout <= 0 || timeout > MAX_INT) @@ -65,6 +70,10 @@ public class HostLookupMessage extends I2CPMessageImpl { _lookupType = LOOKUP_HOST; } + public SessionId getSessionId() { + return _sessionId; + } + /** * @return 0 to 2**32 - 1 */ @@ -102,6 +111,8 @@ public class HostLookupMessage extends I2CPMessageImpl { protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException { try { + _sessionId = new SessionId(); + _sessionId.readBytes(in); _reqID = DataHelper.readLong(in, 4); _timeout = DataHelper.readLong(in, 4); _lookupType = (int) DataHelper.readLong(in, 1); @@ -124,16 +135,17 @@ public class HostLookupMessage extends I2CPMessageImpl { if (_lookupType == LOOKUP_HASH) { if (_hash == null) throw new I2CPMessageException("Unable to write out the message as there is not enough data"); - len = 9 + Hash.HASH_LENGTH; + len = 11 + Hash.HASH_LENGTH; } else if (_lookupType == LOOKUP_HOST) { if (_host == null) throw new I2CPMessageException("Unable to write out the message as there is not enough data"); - len = 10 + _host.length(); + len = 12 + _host.length(); } else { throw new I2CPMessageException("bad type"); } ByteArrayOutputStream os = new ByteArrayOutputStream(len); try { + _sessionId.writeBytes(os); DataHelper.writeLong(os, 4, _reqID); DataHelper.writeLong(os, 4, _timeout); DataHelper.writeLong(os, 1, _lookupType); @@ -156,6 +168,7 @@ public class HostLookupMessage extends I2CPMessageImpl { public String toString() { StringBuilder buf = new StringBuilder(); buf.append("[HostLookupMessage: "); + buf.append("\n\t").append(_sessionId); buf.append("\n\tReqID: ").append(_reqID); buf.append("\n\tTimeout: ").append(_timeout); if (_lookupType == LOOKUP_HASH) diff --git a/core/java/src/net/i2p/data/i2cp/HostReplyMessage.java b/core/java/src/net/i2p/data/i2cp/HostReplyMessage.java index ce595e1f3..d4a8102e2 100644 --- a/core/java/src/net/i2p/data/i2cp/HostReplyMessage.java +++ b/core/java/src/net/i2p/data/i2cp/HostReplyMessage.java @@ -17,7 +17,7 @@ import net.i2p.data.Destination; /** * Response to HostLookupMessage. Replaces DestReplyMessage. * - * @since 0.9.10 + * @since 0.9.11 */ public class HostReplyMessage extends I2CPMessageImpl { public final static int MESSAGE_TYPE = 39; @@ -25,6 +25,7 @@ public class HostReplyMessage extends I2CPMessageImpl { private Destination _dest; private long _reqID; private int _code; + private SessionId _sessionId; public static final int RESULT_SUCCESS = 0; /** generic fail, other codes TBD */ @@ -40,8 +41,8 @@ public class HostReplyMessage extends I2CPMessageImpl { * @param d non-null * @param reqID 0 to 2**32 - 1 */ - public HostReplyMessage(Destination d, long reqID) { - if (d == null) + public HostReplyMessage(SessionId id, Destination d, long reqID) { + if (id == null || d == null) throw new IllegalArgumentException(); if (reqID < 0 || reqID > MAX_INT) throw new IllegalArgumentException(); @@ -55,7 +56,9 @@ public class HostReplyMessage extends I2CPMessageImpl { * @param failureCode 1-255 * @param reqID from the HostLookup 0 to 2**32 - 1 */ - public HostReplyMessage(int failureCode, long reqID) { + public HostReplyMessage(SessionId id, int failureCode, long reqID) { + if (id == null) + throw new IllegalArgumentException(); if (failureCode <= 0 || failureCode > 255) throw new IllegalArgumentException(); if (reqID < 0 || reqID > MAX_INT) @@ -64,6 +67,10 @@ public class HostReplyMessage extends I2CPMessageImpl { _reqID = reqID; } + public SessionId getSessionId() { + return _sessionId; + } + /** * @return 0 to 2**32 - 1 */ @@ -87,6 +94,8 @@ public class HostReplyMessage extends I2CPMessageImpl { protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException { try { + _sessionId = new SessionId(); + _sessionId.readBytes(in); _reqID = DataHelper.readLong(in, 4); _code = (int) DataHelper.readLong(in, 1); if (_code == RESULT_SUCCESS) @@ -97,7 +106,7 @@ public class HostReplyMessage extends I2CPMessageImpl { } protected byte[] doWriteMessage() throws I2CPMessageException, IOException { - int len = 5; + int len = 7; if (_code == RESULT_SUCCESS) { if (_dest == null) throw new I2CPMessageException("Unable to write out the message as there is not enough data"); @@ -105,6 +114,7 @@ public class HostReplyMessage extends I2CPMessageImpl { } ByteArrayOutputStream os = new ByteArrayOutputStream(len); try { + _sessionId.writeBytes(os); DataHelper.writeLong(os, 4, _reqID); DataHelper.writeLong(os, 1, _code); if (_code == RESULT_SUCCESS) @@ -123,6 +133,7 @@ public class HostReplyMessage extends I2CPMessageImpl { public String toString() { StringBuilder buf = new StringBuilder(); buf.append("[HostReplyMessage: "); + buf.append("\n\t").append(_sessionId); buf.append("\n\tReqID: ").append(_reqID); buf.append("\n\tCode: ").append(_code); if (_code == RESULT_SUCCESS) diff --git a/core/java/src/net/i2p/data/i2cp/SessionId.java b/core/java/src/net/i2p/data/i2cp/SessionId.java index 68f8c1a29..2cacd63fe 100644 --- a/core/java/src/net/i2p/data/i2cp/SessionId.java +++ b/core/java/src/net/i2p/data/i2cp/SessionId.java @@ -29,12 +29,24 @@ public class SessionId extends DataStructureImpl { _sessionId = -1; } + /** + * @param id 0-65535 + * @since 0.9.11 + */ + public SessionId(int id) { + if (id < 0 || id > 65535) + throw new IllegalArgumentException(); + _sessionId = id; + } + public int getSessionId() { return _sessionId; } /** @param id 0-65535 */ public void setSessionId(int id) { + if (id < 0 || id > 65535) + throw new IllegalArgumentException(); _sessionId = id; } diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index a3f4b6c9e..9518a2193 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -232,7 +232,7 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi * * @param props contains i2cp.username and i2cp.password, may be null * @return success - * @since 0.9.10 + * @since 0.9.11 */ private boolean checkAuth(Properties props) { if (_authorized) @@ -368,11 +368,12 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi /** * override for testing - * @since 0.9.10 + * @since 0.9.11 */ protected void handleHostLookup(HostLookupMessage message) { _context.jobQueue().addJob(new LookupDestJob(_context, _runner, message.getReqID(), - message.getTimeout(), message.getHash(), message.getHostname())); + message.getTimeout(), message.getSessionId(), + message.getHash(), message.getHostname())); } /** diff --git a/router/java/src/net/i2p/router/client/LookupDestJob.java b/router/java/src/net/i2p/router/client/LookupDestJob.java index eb177a2a8..d5ab08775 100644 --- a/router/java/src/net/i2p/router/client/LookupDestJob.java +++ b/router/java/src/net/i2p/router/client/LookupDestJob.java @@ -14,12 +14,13 @@ import net.i2p.data.i2cp.DestReplyMessage; import net.i2p.data.i2cp.HostReplyMessage; import net.i2p.data.i2cp.I2CPMessage; import net.i2p.data.i2cp.I2CPMessageException; +import net.i2p.data.i2cp.SessionId; import net.i2p.router.JobImpl; import net.i2p.router.RouterContext; /** * Look up the lease of a hash, to convert it to a Destination for the client. - * Or, since 0.9.10, lookup a host name in the naming service. + * Or, since 0.9.11, lookup a host name in the naming service. */ class LookupDestJob extends JobImpl { private final ClientConnectionRunner _runner; @@ -27,28 +28,32 @@ class LookupDestJob extends JobImpl { private final long _timeout; private final Hash _hash; private final String _name; + private final SessionId _sessID; private static final long DEFAULT_TIMEOUT = 15*1000; public LookupDestJob(RouterContext context, ClientConnectionRunner runner, Hash h) { - this(context, runner, -1, DEFAULT_TIMEOUT, h, null); + this(context, runner, -1, DEFAULT_TIMEOUT, null, h, null); } /** * One of h or name non-null * @param reqID must be >= 0 if name != null - * @since 0.9.10 + * @param sessID must non-null if reqID >= 0 + * @since 0.9.11 */ public LookupDestJob(RouterContext context, ClientConnectionRunner runner, - long reqID, long timeout, Hash h, String name) { + long reqID, long timeout, SessionId sessID, Hash h, String name) { super(context); if ((h == null && name == null) || (h != null && name != null) || + (reqID >= 0 && sessID == null) || (reqID < 0 && name != null)) throw new IllegalArgumentException(); _runner = runner; _reqID = reqID; _timeout = timeout; + _sessID = sessID; if (name != null && name.length() == 60) { // convert a b32 lookup to a hash lookup String nlc = name.toLowerCase(Locale.US); @@ -100,7 +105,7 @@ class LookupDestJob extends JobImpl { private void returnDest(Destination d) { I2CPMessage msg; if (_reqID >= 0) - msg = new HostReplyMessage(d, _reqID); + msg = new HostReplyMessage(_sessID, d, _reqID); else msg = new DestReplyMessage(d); try { @@ -115,7 +120,7 @@ class LookupDestJob extends JobImpl { private void returnFail() { I2CPMessage msg; if (_reqID >= 0) - msg = new HostReplyMessage(HostReplyMessage.RESULT_FAILURE, _reqID); + msg = new HostReplyMessage(_sessID, HostReplyMessage.RESULT_FAILURE, _reqID); else msg = new DestReplyMessage(_hash); try {