mirror of
https://github.com/i2p/i2p.i2p.git
synced 2026-10-22 15:22:39 +00:00
I2CP, SAM: Support lookup of ls2 options (proposal 167)
This commit is contained in:
18 files changed
+548
-101
No files matched your search
@@ -423,7 +423,7 @@ public interface I2PSession {
|
||||
public LookupResult lookupDest2(String name, long maxWait) throws I2PSessionException;
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hostname.
|
||||
* Lookup a Destination by hash.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
@@ -436,7 +436,7 @@ public interface I2PSession {
|
||||
public LookupResult lookupDest(Hash h, long maxWait, LookupCallback callback) throws I2PSessionException;
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hash.
|
||||
* Lookup a Destination by hostname.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
@@ -448,6 +448,46 @@ public interface I2PSession {
|
||||
*/
|
||||
public LookupResult lookupDest(String name, long maxWait, LookupCallback callback) throws I2PSessionException;
|
||||
|
||||
/**
|
||||
* Ask the router to lookup a Destination by hostname.
|
||||
* Blocking. See above for details.
|
||||
* Same as lookupDest() but with a failure code in the return value
|
||||
*
|
||||
* @param maxWait ms
|
||||
* @param withOptions see proposal 167
|
||||
* @return non-null
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public LookupResult lookupDest2(String name, long maxWait, boolean withOptions) throws I2PSessionException;
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hash.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
*
|
||||
* @param maxWait ms
|
||||
* @param callback to return the result, non-null
|
||||
* @param withOptions see proposal 167
|
||||
* @return non-null. If result code is RESULT_DEFERRED, callback will be called later
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public LookupResult lookupDest(Hash h, long maxWait, LookupCallback callback, boolean withOptions) throws I2PSessionException;
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hostname.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
*
|
||||
* @param maxWait ms
|
||||
* @param callback to return the result, non-null
|
||||
* @param withOptions see proposal 167
|
||||
* @return non-null. If result code is RESULT_DEFERRED, callback will be called later
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public LookupResult lookupDest(String name, long maxWait, LookupCallback callback, boolean withOptions) throws I2PSessionException;
|
||||
|
||||
/**
|
||||
* Pass updated options to the router.
|
||||
* Does not remove properties previously present but missing from this options parameter.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.i2p.client;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.i2cp.HostReplyMessage;
|
||||
|
||||
@@ -40,6 +42,18 @@ public interface LookupResult {
|
||||
*/
|
||||
public static final int RESULT_DECRYPTION_FAILURE = HostReplyMessage.RESULT_DECRYPTION_FAILURE;
|
||||
|
||||
/**
|
||||
* See proposal 167
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public static final int RESULT_LEASESET_LOOKUP_FAILURE = HostReplyMessage.RESULT_LEASESET_LOOKUP_FAILURE;
|
||||
|
||||
/**
|
||||
* See proposal 167
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public static final int RESULT_LOOKUP_TYPE_UNSUPPORTED = HostReplyMessage.RESULT_LOOKUP_TYPE_UNSUPPORTED;
|
||||
|
||||
/**
|
||||
* For async calls only. Nonce will be non-zero and destination will be null.
|
||||
* Callback will be called later with the final result and the same nonce.
|
||||
@@ -58,6 +72,13 @@ public interface LookupResult {
|
||||
*/
|
||||
public Destination getDestination();
|
||||
|
||||
/**
|
||||
* See proposal 167
|
||||
* @return options from leaseset or null
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public Properties getOptions();
|
||||
|
||||
/**
|
||||
* For async calls only. Nonce will be non-zero.
|
||||
* Callback will be called later with the final result and the same nonce.
|
||||
|
||||
@@ -30,7 +30,7 @@ class HostReplyMessageHandler extends HandlerImpl {
|
||||
Destination d = msg.getDestination();
|
||||
long id = msg.getReqID();
|
||||
if (d != null) {
|
||||
session.destReceived(id, d);
|
||||
session.destReceived(id, d, msg.getOptions());
|
||||
} else {
|
||||
session.destLookupFailed(id, msg.getResultCode());
|
||||
}
|
||||
|
||||
@@ -206,6 +206,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
private volatile boolean _routerSupportsHostLookup;
|
||||
private volatile boolean _routerSupportsLS2;
|
||||
private volatile boolean _routerSupportsBlindingInfo;
|
||||
private volatile boolean _routerSupportsLookupOptions;
|
||||
|
||||
protected static final int CACHE_MAX_SIZE = SystemVersion.isAndroid() ? 32 : 128;
|
||||
/**
|
||||
@@ -230,6 +231,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
private static final String MIN_FAST_VERSION = "0.9.4";
|
||||
private static final String MIN_LS2_VERSION = "0.9.38";
|
||||
private static final String MIN_BLINDINFO_VERSION = "0.9.43";
|
||||
private static final String MIN_LOOKUP_OPTIONS_VERSION = "0.9.70";
|
||||
|
||||
/** @param routerVersion as rcvd in the SetDateMessage, may be null for very old routers */
|
||||
void dateUpdated(String routerVersion) {
|
||||
@@ -250,6 +252,9 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
_routerSupportsBlindingInfo = isrc ||
|
||||
(routerVersion != null && routerVersion.length() > 0 &&
|
||||
VersionComparator.comp(routerVersion, MIN_BLINDINFO_VERSION) >= 0);
|
||||
_routerSupportsLookupOptions = isrc ||
|
||||
(routerVersion != null && routerVersion.length() > 0 &&
|
||||
VersionComparator.comp(routerVersion, MIN_LOOKUP_OPTIONS_VERSION) >= 0);
|
||||
synchronized (_stateLock) {
|
||||
if (_state == State.OPENING) {
|
||||
changeState(State.GOTDATE);
|
||||
@@ -327,6 +332,8 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
_routerSupportsHostLookup = isrc;
|
||||
_routerSupportsSubsessions = isrc;
|
||||
_routerSupportsLS2 = isrc;
|
||||
_routerSupportsBlindingInfo = isrc;
|
||||
_routerSupportsLookupOptions = isrc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1611,7 +1618,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @param d non-null
|
||||
* @since 0.9.11
|
||||
*/
|
||||
void destReceived(long nonce, Destination d) {
|
||||
void destReceived(long nonce, Destination d, Properties opts) {
|
||||
// notify by nonce and hash
|
||||
Hash h = d.calculateHash();
|
||||
for (LookupWaiter w : _pendingLookups) {
|
||||
@@ -1623,13 +1630,14 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
}
|
||||
if (w.callback != null) {
|
||||
// asynch
|
||||
LkupResult result = new LkupResult(LookupResult.RESULT_SUCCESS, d, (int) w.nonce);
|
||||
LkupResult result = new LkupResult(LookupResult.RESULT_SUCCESS, d, (int) w.nonce, opts);
|
||||
w.callback.complete(result);
|
||||
} else {
|
||||
// synch
|
||||
synchronized (w) {
|
||||
w.destination = d;
|
||||
w.code = LookupResult.RESULT_SUCCESS;
|
||||
w.options = opts;
|
||||
w.notifyAll();
|
||||
}
|
||||
}
|
||||
@@ -1691,6 +1699,11 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public final LookupCallback callback;
|
||||
/**
|
||||
* the leaseset options, see proposal 167
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public Properties options;
|
||||
|
||||
public LookupWaiter(Hash h) {
|
||||
this(h, -1);
|
||||
@@ -1847,7 +1860,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @return null on failure
|
||||
*/
|
||||
public Destination lookupDest(String name, long maxWait) throws I2PSessionException {
|
||||
LookupWaiter waiter = x_lookupDest(name, maxWait);
|
||||
LookupWaiter waiter = x_lookupDest(name, maxWait, false);
|
||||
if (waiter == null)
|
||||
return null;
|
||||
synchronized(waiter) {
|
||||
@@ -1865,7 +1878,21 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @return non-null
|
||||
*/
|
||||
public LookupResult lookupDest2(String name, long maxWait) throws I2PSessionException {
|
||||
LookupWaiter waiter = x_lookupDest(name, maxWait);
|
||||
return lookupDest2(name, maxWait, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the router to lookup a Destination by hostname.
|
||||
* Blocking. See above for details.
|
||||
* Same as lookupDest() but with a failure code in the return value
|
||||
*
|
||||
* @param maxWait ms
|
||||
* @param withOptions see proposal 167
|
||||
* @return non-null
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public LookupResult lookupDest2(String name, long maxWait, boolean withOptions) throws I2PSessionException {
|
||||
LookupWaiter waiter = x_lookupDest(name, maxWait, withOptions);
|
||||
if (waiter == null)
|
||||
return LOOKUP_FAILURE;
|
||||
synchronized(waiter) {
|
||||
@@ -1873,6 +1900,8 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
Destination d = waiter.destination;
|
||||
if (d == null && code == LookupResult.RESULT_SUCCESS)
|
||||
code = LookupResult.RESULT_FAILURE;
|
||||
if (withOptions && code == LookupResult.RESULT_SUCCESS)
|
||||
return new LkupResult(code, d, 0, waiter.options);
|
||||
return new LkupResult(code, d);
|
||||
}
|
||||
}
|
||||
@@ -1884,7 +1913,12 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @since 0.9.11
|
||||
* @return null on failure
|
||||
*/
|
||||
private LookupWaiter x_lookupDest(String name, long maxWait) throws I2PSessionException {
|
||||
private LookupWaiter x_lookupDest(String name, long maxWait, boolean withOptions) throws I2PSessionException {
|
||||
if (!_routerSupportsLookupOptions) {
|
||||
withOptions = false;
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Lookup with options not supported by router");
|
||||
}
|
||||
if (name.length() == 0)
|
||||
return null;
|
||||
// Shortcut for b64
|
||||
@@ -1898,10 +1932,13 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
// won't fit in Mapping
|
||||
if (name.length() >= 256 && !_context.isRouterContext())
|
||||
return null;
|
||||
synchronized (_lookupCache) {
|
||||
Destination rv = _lookupCache.get(name);
|
||||
if (rv != null)
|
||||
return new LookupWaiter(rv);
|
||||
// if options are requested, we need to ask the router
|
||||
if (!withOptions) {
|
||||
synchronized (_lookupCache) {
|
||||
Destination rv = _lookupCache.get(name);
|
||||
if (rv != null)
|
||||
return new LookupWaiter(rv);
|
||||
}
|
||||
}
|
||||
if (isClosed()) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
@@ -1910,8 +1947,48 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
}
|
||||
if (!_routerSupportsHostLookup) {
|
||||
// do them a favor and convert to Hash lookup
|
||||
if (name.length() == 60 && name.toLowerCase(Locale.US).endsWith(".b32.i2p"))
|
||||
return new LookupWaiter(lookupDest(Hash.create(Base32.decode(name.toLowerCase(Locale.US).substring(0, 52))), maxWait));
|
||||
if (name.length() == 60 && name.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
||||
Hash h = Hash.create(Base32.decode(name.toLowerCase(Locale.US).substring(0, 52)));
|
||||
if (withOptions) {
|
||||
// we only have an async call for hash-with-options
|
||||
LkupCallback cb = new LkupCallback();
|
||||
LookupResult res = lookupDest(h, maxWait, cb, true);
|
||||
LookupWaiter rv = new LookupWaiter((Destination) null);
|
||||
int code = res.getResultCode();
|
||||
if (code == LookupResult.RESULT_SUCCESS) {
|
||||
rv.destination = res.getDestination();
|
||||
rv.options = res.getOptions();
|
||||
rv.code = code;
|
||||
return rv;
|
||||
}
|
||||
if (code != LookupResult.RESULT_DEFERRED) {
|
||||
// immediate failure
|
||||
rv.code = code;
|
||||
return rv;
|
||||
}
|
||||
// blocking, sit and wait for it
|
||||
synchronized(cb) {
|
||||
try { cb.wait(maxWait); } catch (InterruptedException ie) {}
|
||||
res = cb.getResult();
|
||||
}
|
||||
if (res == null) {
|
||||
// timeout
|
||||
rv.code = LookupResult.RESULT_FAILURE;
|
||||
return rv;
|
||||
}
|
||||
code = res.getResultCode();
|
||||
if (code == LookupResult.RESULT_SUCCESS) {
|
||||
rv.destination = res.getDestination();
|
||||
rv.options = res.getOptions();
|
||||
rv.code = code;
|
||||
return rv;
|
||||
}
|
||||
// failure
|
||||
rv.code = code;
|
||||
return rv;
|
||||
}
|
||||
return new LookupWaiter(lookupDest(h, maxWait));
|
||||
}
|
||||
// else unsupported
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Router does not support HostLookup for " + name);
|
||||
@@ -1926,7 +2003,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
SessionId id = _sessionId;
|
||||
if (id == null)
|
||||
id = DUMMY_SESSION;
|
||||
sendMessage_unchecked(new HostLookupMessage(id, name, nonce, maxWait));
|
||||
sendMessage_unchecked(new HostLookupMessage(id, name, nonce, maxWait, withOptions));
|
||||
try {
|
||||
synchronized (waiter) {
|
||||
waiter.wait(maxWait);
|
||||
@@ -1941,7 +2018,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hostname.
|
||||
* Lookup a Destination by hash.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
@@ -1952,10 +2029,34 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public LookupResult lookupDest(Hash h, long maxWait, LookupCallback callback) throws I2PSessionException {
|
||||
synchronized (_lookupCache) {
|
||||
Destination rv = _lookupCache.get(h);
|
||||
if (rv != null)
|
||||
return new LkupResult(LookupResult.RESULT_SUCCESS, rv);
|
||||
return lookupDest(h, maxWait, callback, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hash.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
*
|
||||
* @param maxWait ms
|
||||
* @param callback to return the result, non-null
|
||||
* @param withOptions see proposal 167
|
||||
* @return non-null. If result code is RESULT_DEFERRED, callback will be called later
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public LookupResult lookupDest(Hash h, long maxWait, LookupCallback callback, boolean withOptions) throws I2PSessionException {
|
||||
if (!_routerSupportsLookupOptions) {
|
||||
withOptions = false;
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Lookup with options not supported by router");
|
||||
}
|
||||
// if options are requested, we need to ask the router
|
||||
if (!withOptions) {
|
||||
synchronized (_lookupCache) {
|
||||
Destination rv = _lookupCache.get(h);
|
||||
if (rv != null)
|
||||
return new LkupResult(LookupResult.RESULT_SUCCESS, rv);
|
||||
}
|
||||
}
|
||||
synchronized (_stateLock) {
|
||||
// not before GOTDATE
|
||||
@@ -1977,7 +2078,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
if (maxWait > 60*1000)
|
||||
maxWait = 60*1000;
|
||||
try {
|
||||
sendMessage_unchecked(new HostLookupMessage(id, h, nonce, maxWait));
|
||||
sendMessage_unchecked(new HostLookupMessage(id, h, nonce, maxWait, withOptions));
|
||||
} catch (I2PSessionException ise) {
|
||||
_pendingLookups.remove(waiter);
|
||||
throw ise;
|
||||
@@ -1987,7 +2088,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hash.
|
||||
* Lookup a Destination by hostname.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
@@ -1998,6 +2099,27 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
* @since 0.9.67
|
||||
*/
|
||||
public LookupResult lookupDest(String name, long maxWait, LookupCallback callback) throws I2PSessionException {
|
||||
return lookupDest(name, maxWait, callback, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a Destination by hostname.
|
||||
* Non-blocking.
|
||||
* If the result is cached or there is an immediate failure,
|
||||
* the result code will be something other than RESULT_DEFERRED, and the callback will NOT be called.
|
||||
*
|
||||
* @param maxWait ms
|
||||
* @param callback to return the result, non-null
|
||||
* @param withOptions see proposal 167
|
||||
* @return non-null. If result code is RESULT_DEFERRED, callback will be called later
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public LookupResult lookupDest(String name, long maxWait, LookupCallback callback, boolean withOptions) throws I2PSessionException {
|
||||
if (!_routerSupportsLookupOptions) {
|
||||
withOptions = false;
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Lookup with options not supported by router");
|
||||
}
|
||||
if (name.length() == 0)
|
||||
return LOOKUP_FAILURE;
|
||||
// Shortcut for b64
|
||||
@@ -2012,10 +2134,13 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
// won't fit in Mapping
|
||||
if (name.length() >= 256 && !_context.isRouterContext())
|
||||
return LOOKUP_FAILURE;
|
||||
synchronized (_lookupCache) {
|
||||
Destination rv = _lookupCache.get(name);
|
||||
if (rv != null)
|
||||
return new LkupResult(LookupResult.RESULT_SUCCESS, rv);
|
||||
// if options are requested, we need to ask the router
|
||||
if (!withOptions) {
|
||||
synchronized (_lookupCache) {
|
||||
Destination rv = _lookupCache.get(name);
|
||||
if (rv != null)
|
||||
return new LkupResult(LookupResult.RESULT_SUCCESS, rv);
|
||||
}
|
||||
}
|
||||
synchronized (_stateLock) {
|
||||
// not before GOTDATE
|
||||
@@ -2037,7 +2162,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
|
||||
if (maxWait > 60*1000)
|
||||
maxWait = 60*1000;
|
||||
try {
|
||||
sendMessage_unchecked(new HostLookupMessage(id, name, nonce, maxWait));
|
||||
sendMessage_unchecked(new HostLookupMessage(id, name, nonce, maxWait, withOptions));
|
||||
} catch (I2PSessionException ise) {
|
||||
_pendingLookups.remove(waiter);
|
||||
throw ise;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.i2p.client.impl;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.client.LookupResult;
|
||||
import net.i2p.data.Destination;
|
||||
|
||||
@@ -13,9 +15,10 @@ public class LkupResult implements LookupResult {
|
||||
private final int _code;
|
||||
private final Destination _dest;
|
||||
private final int _nonce;
|
||||
private final Properties _opts;
|
||||
|
||||
LkupResult(int code, Destination dest) {
|
||||
this(code, dest, 0);
|
||||
this(code, dest, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,7 +27,7 @@ public class LkupResult implements LookupResult {
|
||||
* @since 0.9.67
|
||||
*/
|
||||
LkupResult(int nonce) {
|
||||
this(RESULT_DEFERRED, null, nonce);
|
||||
this(RESULT_DEFERRED, null, nonce, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,9 +36,19 @@ public class LkupResult implements LookupResult {
|
||||
* @since 0.9.67
|
||||
*/
|
||||
LkupResult(int code, Destination dest, int nonce) {
|
||||
this(code, dest, nonce, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* See proposal 167
|
||||
*
|
||||
* @since 0.9.70
|
||||
*/
|
||||
LkupResult(int code, Destination dest, int nonce, Properties opts) {
|
||||
_code = code;
|
||||
_dest = dest;
|
||||
_nonce = nonce;
|
||||
_opts = opts;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +61,13 @@ public class LkupResult implements LookupResult {
|
||||
*/
|
||||
public Destination getDestination() { return _dest; }
|
||||
|
||||
/**
|
||||
* See proposal 167
|
||||
* @return options from leaseset or null
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public Properties getOptions() { return _opts; }
|
||||
|
||||
/**
|
||||
* For async calls only. Nonce will be non-zero.
|
||||
* Callback will be called later with the final result and the same nonce.
|
||||
|
||||
@@ -257,8 +257,8 @@ class SubSession extends I2PSessionMuxedImpl {
|
||||
* on reception of HostReplyMessage
|
||||
* @param d non-null
|
||||
*/
|
||||
void destReceived(long nonce, Destination d) {
|
||||
_primary.destReceived(nonce, d);
|
||||
void destReceived(long nonce, Destination d, Properties opts) {
|
||||
_primary.destReceived(nonce, d, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,7 +78,7 @@ public class DummyNamingService extends NamingService {
|
||||
try {
|
||||
if (hostname.length() == BASE32_HASH_LENGTH + 8) {
|
||||
// b32
|
||||
d = LookupDest.lookupBase32Hash(_context, hostname.substring(0, BASE32_HASH_LENGTH));
|
||||
d = LookupDest.lookupBase32Hash(_context, hostname.substring(0, BASE32_HASH_LENGTH), storedOptions);
|
||||
} else {
|
||||
// b33
|
||||
d = LookupDest.lookupHostname(_context, hostname);
|
||||
|
||||
@@ -11,6 +11,8 @@ import net.i2p.client.I2PSessionException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PSession;
|
||||
import net.i2p.client.I2PSimpleClient;
|
||||
import net.i2p.client.LookupResult;
|
||||
import net.i2p.client.impl.LkupCallback;
|
||||
import net.i2p.data.Base32;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
@@ -38,12 +40,22 @@ public class LookupDest {
|
||||
|
||||
protected LookupDest(I2PAppContext context) {}
|
||||
|
||||
/** @param key 52 chars (do not include the .b32.i2p suffix) */
|
||||
/**
|
||||
* @param key 52 chars (do not include the .b32.i2p suffix)
|
||||
*/
|
||||
static Destination lookupBase32Hash(I2PAppContext ctx, String key) throws I2PSessionException {
|
||||
return lookupBase32Hash(ctx, key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 52 chars (do not include the .b32.i2p suffix)
|
||||
* @param lsopts out property or null
|
||||
*/
|
||||
static Destination lookupBase32Hash(I2PAppContext ctx, String key, Properties lsopts) throws I2PSessionException {
|
||||
byte[] h = Base32.decode(key);
|
||||
if (h == null)
|
||||
return null;
|
||||
return lookupHash(ctx, h);
|
||||
return lookupHash(ctx, h, lsopts);
|
||||
}
|
||||
|
||||
/* Might be useful but not in the context of urls due to upper/lower case */
|
||||
@@ -56,8 +68,12 @@ public class LookupDest {
|
||||
}
|
||||
****/
|
||||
|
||||
/** @param h 32 byte hash */
|
||||
private static Destination lookupHash(I2PAppContext ctx, byte[] h) throws I2PSessionException {
|
||||
/**
|
||||
* @param h 32 byte hash
|
||||
* @param lsopts out property or null
|
||||
* @since 0.9.70
|
||||
*/
|
||||
private static Destination lookupHash(I2PAppContext ctx, byte[] h, Properties lsopts) throws I2PSessionException {
|
||||
Hash key = Hash.create(h);
|
||||
Destination rv = null;
|
||||
I2PClient client = new I2PSimpleClient();
|
||||
@@ -66,7 +82,32 @@ public class LookupDest {
|
||||
try {
|
||||
session = client.createSession(null, opts);
|
||||
session.connect();
|
||||
rv = session.lookupDest(key, DEFAULT_TIMEOUT);
|
||||
if (lsopts != null) {
|
||||
// prop. 167
|
||||
LkupCallback cb = new LkupCallback();
|
||||
LookupResult res = session.lookupDest(key, 10*1000, cb, true);
|
||||
int code = res.getResultCode();
|
||||
if (code == LookupResult.RESULT_SUCCESS) {
|
||||
rv = res.getDestination();
|
||||
Properties ropts = res.getOptions();
|
||||
if (ropts != null && !ropts.isEmpty())
|
||||
lsopts.putAll(ropts);
|
||||
} else if (code == LookupResult.RESULT_DEFERRED) {
|
||||
// blocking, sit and wait for it
|
||||
synchronized(cb) {
|
||||
try { cb.wait(10*1000); } catch (InterruptedException ie) {}
|
||||
res = cb.getResult();
|
||||
}
|
||||
if (res != null && res.getResultCode() == LookupResult.RESULT_SUCCESS) {
|
||||
rv = res.getDestination();
|
||||
Properties ropts = res.getOptions();
|
||||
if (ropts != null && !ropts.isEmpty())
|
||||
lsopts.putAll(ropts);
|
||||
} // else timeout or failure
|
||||
} // else immediate failure
|
||||
} else {
|
||||
rv = session.lookupDest(key, DEFAULT_TIMEOUT);
|
||||
}
|
||||
} finally {
|
||||
if (session != null)
|
||||
session.destroySession();
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.io.InputStream;
|
||||
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.util.ByteArrayStream;
|
||||
|
||||
@@ -28,6 +29,7 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
private int _lookupType;
|
||||
private Hash _hash;
|
||||
private String _host;
|
||||
private Destination _dest;
|
||||
private SessionId _sessionId;
|
||||
|
||||
public static final int LOOKUP_HASH = 0;
|
||||
@@ -96,6 +98,28 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
_lookupType = reqOpts ? LOOKUP_HOST_OPT : LOOKUP_HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always requests LS2 options
|
||||
*
|
||||
* @param reqID 0 to 2**32 - 1
|
||||
* @param timeout ms 1 to 2**32 - 1
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public HostLookupMessage(SessionId id, Destination dest, long reqID, long timeout) {
|
||||
if (id == null || dest == null)
|
||||
throw new IllegalArgumentException();
|
||||
if (reqID < 0 || reqID > MAX_INT)
|
||||
throw new IllegalArgumentException();
|
||||
if (timeout <= 0 || timeout > MAX_INT)
|
||||
throw new IllegalArgumentException();
|
||||
_sessionId = id;
|
||||
_dest = dest;
|
||||
_hash = dest.calculateHash();
|
||||
_reqID = reqID;
|
||||
_timeout = timeout;
|
||||
_lookupType = LOOKUP_DEST_OPT;
|
||||
}
|
||||
|
||||
public SessionId getSessionId() {
|
||||
return _sessionId;
|
||||
}
|
||||
@@ -125,26 +149,34 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 0 (hash) or 1 (host)
|
||||
* @return 0-4
|
||||
*/
|
||||
public int getLookupType() {
|
||||
return _lookupType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return only valid if lookup type == 0
|
||||
* @return only valid if lookup type == 0 or 2 or 4
|
||||
*/
|
||||
public Hash getHash() {
|
||||
return _hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return only valid if lookup type == 1
|
||||
* @return only valid if lookup type == 1 or 3
|
||||
*/
|
||||
public String getHostname() {
|
||||
return _host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return only valid if lookup type == 4
|
||||
* @since 0.9.70
|
||||
*/
|
||||
public Destination getDestination() {
|
||||
return _dest;
|
||||
}
|
||||
|
||||
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
|
||||
try {
|
||||
_sessionId = new SessionId();
|
||||
@@ -154,13 +186,24 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
_lookupType = in.read();
|
||||
if (_lookupType < 0)
|
||||
throw new EOFException();
|
||||
if (_lookupType == LOOKUP_HASH || _lookupType == LOOKUP_HASH_OPT) {
|
||||
switch (_lookupType) {
|
||||
case LOOKUP_HASH:
|
||||
case LOOKUP_HASH_OPT:
|
||||
_hash = Hash.create(in);
|
||||
} else if (_lookupType == LOOKUP_HOST || _lookupType == LOOKUP_HOST_OPT) {
|
||||
break;
|
||||
|
||||
case LOOKUP_HOST:
|
||||
case LOOKUP_HOST_OPT:
|
||||
_host = DataHelper.readString(in);
|
||||
if (_host.length() == 0)
|
||||
throw new I2CPMessageException("bad host");
|
||||
} else {
|
||||
break;
|
||||
|
||||
case LOOKUP_DEST_OPT:
|
||||
_dest = Destination.create(in);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new I2CPMessageException("bad type");
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
@@ -170,15 +213,26 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
|
||||
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
|
||||
int len;
|
||||
if (_lookupType == LOOKUP_HASH || _lookupType == LOOKUP_HASH_OPT) {
|
||||
switch (_lookupType) {
|
||||
case LOOKUP_HASH:
|
||||
case LOOKUP_HASH_OPT:
|
||||
if (_hash == null)
|
||||
throw new I2CPMessageException("Unable to write out the message as there is not enough data");
|
||||
len = 11 + Hash.HASH_LENGTH;
|
||||
} else if (_lookupType == LOOKUP_HOST || _lookupType == LOOKUP_HOST_OPT) {
|
||||
break;
|
||||
|
||||
case LOOKUP_HOST:
|
||||
case LOOKUP_HOST_OPT:
|
||||
if (_host == null)
|
||||
throw new I2CPMessageException("Unable to write out the message as there is not enough data");
|
||||
len = 12 + _host.length();
|
||||
} else {
|
||||
break;
|
||||
|
||||
case LOOKUP_DEST_OPT:
|
||||
len = 11 + _dest.size();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new I2CPMessageException("bad type");
|
||||
}
|
||||
ByteArrayStream os = new ByteArrayStream(len);
|
||||
@@ -187,10 +241,20 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
DataHelper.writeLong(os, 4, _reqID);
|
||||
DataHelper.writeLong(os, 4, _timeout);
|
||||
os.write((byte) _lookupType);
|
||||
if (_lookupType == LOOKUP_HASH) {
|
||||
switch (_lookupType) {
|
||||
case LOOKUP_HASH:
|
||||
case LOOKUP_HASH_OPT:
|
||||
_hash.writeBytes(os);
|
||||
} else {
|
||||
break;
|
||||
|
||||
case LOOKUP_HOST:
|
||||
case LOOKUP_HOST_OPT:
|
||||
DataHelper.writeString(os, _host);
|
||||
break;
|
||||
|
||||
case LOOKUP_DEST_OPT:
|
||||
_dest.writeBytes(os);
|
||||
break;
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new I2CPMessageException("bad data", dfe);
|
||||
@@ -209,10 +273,22 @@ public class HostLookupMessage extends I2CPMessageImpl {
|
||||
buf.append("\n\t").append(_sessionId);
|
||||
buf.append("\n\tReqID: ").append(_reqID);
|
||||
buf.append("\n\tTimeout: ").append(_timeout);
|
||||
if (_lookupType == LOOKUP_HASH)
|
||||
buf.append("\n\tType: ").append(_lookupType);
|
||||
switch (_lookupType) {
|
||||
case LOOKUP_HASH:
|
||||
case LOOKUP_HASH_OPT:
|
||||
buf.append("\n\tHash: ").append(_hash);
|
||||
else if (_lookupType == LOOKUP_HOST)
|
||||
break;
|
||||
|
||||
case LOOKUP_HOST:
|
||||
case LOOKUP_HOST_OPT:
|
||||
buf.append("\n\tHost: ").append(_host);
|
||||
break;
|
||||
|
||||
case LOOKUP_DEST_OPT:
|
||||
buf.append("\n\tDest: ").append(_dest);
|
||||
break;
|
||||
}
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@@ -196,8 +196,11 @@ public class HostReplyMessage extends I2CPMessageImpl {
|
||||
buf.append("\n\t").append(_sessionId);
|
||||
buf.append("\n\tReqID: ").append(_reqID);
|
||||
buf.append("\n\tResult: ").append(_code);
|
||||
if (_code == RESULT_SUCCESS)
|
||||
if (_code == RESULT_SUCCESS) {
|
||||
buf.append("\n\tDestination: ").append(_dest);
|
||||
if (_options != null && !_options.isEmpty())
|
||||
buf.append("\n\tOptions: ").append(DataHelper.toString(_options));
|
||||
}
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user