2004-11-05 jrandom
* Bugfixes and unit tests for the SAM bridge to handle quoted message parameters, verify proper operation after multiple session lifetimes, as well as some synchronization problems. * New properties method on the DataHelper class. * Address a race on fast disconnecting clients
This commit is contained in:
@ -46,7 +46,7 @@ public class SAMBridge implements Runnable {
|
|||||||
* app designated destination name to the base64 of the I2P formatted
|
* app designated destination name to the base64 of the I2P formatted
|
||||||
* destination keys (Destination+PrivateKey+SigningPrivateKey)
|
* destination keys (Destination+PrivateKey+SigningPrivateKey)
|
||||||
*/
|
*/
|
||||||
private Map nameToPrivKeys = Collections.synchronizedMap(new HashMap(8));
|
private Map nameToPrivKeys;
|
||||||
|
|
||||||
private boolean acceptConnections = true;
|
private boolean acceptConnections = true;
|
||||||
|
|
||||||
@ -65,6 +65,7 @@ public class SAMBridge implements Runnable {
|
|||||||
*/
|
*/
|
||||||
public SAMBridge(String listenHost, int listenPort, Properties i2cpProps, String persistFile) {
|
public SAMBridge(String listenHost, int listenPort, Properties i2cpProps, String persistFile) {
|
||||||
persistFilename = persistFile;
|
persistFilename = persistFile;
|
||||||
|
nameToPrivKeys = new HashMap(8);
|
||||||
loadKeys();
|
loadKeys();
|
||||||
try {
|
try {
|
||||||
if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) {
|
if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) {
|
||||||
@ -93,6 +94,7 @@ public class SAMBridge implements Runnable {
|
|||||||
* @return null if the name does not exist, or if it is improperly formatted
|
* @return null if the name does not exist, or if it is improperly formatted
|
||||||
*/
|
*/
|
||||||
public Destination getDestination(String name) {
|
public Destination getDestination(String name) {
|
||||||
|
synchronized (nameToPrivKeys) {
|
||||||
String val = (String)nameToPrivKeys.get(name);
|
String val = (String)nameToPrivKeys.get(name);
|
||||||
if (val == null) return null;
|
if (val == null) return null;
|
||||||
try {
|
try {
|
||||||
@ -105,6 +107,7 @@ public class SAMBridge implements Runnable {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the I2P private keystream for the given name, formatted
|
* Retrieve the I2P private keystream for the given name, formatted
|
||||||
@ -114,17 +117,21 @@ public class SAMBridge implements Runnable {
|
|||||||
* @return null if the name does not exist, else the stream
|
* @return null if the name does not exist, else the stream
|
||||||
*/
|
*/
|
||||||
public String getKeystream(String name) {
|
public String getKeystream(String name) {
|
||||||
|
synchronized (nameToPrivKeys) {
|
||||||
String val = (String)nameToPrivKeys.get(name);
|
String val = (String)nameToPrivKeys.get(name);
|
||||||
if (val == null) return null;
|
if (val == null) return null;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify that the given keystream should be used for the given name
|
* Specify that the given keystream should be used for the given name
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void addKeystream(String name, String stream) {
|
public void addKeystream(String name, String stream) {
|
||||||
|
synchronized (nameToPrivKeys) {
|
||||||
nameToPrivKeys.put(name, stream);
|
nameToPrivKeys.put(name, stream);
|
||||||
|
}
|
||||||
storeKeys();
|
storeKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +139,9 @@ public class SAMBridge implements Runnable {
|
|||||||
* Load up the keys from the persistFilename
|
* Load up the keys from the persistFilename
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private synchronized void loadKeys() {
|
private void loadKeys() {
|
||||||
Map keys = new HashMap(16);
|
synchronized (nameToPrivKeys) {
|
||||||
|
nameToPrivKeys.clear();
|
||||||
FileInputStream in = null;
|
FileInputStream in = null;
|
||||||
try {
|
try {
|
||||||
in = new FileInputStream(persistFilename);
|
in = new FileInputStream(persistFilename);
|
||||||
@ -143,7 +151,7 @@ public class SAMBridge implements Runnable {
|
|||||||
int eq = line.indexOf('=');
|
int eq = line.indexOf('=');
|
||||||
String name = line.substring(0, eq);
|
String name = line.substring(0, eq);
|
||||||
String privKeys = line.substring(eq+1);
|
String privKeys = line.substring(eq+1);
|
||||||
keys.put(name, privKeys);
|
nameToPrivKeys.put(name, privKeys);
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException fnfe) {
|
} catch (FileNotFoundException fnfe) {
|
||||||
_log.warn("Key file does not exist at " + persistFilename);
|
_log.warn("Key file does not exist at " + persistFilename);
|
||||||
@ -152,14 +160,15 @@ public class SAMBridge implements Runnable {
|
|||||||
} finally {
|
} finally {
|
||||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||||
}
|
}
|
||||||
nameToPrivKeys = Collections.synchronizedMap(keys);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the current keys to disk in the location specified on creation
|
* Store the current keys to disk in the location specified on creation
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private synchronized void storeKeys() {
|
private void storeKeys() {
|
||||||
|
synchronized (nameToPrivKeys) {
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
out = new FileOutputStream(persistFilename);
|
out = new FileOutputStream(persistFilename);
|
||||||
@ -177,6 +186,7 @@ public class SAMBridge implements Runnable {
|
|||||||
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage:
|
* Usage:
|
||||||
|
@ -111,9 +111,10 @@ public class SAMUtils {
|
|||||||
*/
|
*/
|
||||||
public static Properties parseParams(StringTokenizer tok) throws SAMException {
|
public static Properties parseParams(StringTokenizer tok) throws SAMException {
|
||||||
int pos, nprops = 0, ntoks = tok.countTokens();
|
int pos, nprops = 0, ntoks = tok.countTokens();
|
||||||
String token, param, value;
|
String token, param;
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
|
|
||||||
|
StringBuffer value = new StringBuffer();
|
||||||
for (int i = 0; i < ntoks; ++i) {
|
for (int i = 0; i < ntoks; ++i) {
|
||||||
token = tok.nextToken();
|
token = tok.nextToken();
|
||||||
|
|
||||||
@ -123,9 +124,16 @@ public class SAMUtils {
|
|||||||
throw new SAMException("Bad formatting for param [" + token + "]");
|
throw new SAMException("Bad formatting for param [" + token + "]");
|
||||||
}
|
}
|
||||||
param = token.substring(0, pos);
|
param = token.substring(0, pos);
|
||||||
value = token.substring(pos + 1);
|
value.append(token.substring(pos+1));
|
||||||
|
if (value.charAt(0) == '"') {
|
||||||
|
while ( (i < ntoks) && (value.lastIndexOf("\"") <= 0) ) {
|
||||||
|
value.append(' ').append(tok.nextToken());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
props.setProperty(param, value);
|
props.setProperty(param, value.toString());
|
||||||
|
value.setLength(0);
|
||||||
nprops += 1;
|
nprops += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,4 +165,19 @@ public class SAMUtils {
|
|||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
try {
|
||||||
|
test("a=b c=d e=\"f g h\"");
|
||||||
|
test("a=\"b c d\" e=\"f g h\" i=\"j\"");
|
||||||
|
test("a=\"b c d\" e=f i=\"j\"");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void test(String props) throws Exception {
|
||||||
|
StringTokenizer tok = new StringTokenizer(props);
|
||||||
|
Properties p = parseParams(tok);
|
||||||
|
System.out.println(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
|||||||
|
|
||||||
msg = buf.toString("ISO-8859-1").trim();
|
msg = buf.toString("ISO-8859-1").trim();
|
||||||
if (_log.shouldLog(Log.DEBUG)) {
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
_log.debug("New message received: " + msg);
|
_log.debug("New message received: [" + msg + "]");
|
||||||
}
|
}
|
||||||
buf.reset();
|
buf.reset();
|
||||||
|
|
||||||
|
@ -33,7 +33,11 @@ public class TestStreamTransfer {
|
|||||||
|
|
||||||
private static void runTest(String samHost, int samPort, String conOptions) {
|
private static void runTest(String samHost, int samPort, String conOptions) {
|
||||||
startAlice(samHost, samPort, conOptions);
|
startAlice(samHost, samPort, conOptions);
|
||||||
testBob(samHost, samPort, conOptions);
|
for (int i = 0; i < 20; i++) {
|
||||||
|
testBob("bob" + i, samHost, samPort, conOptions);
|
||||||
|
if (i % 2 == 1)
|
||||||
|
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void startAlice(String host, int port, String conOptions) {
|
private static void startAlice(String host, int port, String conOptions) {
|
||||||
@ -95,11 +99,13 @@ public class TestStreamTransfer {
|
|||||||
try { _out.close(); } catch (IOException ioe) {}
|
try { _out.close(); } catch (IOException ioe) {}
|
||||||
try { _s.close(); } catch (IOException ioe) {}
|
try { _s.close(); } catch (IOException ioe) {}
|
||||||
_streams.clear();
|
_streams.clear();
|
||||||
|
_dead = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void doRun() throws IOException, SAMException {
|
private void doRun() throws IOException, SAMException {
|
||||||
String line = _reader.readLine();
|
String line = _reader.readLine();
|
||||||
|
_log.debug("Read: " + line);
|
||||||
StringTokenizer tok = new StringTokenizer(line);
|
StringTokenizer tok = new StringTokenizer(line);
|
||||||
String maj = tok.nextToken();
|
String maj = tok.nextToken();
|
||||||
String min = tok.nextToken();
|
String min = tok.nextToken();
|
||||||
@ -146,12 +152,15 @@ public class TestStreamTransfer {
|
|||||||
}
|
}
|
||||||
_log.info("Received from the stream " + id + ": [" + new String(payload) + "]");
|
_log.info("Received from the stream " + id + ": [" + new String(payload) + "]");
|
||||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||||
|
/*
|
||||||
// now echo it back
|
// now echo it back
|
||||||
String reply = "STREAM SEND ID=" + id +
|
String reply = "STREAM SEND ID=" + id +
|
||||||
" SIZE=" + payloadSize +
|
" SIZE=" + payloadSize +
|
||||||
"\n" + payload;
|
"\n" + new String(payload);
|
||||||
_out.write(reply.getBytes());
|
_out.write(reply.getBytes());
|
||||||
_out.flush();
|
_out.flush();
|
||||||
|
_log.info("Reply sent back [" + new String(reply.getBytes()) + "]");
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
_log.error("Received unsupported type [" + maj + "/"+ min + "]");
|
_log.error("Received unsupported type [" + maj + "/"+ min + "]");
|
||||||
return;
|
return;
|
||||||
@ -159,8 +168,27 @@ public class TestStreamTransfer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testBob(String host, int port, String conOptions) {
|
private static void testBob(String sessionName, String host, int port, String conOptions) {
|
||||||
_log.info("\n\nTesting Bob\n\n\n");
|
I2PThread t = new I2PThread(new TestBob(sessionName, host, port, conOptions), sessionName);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
private static class TestBob implements Runnable {
|
||||||
|
private String _sessionName;
|
||||||
|
private String _host;
|
||||||
|
private int _port;
|
||||||
|
private String _opts;
|
||||||
|
public TestBob(String name, String host, int port, String opts) {
|
||||||
|
_sessionName = name;
|
||||||
|
_host = host;
|
||||||
|
_port = port;
|
||||||
|
_opts = opts;
|
||||||
|
}
|
||||||
|
public void run() {
|
||||||
|
doTestBob(_sessionName, _host, _port, _opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void doTestBob(String sessionName, String host, int port, String conOptions) {
|
||||||
|
_log.info("\n\nTesting " + sessionName + "\n\n\n");
|
||||||
try {
|
try {
|
||||||
Socket s = new Socket(host, port);
|
Socket s = new Socket(host, port);
|
||||||
OutputStream out = s.getOutputStream();
|
OutputStream out = s.getOutputStream();
|
||||||
@ -168,32 +196,37 @@ public class TestStreamTransfer {
|
|||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||||
String line = reader.readLine();
|
String line = reader.readLine();
|
||||||
_log.debug("line read for valid version: " + line);
|
_log.debug("line read for valid version: " + line);
|
||||||
String req = "SESSION CREATE STYLE=STREAM DESTINATION=Bob " + conOptions + "\n";
|
String req = "SESSION CREATE STYLE=STREAM DESTINATION=" + sessionName + " " + conOptions + "\n";
|
||||||
out.write(req.getBytes());
|
out.write(req.getBytes());
|
||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
_log.info("Response to creating the session with destination Bob: " + line);
|
_log.info("Response to creating the session with destination "+ sessionName+": " + line);
|
||||||
req = "STREAM CONNECT ID=42 DESTINATION=" + _alice + "\n";
|
req = "STREAM CONNECT ID=42 DESTINATION=" + _alice + "\n";
|
||||||
out.write(req.getBytes());
|
out.write(req.getBytes());
|
||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
_log.info("Response to the stream connect from Bob to Alice: " + line);
|
_log.info("Response to the stream connect from "+sessionName+" to Alice: " + line);
|
||||||
StringTokenizer tok = new StringTokenizer(line);
|
StringTokenizer tok = new StringTokenizer(line);
|
||||||
String maj = tok.nextToken();
|
String maj = tok.nextToken();
|
||||||
String min = tok.nextToken();
|
String min = tok.nextToken();
|
||||||
Properties props = SAMUtils.parseParams(tok);
|
Properties props = SAMUtils.parseParams(tok);
|
||||||
|
_log.info("props = " + props);
|
||||||
String result = props.getProperty("RESULT");
|
String result = props.getProperty("RESULT");
|
||||||
if (!("OK".equals(result))) {
|
if (!("OK".equals(result))) {
|
||||||
_log.error("Unable to connect!");
|
_log.error("Unable to connect!");
|
||||||
_dead = true;
|
//_dead = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try { Thread.sleep(5*1000) ; } catch (InterruptedException ie) {}
|
try { Thread.sleep(5*1000) ; } catch (InterruptedException ie) {}
|
||||||
req = "STREAM SEND ID=42 SIZE=10\nBlahBlah!!";
|
req = "STREAM SEND ID=42 SIZE=10\nBlahBlah!!";
|
||||||
|
_log.info("Sending data");
|
||||||
out.write(req.getBytes());
|
out.write(req.getBytes());
|
||||||
|
out.flush();
|
||||||
try { Thread.sleep(20*1000); } catch (InterruptedException ie) {}
|
try { Thread.sleep(20*1000); } catch (InterruptedException ie) {}
|
||||||
|
_log.info("Sending close");
|
||||||
req = "STREAM CLOSE ID=42\n";
|
req = "STREAM CLOSE ID=42\n";
|
||||||
out.write(req.getBytes());
|
out.write(req.getBytes());
|
||||||
try { Thread.sleep(3*1000); } catch (InterruptedException ie) {}
|
out.flush();
|
||||||
_dead = true;
|
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
|
||||||
|
//_dead = true;
|
||||||
s.close();
|
s.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
_log.error("Error testing for valid version", e);
|
_log.error("Error testing for valid version", e);
|
||||||
@ -203,7 +236,7 @@ public class TestStreamTransfer {
|
|||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
// "i2cp.tcp.host=www.i2p.net i2cp.tcp.port=7765 tunnels.inboundDepth=0";
|
// "i2cp.tcp.host=www.i2p.net i2cp.tcp.port=7765 tunnels.inboundDepth=0";
|
||||||
// "i2cp.tcp.host=localhost i2cp.tcp.port=7654 tunnels.inboundDepth=0";
|
// "i2cp.tcp.host=localhost i2cp.tcp.port=7654 tunnels.inboundDepth=0";
|
||||||
String conOptions = "i2cp.tcp.host=www.i2p.net i2cp.tcp.port=7765 tunnels.inboundDepth=0";
|
String conOptions = "i2cp.tcp.host=localhost i2cp.tcp.port=10001 tunnels.inboundDepth=0";
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
conOptions = "";
|
conOptions = "";
|
||||||
for (int i = 0; i < args.length; i++)
|
for (int i = 0; i < args.length; i++)
|
||||||
@ -215,8 +248,8 @@ public class TestStreamTransfer {
|
|||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
_log.error("Error running test", t);
|
_log.error("Error running test", t);
|
||||||
}
|
}
|
||||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
//try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||||
System.exit(0);
|
//System.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,17 @@ package net.i2p.data;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -162,6 +165,21 @@ public class DataHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void storeProps(Properties props, File file) throws IOException {
|
||||||
|
PrintWriter out = null;
|
||||||
|
try {
|
||||||
|
out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
|
||||||
|
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||||
|
String name = (String)iter.next();
|
||||||
|
String val = props.getProperty(name);
|
||||||
|
out.println(name + "=" + val);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} finally {
|
||||||
|
if (out != null) out.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pretty print the collection
|
* Pretty print the collection
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
$Id: history.txt,v 1.61 2004/11/02 03:27:56 jrandom Exp $
|
$Id: history.txt,v 1.62 2004/11/02 06:57:08 jrandom Exp $
|
||||||
|
|
||||||
|
2004-11-05 jrandom
|
||||||
|
* Bugfixes and unit tests for the SAM bridge to handle quoted message
|
||||||
|
parameters, verify proper operation after multiple session lifetimes,
|
||||||
|
as well as some synchronization problems.
|
||||||
|
* New properties method on the DataHelper class.
|
||||||
|
* Address a race on fast disconnecting clients
|
||||||
|
|
||||||
2004-11-02 jrandom
|
2004-11-02 jrandom
|
||||||
* Fix for a long standing synchronization bug in the JobQueue (and added
|
* Fix for a long standing synchronization bug in the JobQueue (and added
|
||||||
|
@ -598,6 +598,10 @@ public class JobQueue {
|
|||||||
for (int i = 0; states != null && i < states.length; i++)
|
for (int i = 0; states != null && i < states.length; i++)
|
||||||
str.append(states[i]).append(" ");
|
str.append(states[i]).append(" ");
|
||||||
str.append(" -->\n");
|
str.append(" -->\n");
|
||||||
|
str.append("<!-- jobs: ");
|
||||||
|
for (int i = 0; i < activeJobs.size(); i++)
|
||||||
|
str.append(activeJobs.get(i).toString()).append(" ");
|
||||||
|
str.append("-->\n");
|
||||||
out.write(str.toString());
|
out.write(str.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RouterVersion {
|
public class RouterVersion {
|
||||||
public final static String ID = "$Revision: 1.67 $ $Date: 2004/11/02 03:27:56 $";
|
public final static String ID = "$Revision: 1.68 $ $Date: 2004/11/02 06:57:08 $";
|
||||||
public final static String VERSION = "0.4.1.3";
|
public final static String VERSION = "0.4.1.3";
|
||||||
public final static long BUILD = 8;
|
public final static long BUILD = 9;
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
System.out.println("I2P Router version: " + VERSION);
|
System.out.println("I2P Router version: " + VERSION);
|
||||||
System.out.println("Router ID: " + RouterVersion.ID);
|
System.out.println("Router ID: " + RouterVersion.ID);
|
||||||
|
@ -134,7 +134,7 @@ class ClientTunnelPoolManagerJob extends JobImpl {
|
|||||||
// this aint good 'nuff...
|
// this aint good 'nuff...
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boolean ok = _tunnelPool.allocateTunnel(id, _clientPool.getDestination());
|
boolean ok = _tunnelPool.allocateTunnel(id, _clientPool);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
allocated++;
|
allocated++;
|
||||||
}
|
}
|
||||||
|
@ -175,23 +175,25 @@ class TunnelPool {
|
|||||||
* @return true if the tunnel was allocated successfully, false if an error occurred
|
* @return true if the tunnel was allocated successfully, false if an error occurred
|
||||||
*/
|
*/
|
||||||
public boolean allocateTunnel(TunnelId id, Destination dest) {
|
public boolean allocateTunnel(TunnelId id, Destination dest) {
|
||||||
|
return allocateTunnel(id, getClientPool(dest));
|
||||||
|
}
|
||||||
|
public boolean allocateTunnel(TunnelId id, ClientTunnelPool pool) {
|
||||||
if (!_isLive) return false;
|
if (!_isLive) return false;
|
||||||
ClientTunnelPool pool = getClientPool(dest);
|
|
||||||
if (pool == null) {
|
if (pool == null) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error allocating tunnel " + id + " to " + dest + ": no pool for the client known");
|
_log.error("Error allocating tunnel " + id + " to " + pool.getDestination() + ": no pool for the client known");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TunnelInfo tunnel = removeFreeTunnel(id);
|
TunnelInfo tunnel = removeFreeTunnel(id);
|
||||||
if (tunnel == null) {
|
if (tunnel == null) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error allocating tunnel " + id + " to " + dest + ": tunnel is no longer free?");
|
_log.error("Error allocating tunnel " + id + " to " + pool.getDestination() + ": tunnel is no longer free?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TunnelInfo t = tunnel;
|
TunnelInfo t = tunnel;
|
||||||
while (t != null) {
|
while (t != null) {
|
||||||
t.setDestination(dest);
|
t.setDestination(pool.getDestination());
|
||||||
t = t.getNextHopInfo();
|
t = t.getNextHopInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user