diff --git a/apps/BOB/nbproject/private/private.xml b/apps/BOB/nbproject/private/private.xml
index 237b674f1..c1f155a78 100644
--- a/apps/BOB/nbproject/private/private.xml
+++ b/apps/BOB/nbproject/private/private.xml
@@ -1,7 +1,4 @@
-
- file:/root/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
-
diff --git a/apps/BOB/src/net/i2p/BOB/BOB.java b/apps/BOB/src/net/i2p/BOB/BOB.java
index f08d27c2f..ee3f5937a 100644
--- a/apps/BOB/src/net/i2p/BOB/BOB.java
+++ b/apps/BOB/src/net/i2p/BOB/BOB.java
@@ -166,6 +166,7 @@ public class BOB {
public static void stop() {
spin.set(false);
}
+
/**
* Listen for incoming connections and handle them
*
@@ -188,9 +189,10 @@ public class BOB {
i = Y2.hashCode();
try {
{
- File cfg = new File(configLocation);
- if (!cfg.isAbsolute())
+ File cfg = new File(configLocation);
+ if (!cfg.isAbsolute()) {
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
+ }
try {
FileInputStream fi = new FileInputStream(cfg);
props.load(fi);
@@ -233,9 +235,10 @@ public class BOB {
props.setProperty(PROP_BOB_HOST, "localhost");
}
if (save) {
- File cfg = new File(configLocation);
- if (!cfg.isAbsolute())
+ File cfg = new File(configLocation);
+ if (!cfg.isAbsolute()) {
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
+ }
try {
warn("Writing new defaults file " + cfg.getAbsolutePath());
FileOutputStream fo = new FileOutputStream(cfg);
diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java
index 9019ef85b..8e4afb143 100644
--- a/apps/BOB/src/net/i2p/BOB/DoCMDS.java
+++ b/apps/BOB/src/net/i2p/BOB/DoCMDS.java
@@ -36,6 +36,9 @@ import net.i2p.I2PException;
import net.i2p.client.I2PClientFactory;
import net.i2p.data.Destination;
import net.i2p.util.Log;
+// needed only for debugging.
+// import java.util.logging.Level;
+// import java.util.logging.Logger;
/**
* Simplistic command parser for BOB
@@ -47,7 +50,7 @@ public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
- public static final String BMAJ = "00", BMIN = "00", BREV = "07", BEXT = "";
+ public static final String BMAJ = "00", BMIN = "00", BREV = "08", BEXT = "";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private Socket server;
private Properties props;
@@ -404,451 +407,545 @@ public class DoCMDS implements Runnable {
*/
public void run() {
dk = ns = ip = op = false;
-
try {
- // Get input from the client
- BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
- PrintStream out = new PrintStream(server.getOutputStream());
- quit:
- {
- die:
+ try {
+ // Get input from the client
+ BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
+ PrintStream out = new PrintStream(server.getOutputStream());
+ quit:
{
- prikey = new ByteArrayOutputStream();
- out.println("BOB " + BOBversion);
- out.println("OK");
- while ((line = in.readLine()) != null) {
- StringTokenizer token = new StringTokenizer(line, " "); // use a space as a delimiter
- String Command = "";
- String Arg = "";
- NamedDB info;
+ die:
+ {
+ prikey = new ByteArrayOutputStream();
+ out.println("BOB " + BOBversion);
+ out.println("OK");
+ while ((line = in.readLine()) != null) {
+ StringTokenizer token = new StringTokenizer(line, " "); // use a space as a delimiter
+ String Command = "";
+ String Arg = "";
+ NamedDB info;
- if (token.countTokens() != 0) {
- Command = token.nextToken();
- Command =
- Command.toLowerCase();
if (token.countTokens() != 0) {
- Arg = token.nextToken();
- } else {
- Arg = "";
- }
- // The rest of the tokens are considered junk,
- // and discarded without any warnings.
- if (Command.equals(C_help)) {
- for (int i = 0; !C_ALL[i][0].equals(" "); i++) {
- if (C_ALL[i][0].equalsIgnoreCase(Arg)) {
- out.println("OK " + C_ALL[i][1]);
- }
-
+ Command = token.nextToken();
+ Command =
+ Command.toLowerCase();
+ if (token.countTokens() != 0) {
+ Arg = token.nextToken();
+ } else {
+ Arg = "";
}
- } else if (Command.equals(C_visit)) {
- visitAllThreads();
- out.println("OK ");
- } else if (Command.equals(C_getdest)) {
- if (ns) {
- if (dk) {
- try {
- rlock();
- } catch (Exception ex) {
- break die;
+ // The rest of the tokens are considered junk,
+ // and discarded without any warnings.
+ if (Command.equals(C_help)) {
+ for (int i = 0; !C_ALL[i][0].equals(" "); i++) {
+ if (C_ALL[i][0].equalsIgnoreCase(Arg)) {
+ out.println("OK " + C_ALL[i][1]);
}
- try {
- out.println("OK " + nickinfo.get(P_DEST));
- } catch (Exception e) {
+ }
+ } else if (Command.equals(C_visit)) {
+ visitAllThreads();
+ out.println("OK ");
+ } else if (Command.equals(C_getdest)) {
+ if (ns) {
+ if (dk) {
+ try {
+ rlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ out.println("OK " + nickinfo.get(P_DEST));
+ } catch (Exception e) {
+ try {
+ runlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ break die;
+ }
+
try {
runlock();
} catch (Exception ex) {
break die;
}
- break die;
- }
- try {
- runlock();
- } catch (Exception ex) {
- break die;
+ } else {
+ out.println("ERROR keys not set.");
}
} else {
- out.println("ERROR keys not set.");
+ nns(out);
}
- } else {
- nns(out);
- }
-
- } else if (Command.equals(C_list)) {
- // Produce a formatted list of all nicknames
- database.getReadLock();
- for (int i = 0; i <
- database.getcount(); i++) {
- try {
- info = (NamedDB) database.getnext(i);
- out.print("DATA");
- } catch (Exception e) {
- database.releaseReadLock();
- break die;
- }
-
- try {
- info.getReadLock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickprint(out, info);
- } catch (Exception e) {
+ } else if (Command.equals(C_list)) {
+ // Produce a formatted list of all nicknames
+ database.getReadLock();
+ for (int i = 0; i <
+ database.getcount(); i++) {
try {
- info.releaseReadLock();
+ info = (NamedDB) database.getnext(i);
+ out.print("DATA");
+ } catch (Exception e) {
database.releaseReadLock();
+ break die;
+ }
+
+ try {
+ info.getReadLock();
+ } catch (Exception ex) {
+ break die;
+ }
+ try {
+ nickprint(out, info);
+ } catch (Exception e) {
+ try {
+ info.releaseReadLock();
+ database.releaseReadLock();
+ } catch (Exception ex) {
+ break die;
+ }
+ break die;
+ }
+
+ try {
+ info.releaseReadLock();
} catch (Exception ex) {
break die;
}
- break die;
}
try {
- info.releaseReadLock();
+ database.releaseReadLock();
} catch (Exception ex) {
break die;
}
- }
-
- try {
- database.releaseReadLock();
- } catch (Exception ex) {
- break die;
- }
- out.println("OK Listing done");
- } else if (Command.equals(C_quit)) {
- // End the command session
- break quit;
- } else if (Command.equals(C_zap)) {
- // Kill BOB!! (let's hope this works!)
- LIVE.set(false);
- // End the command session
- break quit;
- } else if (Command.equals(C_newkeys)) {
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- try {
- // Make a new PublicKey and PrivateKey
- prikey = new ByteArrayOutputStream();
- d = I2PClientFactory.createClient().createDestination(prikey);
+ out.println("OK Listing done");
+ } else if (Command.equals(C_quit)) {
+ // End the command session
+ break quit;
+ } else if (Command.equals(C_zap)) {
+ // Kill BOB!! (let's hope this works!)
+ LIVE.set(false);
+ // End the command session
+ break quit;
+ } else if (Command.equals(C_newkeys)) {
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
try {
- wlock();
- } catch (Exception e) {
- break die;
- }
+ // Make a new PublicKey and PrivateKey
+ prikey = new ByteArrayOutputStream();
+ d = I2PClientFactory.createClient().createDestination(prikey);
+ try {
+ wlock();
+ } catch (Exception e) {
+ break die;
+ }
- try {
- nickinfo.add(P_KEYS, prikey.toByteArray());
- nickinfo.add(P_DEST, d.toBase64());
- } catch (Exception e) {
+ try {
+ nickinfo.add(P_KEYS, prikey.toByteArray());
+ nickinfo.add(P_DEST, d.toBase64());
+ } catch (Exception e) {
+ try {
+ wunlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ break die;
+ }
+
+ dk = true;
try {
wunlock();
} catch (Exception ex) {
break die;
}
- break die;
- }
- dk = true;
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
-
- try {
- rlock();
- } catch (Exception ex) {
- break die;
- }
-
- try {
- out.println("OK " + nickinfo.get(P_DEST));
- } catch (Exception e) {
- runlock();
- break die;
- }
-
- try {
- runlock();
- } catch (Exception ex) {
- break die;
- }
- } catch (I2PException ipe) {
- BOB.error("Error generating keys" + ipe);
- out.println("ERROR generating keys");
- }
-
- }
- } catch (Exception e) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception ex) {
- break die;
- }
- }
-
- } else if (Command.equals(C_getkeys)) {
- // Return public key
- if (dk) {
- prikey = new ByteArrayOutputStream();
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
- try {
- prikey.write(((byte[]) nickinfo.get(P_KEYS)));
- } catch (Exception ex) {
- try {
- runlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
- try {
- runlock();
- } catch (Exception e) {
- break die;
- }
-
- out.println("OK " + net.i2p.data.Base64.encode(prikey.toByteArray()));
- } else {
- out.println("ERROR no public key has been set");
- }
-
- } else if (Command.equals(C_quiet)) {
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- try {
- wlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickinfo.add(P_QUIET, new Boolean(Boolean.parseBoolean(Arg) == true));
- } catch (Exception ex) {
- try {
- wunlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
-
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
-
- out.println("OK Quiet set");
- }
-
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception ex) {
- break die;
- }
- }
-
- } else if (Command.equals(C_verify)) {
- if (is64ok(Arg)) {
- out.println("OK");
- } else {
- out.println("ERROR not in BASE64 format");
- }
- } else if (Command.equals(C_setkeys)) {
- // Set the NamedDB to a privatekey in BASE64 format
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- try {
- prikey = new ByteArrayOutputStream();
- prikey.write(net.i2p.data.Base64.decode(Arg));
- d.fromBase64(Arg);
- } catch (Exception ex) {
- Arg = "";
- }
-
- if ((Arg.length() == 884) && is64ok(Arg)) {
- try {
- wlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickinfo.add(P_KEYS, prikey.toByteArray());
- nickinfo.add(P_DEST, d.toBase64());
- } catch (Exception ex) {
try {
- wunlock();
- } catch (Exception ee) {
+ rlock();
+ } catch (Exception ex) {
break die;
}
- break die;
- }
- dk = true;
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- rlock();
- } catch (Exception ex) {
- break die;
- }
+ try {
+ out.println("OK " + nickinfo.get(P_DEST));
+ } catch (Exception e) {
+ runlock();
+ break die;
+ }
- try {
- out.println("OK " + nickinfo.get(P_DEST));
- } catch (Exception e) {
try {
runlock();
} catch (Exception ex) {
break die;
}
+ } catch (I2PException ipe) {
+ BOB.error("Error generating keys" + ipe);
+ out.println("ERROR generating keys");
+ }
+
+ }
+ } catch (Exception e) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception ex) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_getkeys)) {
+ // Return public key
+ if (dk) {
+ prikey = new ByteArrayOutputStream();
+ try {
+ rlock();
+ } catch (Exception e) {
+ break die;
+ }
+ try {
+ prikey.write(((byte[]) nickinfo.get(P_KEYS)));
+ } catch (Exception ex) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ out.println("OK " + net.i2p.data.Base64.encode(prikey.toByteArray()));
+ } else {
+ out.println("ERROR no public key has been set");
+ }
+
+ } else if (Command.equals(C_quiet)) {
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ try {
+ wlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ try {
+ nickinfo.add(P_QUIET, new Boolean(Boolean.parseBoolean(Arg) == true));
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
break die;
}
try {
- runlock();
+ wunlock();
} catch (Exception ex) {
break die;
}
- } else {
- out.println("ERROR not in BASE64 format");
+
+ out.println("OK Quiet set");
}
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception ex) {
+ break die;
}
- } catch (Exception ex) {
- break die;
}
- } else {
+ } else if (Command.equals(C_verify)) {
+ if (is64ok(Arg)) {
+ out.println("OK");
+ } else {
+ out.println("ERROR not in BASE64 format");
+ }
+ } else if (Command.equals(C_setkeys)) {
+ // Set the NamedDB to a privatekey in BASE64 format
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ try {
+ prikey = new ByteArrayOutputStream();
+ prikey.write(net.i2p.data.Base64.decode(Arg));
+ d.fromBase64(Arg);
+ } catch (Exception ex) {
+ Arg = "";
+ }
+
+ if ((Arg.length() == 884) && is64ok(Arg)) {
+ try {
+ wlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ try {
+ nickinfo.add(P_KEYS, prikey.toByteArray());
+ nickinfo.add(P_DEST, d.toBase64());
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ dk = true;
+ try {
+ wunlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ rlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ out.println("OK " + nickinfo.get(P_DEST));
+ } catch (Exception e) {
+ try {
+ runlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ break die;
+ }
+
+ try {
+ runlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ } else {
+ out.println("ERROR not in BASE64 format");
+ }
+
+ }
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception ex) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_setnick)) {
+ ns = dk = ip = op = false;
try {
- nns(out);
+ database.getReadLock();
} catch (Exception ex) {
break die;
}
- }
+ try {
+ nickinfo = (NamedDB) database.get(Arg);
+ if (!tunnelactive(nickinfo)) {
+ nickinfo = null;
+ ns = true;
+ }
- } else if (Command.equals(C_setnick)) {
- ns = dk = ip = op = false;
- try {
- database.getReadLock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickinfo = (NamedDB) database.get(Arg);
- if (!tunnelactive(nickinfo)) {
+ } catch (Exception b) {
nickinfo = null;
ns = true;
}
- } catch (Exception b) {
- nickinfo = null;
- ns = true;
- }
-
- try {
- database.releaseReadLock();
- } catch (Exception ex) {
- break die;
- }
- // Clears and Sets the initial NamedDB structure to work with
- if (ns) {
- nickinfo = new NamedDB();
try {
- wlock();
- } catch (Exception e) {
+ database.releaseReadLock();
+ } catch (Exception ex) {
break die;
}
-
- try {
- database.add(Arg, nickinfo);
- nickinfo.add(P_NICKNAME, Arg);
- nickinfo.add(P_STARTING, new Boolean(false));
- nickinfo.add(P_RUNNING, new Boolean(false));
- nickinfo.add(P_STOPPING, new Boolean(false));
- nickinfo.add(P_QUIET, new Boolean(false));
- nickinfo.add(P_INHOST, "localhost");
- nickinfo.add(P_OUTHOST, "localhost");
- Properties Q = new Properties();
- Lifted.copyProperties(this.props, Q);
- Q.setProperty("inbound.nickname", Arg);
- Q.setProperty("outbound.nickname", Arg);
- nickinfo.add(P_PROPERTIES, Q);
- } catch (Exception e) {
+ // Clears and Sets the initial NamedDB structure to work with
+ if (ns) {
+ nickinfo = new NamedDB();
try {
- wunlock();
- break die;
- } catch (Exception ee) {
+ wlock();
+ } catch (Exception e) {
break die;
}
+ try {
+ database.add(Arg, nickinfo);
+ nickinfo.add(P_NICKNAME, Arg);
+ nickinfo.add(P_STARTING, new Boolean(false));
+ nickinfo.add(P_RUNNING, new Boolean(false));
+ nickinfo.add(P_STOPPING, new Boolean(false));
+ nickinfo.add(P_QUIET, new Boolean(false));
+ nickinfo.add(P_INHOST, "localhost");
+ nickinfo.add(P_OUTHOST, "localhost");
+ Properties Q = new Properties();
+ Lifted.copyProperties(this.props, Q);
+ Q.setProperty("inbound.nickname", Arg);
+ Q.setProperty("outbound.nickname", Arg);
+ nickinfo.add(P_PROPERTIES, Q);
+ } catch (Exception e) {
+ try {
+ wunlock();
+ break die;
+ } catch (Exception ee) {
+ break die;
+ }
+
+ }
+ try {
+ wunlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ out.println("OK Nickname set to " + Arg);
+ } else {
+ out.println("ERROR tunnel is active");
}
+
+ } else if (Command.equals(C_option)) {
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ StringTokenizer otoken = new StringTokenizer(Arg, "="); // use an equal sign as a delimiter
+ if (otoken.countTokens() != 2) {
+ out.println("ERROR to many or no options.");
+ } else {
+ String pname = otoken.nextToken();
+ String pval = otoken.nextToken();
+ try {
+ rlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ Properties Q = (Properties) nickinfo.get(P_PROPERTIES);
+ try {
+ runlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ Q.setProperty(pname, pval);
+ try {
+ wlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ nickinfo.add(P_PROPERTIES, Q);
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ wunlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ out.println("OK " + pname + " set to " + pval);
+ }
+
+ }
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ nns(out);
+ }
+
+ } else if (Command.equals(C_getnick)) {
+ // Get the NamedDB to work with...
try {
- wunlock();
- } catch (Exception e) {
+ database.getReadLock();
+ } catch (Exception ex) {
break die;
}
-
- out.println("OK Nickname set to " + Arg);
- } else {
- out.println("ERROR tunnel is active");
- }
-
- } else if (Command.equals(C_option)) {
- if (ns) {
try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- StringTokenizer otoken = new StringTokenizer(Arg, "="); // use an equal sign as a delimiter
- if (otoken.countTokens() != 2) {
- out.println("ERROR to many or no options.");
+ nickinfo = (NamedDB) database.get(Arg);
+ ns = true;
+ } catch (RuntimeException b) {
+ try {
+ nns(out);
+ } catch (Exception ex) {
+ try {
+ database.releaseReadLock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ }
+
+ database.releaseReadLock();
+ if (ns) {
+ try {
+ rlock();
+ } catch (Exception e) {
+ break die;
+ }
+ try {
+ dk = nickinfo.exists(P_KEYS);
+ ip = nickinfo.exists(P_INPORT);
+ op = nickinfo.exists(P_OUTPORT);
+ } catch (Exception ex) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+// Finally say OK.
+ out.println("OK Nickname set to " + Arg);
+ }
+
+ } else if (Command.equals(C_inport)) {
+ // Set the NamedDB inbound TO the router port
+ // app --> BOB
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
} else {
- String pname = otoken.nextToken();
- String pval = otoken.nextToken();
- try {
- rlock();
- } catch (Exception ex) {
- break die;
- }
-
- Properties Q = (Properties) nickinfo.get(P_PROPERTIES);
- try {
- runlock();
- } catch (Exception ex) {
- break die;
- }
-
- Q.setProperty(pname, pval);
+ int prt;
try {
wlock();
} catch (Exception ex) {
@@ -856,7 +953,181 @@ public class DoCMDS implements Runnable {
}
try {
- nickinfo.add(P_PROPERTIES, Q);
+ nickinfo.kill(P_INPORT);
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
+
+ break die;
+ }
+ try {
+ prt = Integer.parseInt(Arg);
+ if (prt > 1 && prt < 65536) {
+ try {
+ nickinfo.add(P_INPORT, new Integer(prt));
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
+
+ break die;
+ }
+ }
+
+ } catch (NumberFormatException nfe) {
+ out.println("ERROR not a number");
+ }
+
+ try {
+ wunlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ try {
+ rlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ ip = nickinfo.exists(P_INPORT);
+ } catch (Exception ex) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ runlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ if (ip) {
+ out.println("OK inbound port set");
+ } else {
+ out.println("ERROR port out of range");
+ }
+
+ }
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ nns(out);
+ }
+
+ } else if (Command.equals(C_outport)) {
+ // Set the NamedDB outbound FROM the router port
+ // BOB --> app
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ int prt;
+ try {
+ wlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ nickinfo.kill(P_OUTPORT);
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ prt = Integer.parseInt(Arg);
+ if (prt > 1 && prt < 65536) {
+ try {
+ nickinfo.add(P_OUTPORT, new Integer(prt));
+ } catch (Exception ex) {
+ try {
+ wunlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ }
+
+ } catch (NumberFormatException nfe) {
+ out.println("ERROR not a number");
+ }
+
+ try {
+ wunlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ try {
+ rlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ try {
+ ip = nickinfo.exists(P_OUTPORT);
+ } catch (Exception ex) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ runlock();
+ } catch (Exception ex) {
+ break die;
+ }
+
+ if (ip) {
+ out.println("OK outbound port set");
+ } else {
+ out.println("ERROR port out of range");
+ }
+
+ }
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception ex) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_inhost)) {
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ try {
+ wlock();
+ } catch (Exception ex) {
+ break die;
+ }
+ try {
+ nickinfo.add(P_INHOST, Arg);
} catch (Exception ex) {
try {
wunlock();
@@ -871,555 +1142,92 @@ public class DoCMDS implements Runnable {
break die;
}
- out.println("OK " + pname + " set to " + pval);
+ out.println("OK inhost set");
}
- }
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- nns(out);
- }
-
- } else if (Command.equals(C_getnick)) {
- // Get the NamedDB to work with...
- try {
- database.getReadLock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickinfo = (NamedDB) database.get(Arg);
- ns = true;
- } catch (RuntimeException b) {
- try {
- nns(out);
- } catch (Exception ex) {
- try {
- database.releaseReadLock();
- } catch (Exception ee) {
+ } catch (Exception ex) {
break die;
}
- break die;
- }
- }
- database.releaseReadLock();
- if (ns) {
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
- try {
- dk = nickinfo.exists(P_KEYS);
- ip = nickinfo.exists(P_INPORT);
- op = nickinfo.exists(P_OUTPORT);
- } catch (Exception ex) {
+ } else {
try {
- runlock();
- } catch (Exception ee) {
+ nns(out);
+ } catch (Exception ex) {
break die;
}
- break die;
}
- try {
- runlock();
- } catch (Exception e) {
- break die;
- }
-// Finally say OK.
- out.println("OK Nickname set to " + Arg);
- }
- } else if (Command.equals(C_inport)) {
- // Set the NamedDB inbound TO the router port
- // app --> BOB
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- int prt;
- try {
- wlock();
- } catch (Exception ex) {
- break die;
- }
-
- try {
- nickinfo.kill(P_INPORT);
- } catch (Exception ex) {
+ } else if (Command.equals(C_outhost)) {
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
try {
- wunlock();
- } catch (Exception ee) {
+ wlock();
+ } catch (Exception ex) {
break die;
}
-
- break die;
- }
- try {
- prt = Integer.parseInt(Arg);
- if (prt > 1 && prt < 65536) {
+ try {
+ nickinfo.add(P_OUTHOST, Arg);
+ } catch (Exception ex) {
try {
- nickinfo.add(P_INPORT, new Integer(prt));
- } catch (Exception ex) {
- try {
- wunlock();
- } catch (Exception ee) {
- break die;
- }
-
+ wunlock();
+ } catch (Exception ee) {
break die;
}
- }
-
- } catch (NumberFormatException nfe) {
- out.println("ERROR not a number");
- }
-
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- rlock();
- } catch (Exception ex) {
- break die;
- }
-
- try {
- ip = nickinfo.exists(P_INPORT);
- } catch (Exception ex) {
- try {
- runlock();
- } catch (Exception ee) {
break die;
}
- break die;
- }
- try {
- runlock();
- } catch (Exception ex) {
- break die;
- }
-
- if (ip) {
- out.println("OK inbound port set");
- } else {
- out.println("ERROR port out of range");
- }
-
- }
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- nns(out);
- }
-
- } else if (Command.equals(C_outport)) {
- // Set the NamedDB outbound FROM the router port
- // BOB --> app
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- int prt;
- try {
- wlock();
- } catch (Exception ex) {
- break die;
- }
-
- try {
- nickinfo.kill(P_OUTPORT);
- } catch (Exception ex) {
try {
wunlock();
- } catch (Exception ee) {
+ } catch (Exception ex) {
break die;
}
- break die;
- }
- try {
- prt = Integer.parseInt(Arg);
- if (prt > 1 && prt < 65536) {
- try {
- nickinfo.add(P_OUTPORT, new Integer(prt));
- } catch (Exception ex) {
- try {
- wunlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
- }
- } catch (NumberFormatException nfe) {
- out.println("ERROR not a number");
+ out.println("OK outhost set");
}
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- rlock();
- } catch (Exception ex) {
- break die;
- }
-
- try {
- ip = nickinfo.exists(P_OUTPORT);
- } catch (Exception ex) {
- try {
- runlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
- try {
- runlock();
- } catch (Exception ex) {
- break die;
- }
-
- if (ip) {
- out.println("OK outbound port set");
- } else {
- out.println("ERROR port out of range");
- }
-
- }
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception ex) {
- break die;
- }
- }
-
- } else if (Command.equals(C_inhost)) {
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- try {
- wlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickinfo.add(P_INHOST, Arg);
- } catch (Exception ex) {
- try {
- wunlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
-
- out.println("OK inhost set");
- }
-
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception ex) {
- break die;
- }
- }
-
- } else if (Command.equals(C_outhost)) {
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- try {
- wlock();
- } catch (Exception ex) {
- break die;
- }
- try {
- nickinfo.add(P_OUTHOST, Arg);
- } catch (Exception ex) {
- try {
- wunlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
- try {
- wunlock();
- } catch (Exception ex) {
- break die;
- }
-
- out.println("OK outhost set");
- }
-
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception ex) {
- break die;
- }
- }
-
- } else if (Command.equals(C_show)) {
- // Get the current NamedDB properties
- if (ns) {
- out.print("OK");
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
-
- try {
- nickprint(out, nickinfo);
- } catch (Exception e) {
- try {
- runlock();
- } catch (Exception ee) {
+ } catch (Exception ex) {
break die;
}
- out.println(); // this will cause an IOE if IOE
- break die;
- }
-
- try {
- runlock();
- } catch (Exception e) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception e) {
- break die;
- }
- }
-
- } else if (Command.equals(C_show_props)) {
- // Get the current options properties
- if (ns) {
- out.print("OK");
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
-
- try {
- propprint(out, nickinfo);
- } catch (Exception e) {
+ } else {
try {
- runlock();
- } catch (Exception ee) {
+ nns(out);
+ } catch (Exception ex) {
break die;
}
-
- out.println(); // this will cause an IOE if IOE
- break die;
}
- try {
- runlock();
- } catch (Exception e) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception e) {
- break die;
- }
- }
-
- } else if (Command.equals(C_start)) {
- // Start the tunnel, if we have all the information
- if (ns && dk && (ip || op)) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- MUXlisten tunnel;
- try {
- while (!lock.compareAndSet(false, true)) {
- // wait
- }
- tunnel = new MUXlisten(lock, database, nickinfo, _log);
- Thread t = new Thread(tunnel);
- t.start();
- // try {
- // Thread.sleep(1000 * 10); // Slow down the startup.
- // } catch(InterruptedException ie) {
- // // ignore it
- // }
- out.println("OK tunnel starting");
- } catch (I2PException e) {
- lock.set(false);
- out.println("ERROR starting tunnel: " + e);
- } catch (IOException e) {
- lock.set(false);
- out.println("ERROR starting tunnel: " + e);
- }
- }
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- out.println("ERROR tunnel settings incomplete");
- }
-
- } else if (Command.equals(C_stop)) {
- // Stop the tunnel, if it is running
- if (ns) {
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
-
- try {
- if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
- try {
- runlock();
- } catch (Exception e) {
- break die;
- }
-
- try {
- wlock();
- } catch (Exception e) {
- break die;
- }
-
- nickinfo.add(P_STOPPING, new Boolean(true));
- try {
- wunlock();
-
- } catch (Exception e) {
- break die;
- }
-
- out.println("OK tunnel stopping");
- } else {
- try {
- runlock();
- } catch (Exception e) {
- break die;
- }
-
- out.println("ERROR tunnel is inactive");
- }
- } catch (Exception e) {
+ } else if (Command.equals(C_show)) {
+ // Get the current NamedDB properties
+ if (ns) {
+ out.print("OK");
try {
- runlock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception e) {
- break die;
- }
- }
-
- } else if (Command.equals(C_clear)) {
- // Clear use of the NamedDB if stopped
- if (ns) {
- try {
- if (tunnelactive(nickinfo)) {
- out.println("ERROR tunnel is active");
- } else {
- try {
- database.getWriteLock();
- } catch (Exception e) {
- break die;
- }
- try {
- database.kill(nickinfo.get(P_NICKNAME));
- } catch (Exception e) {
- try {
- database.releaseWriteLock();
- } catch (Exception ee) {
- break die;
- }
- break die;
- }
- try {
- database.releaseWriteLock();
- } catch (Exception e) {
- break die;
- }
- dk = ns = ip = op = false;
- out.println("OK cleared");
- }
-
- } catch (Exception ex) {
- break die;
- }
-
- } else {
- try {
- nns(out);
- } catch (Exception e) {
- break die;
- }
- }
-
- } else if (Command.equals(C_status)) {
- try {
- if (database.exists(Arg)) {
- // Show status of a NamedDB
- out.print("OK ");
- try {
- ttlpnt(out, Arg);
+ rlock();
} catch (Exception e) {
+ break die;
+ }
+
+ try {
+ nickprint(out, nickinfo);
+ } catch (Exception e) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+
out.println(); // this will cause an IOE if IOE
break die;
}
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+
} else {
try {
nns(out);
@@ -1427,27 +1235,229 @@ public class DoCMDS implements Runnable {
break die;
}
}
- } catch (Exception e) {
- break die;
+
+ } else if (Command.equals(C_show_props)) {
+ // Get the current options properties
+ if (ns) {
+ out.print("OK");
+ try {
+ rlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ try {
+ propprint(out, nickinfo);
+ } catch (Exception e) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+
+ out.println(); // this will cause an IOE if IOE
+ break die;
+ }
+
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception e) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_start)) {
+ // Start the tunnel, if we have all the information
+ if (ns && dk && (ip || op)) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ MUXlisten tunnel;
+ try {
+ while (!lock.compareAndSet(false, true)) {
+ // wait
+ }
+ tunnel = new MUXlisten(lock, database, nickinfo, _log);
+ Thread t = new Thread(tunnel);
+ t.start();
+ // try {
+ // Thread.sleep(1000 * 10); // Slow down the startup.
+ // } catch(InterruptedException ie) {
+ // // ignore it
+ // }
+ out.println("OK tunnel starting");
+ } catch (I2PException e) {
+ lock.set(false);
+ out.println("ERROR starting tunnel: " + e);
+ } catch (IOException e) {
+ lock.set(false);
+ out.println("ERROR starting tunnel: " + e);
+ }
+ }
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ out.println("ERROR tunnel settings incomplete");
+ }
+
+ } else if (Command.equals(C_stop)) {
+ // Stop the tunnel, if it is running
+ if (ns) {
+ try {
+ rlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ try {
+ if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ try {
+ wlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ nickinfo.add(P_STOPPING, new Boolean(true));
+ try {
+ wunlock();
+
+ } catch (Exception e) {
+ break die;
+ }
+
+ out.println("OK tunnel stopping");
+ } else {
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ out.println("ERROR tunnel is inactive");
+ }
+ } catch (Exception e) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception e) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_clear)) {
+ // Clear use of the NamedDB if stopped
+ if (ns) {
+ try {
+ if (tunnelactive(nickinfo)) {
+ out.println("ERROR tunnel is active");
+ } else {
+ try {
+ database.getWriteLock();
+ } catch (Exception e) {
+ break die;
+ }
+ try {
+ database.kill(nickinfo.get(P_NICKNAME));
+ } catch (Exception e) {
+ try {
+ database.releaseWriteLock();
+ } catch (Exception ee) {
+ break die;
+ }
+ break die;
+ }
+ try {
+ database.releaseWriteLock();
+ } catch (Exception e) {
+ break die;
+ }
+ dk = ns = ip = op = false;
+ out.println("OK cleared");
+ }
+
+ } catch (Exception ex) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception e) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_status)) {
+ try {
+ if (database.exists(Arg)) {
+ // Show status of a NamedDB
+ out.print("OK ");
+ try {
+ ttlpnt(out, Arg);
+ } catch (Exception e) {
+ out.println(); // this will cause an IOE if IOE
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception e) {
+ break die;
+ }
+ }
+ } catch (Exception e) {
+ break die;
+ }
+
+ } else {
+ out.println("ERROR UNKNOWN COMMAND! Try help");
}
- } else {
- out.println("ERROR UNKNOWN COMMAND! Try help");
}
-
}
- }
- } // die
- out.print("ERROR A really bad error just happened, ");
- } // quit
+ } // die
+ out.print("ERROR A really bad error just happened, ");
+ } // quit
// Say goodbye.
- out.println("OK Bye!");
+ out.println("OK Bye!");
- server.close();
- } catch (IOException ioe) {
- BOB.warn("IOException on socket listen: " + ioe);
- ioe.printStackTrace();
+ } catch (IOException ioe) {
+ // not really needed, except to debug.
+ // BOB.warn("IOException on socket listen: " + ioe);
+ // ioe.printStackTrace();
+ }
+ } finally {
+ try {
+ server.close();
+ } catch (IOException ex) {
+ // nop
+ }
}
}
// Debugging... None of this is normally used.
@@ -1481,7 +1491,7 @@ public class DoCMDS implements Runnable {
for (int i = 0; i < numThreads; i++) {
// Get thread
Thread thread = threads[i];
- System.out.println("BOB: " + indent + tn + ": " +thread.toString());
+ System.out.println("BOB: " + indent + tn + ": " + thread.toString());
}
// Get thread subgroups of `group'
diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java
index b8d9145f2..e55e54b9d 100644
--- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java
+++ b/apps/BOB/src/net/i2p/BOB/I2Plistener.java
@@ -25,6 +25,7 @@ package net.i2p.BOB;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
@@ -43,6 +44,7 @@ public class I2Plistener implements Runnable {
// private int tgwatch;
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
+ private AtomicBoolean lives;
/**
* Constructor
@@ -52,13 +54,14 @@ public class I2Plistener implements Runnable {
* @param database
* @param _log
*/
- I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
+ I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Log _log, AtomicBoolean lives) {
this.database = database;
this.info = info;
this._log = _log;
this.socketManager = S;
- serverSocket = SS;
+ this.serverSocket = SS;
// tgwatch = 1;
+ this.lives = lives;
}
private void rlock() throws Exception {
@@ -82,27 +85,10 @@ public class I2Plistener implements Runnable {
try {
die:
{
+ try {
+ serverSocket.setSoTimeout(50);
- serverSocket.setSoTimeout(50);
- boolean spin = true;
- while (spin) {
-
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
- try {
- spin = info.get("RUNNING").equals(Boolean.TRUE);
- } catch (Exception e) {
- try {
- runlock();
- } catch (Exception e2) {
- break die;
- }
- break die;
- }
- try {
+ while (lives.get()) {
try {
sessSocket = serverSocket.accept();
g = true;
@@ -115,14 +101,15 @@ public class I2Plistener implements Runnable {
g = false;
conn++;
// toss the connection to a new thread.
- I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database);
+ I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
t.start();
}
- } catch (Exception e) {
- // System.out.println("Exception " + e);
}
+ } catch (I2PException e) {
+ // bad shit
+ System.out.println("Exception " + e);
}
}
} finally {
diff --git a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
index 5df1f3e0e..85dcf5b41 100644
--- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
+++ b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
@@ -26,6 +26,7 @@ package net.i2p.BOB;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
+import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.client.streaming.I2PSocket;
/**
@@ -38,6 +39,7 @@ public class I2PtoTCP implements Runnable {
private I2PSocket I2P;
private NamedDB info, database;
private Socket sock;
+ private AtomicBoolean lives;
/**
* Constructor
@@ -46,10 +48,11 @@ public class I2PtoTCP implements Runnable {
* @param info
* @param database
*/
- I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database) {
+ I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database, AtomicBoolean lives) {
this.I2P = I2Psock;
this.info = info;
this.database = database;
+ this.lives = lives;
}
private void rlock() {
@@ -113,35 +116,19 @@ public class I2PtoTCP implements Runnable {
out.flush(); // not really needed, but...
}
// setup to cross the streams
- TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P
- TCPio conn_a = new TCPio(Iin, out /* , info, database */); // I2P -> app
+ TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
+ TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire!
t.start();
q.start();
- boolean spin = true;
- while (t.isAlive() && q.isAlive() && spin) { // AND is used here to kill off the other thread
+ while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
try {
Thread.sleep(10); //sleep for 10 ms
} catch (InterruptedException e) {
break die;
}
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
- try {
- spin = info.get("RUNNING").equals(Boolean.TRUE);
- } catch (Exception e) {
- try {
- runlock();
- } catch (Exception e2) {
- break die;
- }
- break die;
- }
}
// System.out.println("I2PtoTCP: Going away...");
} catch (Exception e) {
@@ -150,14 +137,6 @@ public class I2PtoTCP implements Runnable {
}
} // die
} finally {
- try {
- t.interrupt();
- } catch (Exception e) {
- }
- try {
- q.interrupt();
- } catch (Exception e) {
- }
try {
in.close();
} catch (Exception ex) {
@@ -174,6 +153,14 @@ public class I2PtoTCP implements Runnable {
Iout.close();
} catch (Exception ex) {
}
+ try {
+ t.interrupt();
+ } catch (Exception e) {
+ }
+ try {
+ q.interrupt();
+ } catch (Exception e) {
+ }
try {
// System.out.println("I2PtoTCP: Close I2P");
I2P.close();
diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java
index d13b8217b..ca7d64497 100644
--- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java
+++ b/apps/BOB/src/net/i2p/BOB/MUXlisten.java
@@ -43,7 +43,7 @@ import net.i2p.util.Log;
*/
public class MUXlisten implements Runnable {
- private NamedDB database, info;
+ private NamedDB database, info;
private Log _log;
private I2PSocketManager socketManager;
private ByteArrayInputStream prikey;
@@ -54,6 +54,7 @@ public class MUXlisten implements Runnable {
boolean go_out;
boolean come_in;
private AtomicBoolean lock;
+ private AtomicBoolean lives;
/**
* Constructor Will fail if INPORT is occupied.
@@ -65,47 +66,86 @@ public class MUXlisten implements Runnable {
* @throws java.io.IOException
*/
MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
- int port = 0;
- InetAddress host = null;
- this.lock = lock;
- this.tg = null;
- this.database = database;
- this.info = info;
- this._log = _log;
+ try {
+ int port = 0;
+ InetAddress host = null;
+ this.lock = lock;
+ this.tg = null;
+ this.database = database;
+ this.info = info;
+ this._log = _log;
+ lives = new AtomicBoolean(false);
- this.database.getReadLock();
- this.info.getReadLock();
- N = this.info.get("NICKNAME").toString();
- prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
- // Make a new copy so that anything else won't muck with our database.
- Properties R = (Properties) info.get("PROPERTIES");
- Properties Q = new Properties();
- Lifted.copyProperties(R, Q);
- this.database.releaseReadLock();
- this.info.releaseReadLock();
+ this.database.getWriteLock();
+ this.info.getWriteLock();
+ this.info.add("STARTING", new Boolean(true));
+ this.info.releaseWriteLock();
+ this.database.releaseWriteLock();
+ this.database.getReadLock();
+ this.info.getReadLock();
- this.database.getReadLock();
- this.info.getReadLock();
- this.go_out = info.exists("OUTPORT");
- this.come_in = info.exists("INPORT");
- if (this.come_in) {
- port = Integer.parseInt(info.get("INPORT").toString());
- host = InetAddress.getByName(info.get("INHOST").toString());
+ N = this.info.get("NICKNAME").toString();
+ prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
+ // Make a new copy so that anything else won't muck with our database.
+ Properties R = (Properties) info.get("PROPERTIES");
+ Properties Q = new Properties();
+ Lifted.copyProperties(R, Q);
+ this.database.releaseReadLock();
+ this.info.releaseReadLock();
+
+ this.database.getReadLock();
+ this.info.getReadLock();
+ this.go_out = info.exists("OUTPORT");
+ this.come_in = info.exists("INPORT");
+ if (this.come_in) {
+ port = Integer.parseInt(info.get("INPORT").toString());
+ host = InetAddress.getByName(info.get("INHOST").toString());
+ }
+ this.database.releaseReadLock();
+ this.info.releaseReadLock();
+
+ socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
+ if (this.come_in) {
+ this.listener = new ServerSocket(port, backlog, host);
+ }
+ // I2PException, IOException, RuntimeException
+ // To bad we can't just catch and enumerate....
+ // } catch (I2PException e) {
+ // Something went bad.
+ // this.database.getWriteLock();
+ // this.info.getWriteLock();
+ // this.info.add("STARTING", new Boolean(false));
+ // this.info.releaseWriteLock();
+ // this.database.releaseWriteLock();
+ // throw new I2PException(e);
+ } catch (IOException e) {
+ // Something went bad.
+ this.database.getWriteLock();
+ this.info.getWriteLock();
+ this.info.add("STARTING", new Boolean(false));
+ this.info.releaseWriteLock();
+ this.database.releaseWriteLock();
+ throw new IOException(e);
+ } catch (RuntimeException e) {
+ // Something went bad.
+ this.database.getWriteLock();
+ this.info.getWriteLock();
+ this.info.add("STARTING", new Boolean(false));
+ this.info.releaseWriteLock();
+ this.database.releaseWriteLock();
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ // Something else went bad.
+ this.database.getWriteLock();
+ this.info.getWriteLock();
+ this.info.add("STARTING", new Boolean(false));
+ this.info.releaseWriteLock();
+ this.database.releaseWriteLock();
+ // throw new Exception(e);
+ // Debugging, I guess.
+ e.printStackTrace();
+ throw new RuntimeException(e);
}
- this.database.releaseReadLock();
- this.info.releaseReadLock();
-
- socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
- if (this.come_in) {
- this.listener = new ServerSocket(port, backlog, host);
- }
-
- // Everything is OK as far as we can tell.
- this.database.getWriteLock();
- this.info.getWriteLock();
- this.info.add("STARTING", new Boolean(true));
- this.info.releaseWriteLock();
- this.database.releaseWriteLock();
}
private void rlock() throws Exception {
@@ -142,18 +182,22 @@ public class MUXlisten implements Runnable {
try {
info.add("RUNNING", new Boolean(true));
} catch (Exception e) {
+ lock.set(false);
wunlock();
return;
}
} catch (Exception e) {
+ lock.set(false);
return;
}
try {
wunlock();
} catch (Exception e) {
+ lock.set(false);
return;
}
// socketManager.addDisconnectListener(new DisconnectListener());
+ lives.set(true);
lock.set(false);
quit:
{
@@ -166,14 +210,14 @@ public class MUXlisten implements Runnable {
if (go_out) {
// I2P -> TCP
SS = socketManager.getServerSocket();
- I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log);
+ I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log, lives);
t = new Thread(tg, conn, "BOBI2Plistener " + N);
t.start();
}
if (come_in) {
// TCP -> I2P
- TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log);
+ TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log, lives);
q = new Thread(tg, conn, "BOBTCPlistener " + N);
q.start();
}
@@ -195,7 +239,7 @@ public class MUXlisten implements Runnable {
break quit;
}
boolean spin = true;
- while (spin) {
+ while (spin && lives.get()) {
try {
Thread.sleep(1000); //sleep for 1 second
} catch (InterruptedException e) {
@@ -226,26 +270,30 @@ public class MUXlisten implements Runnable {
}
} // quit
} finally {
- // Start cleanup.
- while (!lock.compareAndSet(false, true)) {
- // wait
+ lives.set(false);
+ // Some grace time.
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
}
-
- // zero out everything.
try {
wlock();
try {
info.add("STARTING", new Boolean(false));
- info.add("STOPPING", new Boolean(false));
+ info.add("STOPPING", new Boolean(true));
info.add("RUNNING", new Boolean(false));
} catch (Exception e) {
+ lock.set(false);
wunlock();
return;
}
wunlock();
} catch (Exception e) {
}
-
+ // Start cleanup.
+ while (!lock.compareAndSet(false, true)) {
+ // wait
+ }
if (SS != null) {
try {
SS.close();
@@ -261,11 +309,28 @@ public class MUXlisten implements Runnable {
// Some grace time.
try {
- Thread.sleep(250);
+ Thread.sleep(100);
} catch (InterruptedException ex) {
}
+ // zero out everything.
+ try {
+ wlock();
+ try {
+ info.add("STARTING", new Boolean(false));
+ info.add("STOPPING", new Boolean(false));
+ info.add("RUNNING", new Boolean(false));
+ } catch (Exception e) {
+ lock.set(false);
+ wunlock();
+ return;
+ }
+ wunlock();
+ } catch (Exception e) {
+ }
+
lock.set(false); // Should we force waiting for all threads??
+
// Wait around till all threads are collected.
if (tg != null) {
String boner = tg.getName();
@@ -276,7 +341,7 @@ public class MUXlisten implements Runnable {
// visit(tg, 0, boner);
int foo = tg.activeCount() + tg.activeGroupCount();
// hopefully no longer needed!
- // int bar = foo;
+ // int bar = lives;
// System.out.println("BOB: MUXlisten: Waiting on threads for " + boner);
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
// visit(tg, 0, boner);
@@ -284,12 +349,12 @@ public class MUXlisten implements Runnable {
// Happily spin forever :-(
while (foo != 0) {
foo = tg.activeCount() + tg.activeGroupCount();
- // if (foo != bar && foo != 0) {
+ // if (lives != bar && lives != 0) {
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
// visit(tg, 0, boner);
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n");
// }
- // bar = foo;
+ // bar = lives;
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch (InterruptedException ex) {
@@ -356,5 +421,4 @@ public class MUXlisten implements Runnable {
visit(groups[i], level + 1, groups[i].getName());
}
}
-
}
diff --git a/apps/BOB/src/net/i2p/BOB/Main.java b/apps/BOB/src/net/i2p/BOB/Main.java
index aa56e83e0..53a7d9e71 100644
--- a/apps/BOB/src/net/i2p/BOB/Main.java
+++ b/apps/BOB/src/net/i2p/BOB/Main.java
@@ -26,6 +26,7 @@ package net.i2p.BOB;
import net.i2p.client.streaming.RetransmissionTimer;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer2;
+
/**
* Start from command line
*
diff --git a/apps/BOB/src/net/i2p/BOB/NamedDB.java b/apps/BOB/src/net/i2p/BOB/NamedDB.java
index 8b0ba35df..b5189647b 100644
--- a/apps/BOB/src/net/i2p/BOB/NamedDB.java
+++ b/apps/BOB/src/net/i2p/BOB/NamedDB.java
@@ -43,10 +43,10 @@ public class NamedDB {
}
synchronized public void getReadLock() {
- while((writersWaiting != 0)) {
+ while ((writersWaiting != 0)) {
try {
wait();
- } catch(InterruptedException ie) {
+ } catch (InterruptedException ie) {
}
}
readers++;
@@ -59,10 +59,10 @@ public class NamedDB {
synchronized public void getWriteLock() {
writersWaiting++;
- while(readers != 0 && writersWaiting != 1 ) {
+ while (readers != 0 && writersWaiting != 1) {
try {
wait();
- } catch(InterruptedException ie) {
+ } catch (InterruptedException ie) {
}
}
}
@@ -79,8 +79,8 @@ public class NamedDB {
* @throws ArrayIndexOutOfBoundsException when key does not exist
*/
public int idx(Object key) throws ArrayIndexOutOfBoundsException {
- for(int i = 0; i < index; i++) {
- if(key.equals(data[i][0])) {
+ for (int i = 0; i < index; i++) {
+ if (key.equals(data[i][0])) {
return i;
}
}
@@ -100,17 +100,17 @@ public class NamedDB {
try {
k = idx(key);
- } catch(ArrayIndexOutOfBoundsException b) {
+ } catch (ArrayIndexOutOfBoundsException b) {
return;
}
olddata = new Object[index + 2][2];
// copy to olddata, skipping 'k'
- for(i = 0 , l = 0; l < index; i++, l++) {
- if(i == k) {
+ for (i = 0, l = 0; l < index; i++, l++) {
+ if (i == k) {
l++;
didsomething++;
}
- for(j = 0; j < 2; j++) {
+ for (j = 0; j < 2; j++) {
olddata[i][j] = data[l][j];
}
}
@@ -132,13 +132,13 @@ public class NamedDB {
olddata = new Object[index + 2][2];
// copy to olddata
- for(i = 0; i < index; i++) {
- for(j = 0; j < 2; j++) {
+ for (i = 0; i < index; i++) {
+ for (j = 0; j < 2; j++) {
olddata[i][j] = data[i][j];
}
}
data = olddata;
- data[index++] = new Object[] {key, val};
+ data[index++] = new Object[]{key, val};
}
/**
@@ -149,8 +149,8 @@ public class NamedDB {
* @throws java.lang.RuntimeException
*/
public Object get(Object key) throws RuntimeException {
- for(int i = 0; i < index; i++) {
- if(key.equals(data[i][0])) {
+ for (int i = 0; i < index; i++) {
+ if (key.equals(data[i][0])) {
return data[i][1];
}
}
@@ -164,8 +164,8 @@ public class NamedDB {
* @return true if an object exists, else returns false
*/
public boolean exists(Object key) {
- for(int i = 0; i < index; i++) {
- if(key.equals(data[i][0])) {
+ for (int i = 0; i < index; i++) {
+ if (key.equals(data[i][0])) {
return true;
}
}
@@ -180,7 +180,7 @@ public class NamedDB {
* @throws java.lang.RuntimeException
*/
public Object getnext(int i) throws RuntimeException {
- if(i < index && i > -1) {
+ if (i < index && i > -1) {
return data[i][1];
}
throw new RuntimeException("No more data");
diff --git a/apps/BOB/src/net/i2p/BOB/TCPio.java b/apps/BOB/src/net/i2p/BOB/TCPio.java
index 99d408c43..d501759ef 100644
--- a/apps/BOB/src/net/i2p/BOB/TCPio.java
+++ b/apps/BOB/src/net/i2p/BOB/TCPio.java
@@ -26,6 +26,7 @@ package net.i2p.BOB;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Shove data from one stream to the other.
@@ -36,7 +37,7 @@ public class TCPio implements Runnable {
private InputStream Ain;
private OutputStream Aout;
- // private NamedDB info, database;
+ private AtomicBoolean lives;
/**
* Constructor
@@ -46,11 +47,10 @@ public class TCPio implements Runnable {
*
* param database
*/
- TCPio(InputStream Ain, OutputStream Aout /*, NamedDB info , NamedDB database */) {
+ TCPio(InputStream Ain, OutputStream Aout, AtomicBoolean lives) {
this.Ain = Ain;
this.Aout = Aout;
- // this.info = info;
- // this.database = database;
+ this.lives = lives;
}
/**
@@ -84,10 +84,9 @@ public class TCPio implements Runnable {
int b;
byte a[] = new byte[1];
- boolean spin = true;
try {
try {
- while (spin) {
+ while (lives.get()) {
b = Ain.read(a, 0, 1);
if (b > 0) {
Aout.write(a, 0, b);
@@ -105,9 +104,6 @@ public class TCPio implements Runnable {
*
*/
// System.out.println("TCPio: End Of Stream");
- // Ain.close();
- // Aout.close();
- //return;
break;
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java
index 9155cb82b..b5addc27b 100644
--- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java
+++ b/apps/BOB/src/net/i2p/BOB/TCPlistener.java
@@ -29,6 +29,7 @@ import java.net.Socket;
import java.net.SocketTimeoutException;
// import net.i2p.client.I2PSession;
// import net.i2p.client.I2PSessionException;
+import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log;
@@ -45,6 +46,7 @@ public class TCPlistener implements Runnable {
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
private ServerSocket listener;
+ private AtomicBoolean lives;
/**
* Constructor
@@ -53,12 +55,13 @@ public class TCPlistener implements Runnable {
* @param database
* @param _log
*/
- TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
+ TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log, AtomicBoolean lives) {
this.database = database;
this.info = info;
this._log = _log;
this.socketManager = S;
this.listener = listener;
+ this.lives = lives;
}
private void rlock() throws Exception {
@@ -77,7 +80,6 @@ public class TCPlistener implements Runnable {
*/
public void run() {
boolean g = false;
- boolean spin = true;
int conn = 0;
try {
die:
@@ -85,22 +87,7 @@ public class TCPlistener implements Runnable {
try {
Socket server = new Socket();
listener.setSoTimeout(50); // We don't block, we cycle and check.
- while (spin) {
- try {
- rlock();
- } catch (Exception e) {
- break die;
- }
- try {
- spin = info.get("RUNNING").equals(Boolean.TRUE);
- } catch (Exception e) {
- try {
- runlock();
- } catch (Exception e2) {
- break die;
- }
- break die;
- }
+ while (lives.get()) {
try {
server = listener.accept();
g = true;
@@ -110,7 +97,7 @@ public class TCPlistener implements Runnable {
if (g) {
conn++;
// toss the connection to a new thread.
- TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database);
+ TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
t.start();
g = false;
diff --git a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
index 2073e0e69..a4a851c54 100644
--- a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
+++ b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
@@ -30,6 +30,7 @@ import java.io.OutputStream;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.Socket;
+import java.util.concurrent.atomic.AtomicBoolean;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
@@ -49,6 +50,7 @@ public class TCPtoI2P implements Runnable {
private NamedDB info, database;
private Socket sock;
private I2PSocketManager socketManager;
+ private AtomicBoolean lives;
/**
* Constructor
@@ -57,11 +59,12 @@ public class TCPtoI2P implements Runnable {
* param info
* param database
*/
- TCPtoI2P(I2PSocketManager i2p, Socket socket , NamedDB info, NamedDB database) {
+ TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database, AtomicBoolean lives) {
this.sock = socket;
this.info = info;
this.database = database;
this.socketManager = i2p;
+ this.lives = lives;
}
/**
@@ -157,19 +160,15 @@ public class TCPtoI2P implements Runnable {
Iin = I2P.getInputStream();
Iout = I2P.getOutputStream();
// setup to cross the streams
- TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P
- TCPio conn_a = new TCPio(Iin, out /*, info, database */); // I2P -> app
+ TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
+ TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire!
t.start();
q.start();
- boolean spin = true;
- while (t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
+ while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
Thread.sleep(10); //sleep for 10 ms
- rlock();
- spin = info.get("RUNNING").equals(Boolean.TRUE);
- runlock();
}
} catch (I2PException e) {
Emsg(e.toString(), out);
diff --git a/apps/BOB/src/net/i2p/BOB/UDPIOthread.java b/apps/BOB/src/net/i2p/BOB/UDPIOthread.java
index 687fe8089..ff1a1f1ab 100644
--- a/apps/BOB/src/net/i2p/BOB/UDPIOthread.java
+++ b/apps/BOB/src/net/i2p/BOB/UDPIOthread.java
@@ -78,26 +78,26 @@ public class UDPIOthread implements I2PSessionListener, Runnable {
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
- while(up) {
+ while (up) {
int c = in.read(data);
// Note: could do a loopback test here with a wrapper.
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
- if(!ok) {
+ if (!ok) {
up = false; // Is this the right thing to do??
}
}
- } catch(IOException ioe) {
+ } catch (IOException ioe) {
_log.error("Error running", ioe);
- } catch(I2PSessionException ise) {
+ } catch (I2PSessionException ise) {
_log.error("Error communicating", ise);
// } catch(DataFormatException dfe) {
// _log.error("Peer destination file is not valid", dfe);
} finally {
- if(_session != null) {
+ if (_session != null) {
try {
_session.destroySession();
- } catch(I2PSessionException ise) {
+ } catch (I2PSessionException ise) {
// ignored
}
}
@@ -116,9 +116,9 @@ public class UDPIOthread implements I2PSessionListener, Runnable {
byte msg[] = session.receiveMessage(msgId);
out.write(msg);
out.flush();
- } catch(I2PSessionException ise) {
+ } catch (I2PSessionException ise) {
up = false;
- } catch(IOException ioe) {
+ } catch (IOException ioe) {
up = false;
}
}
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
index 662fd9e57..41d49af03 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java
@@ -20,15 +20,15 @@ class I2PServerSocketImpl implements I2PServerSocket {
private final static Log _log = new Log(I2PServerSocketImpl.class);
private I2PSocketManager mgr;
/** list of sockets waiting for the client to accept them */
- private List pendingSockets = Collections.synchronizedList(new ArrayList(4));
+ private final List pendingSockets = Collections.synchronizedList(new ArrayList(4));
/** have we been closed */
private volatile boolean closing = false;
/** lock on this when accepting a pending socket, and wait on it for notification of acceptance */
- private Object socketAcceptedLock = new Object();
+ private final Object socketAcceptedLock = new Object();
/** lock on this when adding a new socket to the pending list, and wait on it accordingly */
- private Object socketAddedLock = new Object();
+ private final Object socketAddedLock = new Object();
/**
* Set Sock Option accept timeout stub, does nothing in ministreaming
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java
index b40b9091f..7015f0a9d 100644
--- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java
@@ -40,15 +40,15 @@ import net.i2p.util.Log;
class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener {
private I2PAppContext _context;
private Log _log;
- private I2PSession _session;
+ private /* final */ I2PSession _session;
private I2PServerSocketImpl _serverSocket = null;
- private Object lock = new Object(); // for locking socket lists
+ private final Object lock = new Object(); // for locking socket lists
private HashMap _outSockets;
private HashMap _inSockets;
private I2PSocketOptions _defaultOptions;
private long _acceptTimeout;
private String _name;
- private List _listeners;
+ private final List _listeners = new ArrayList(1);;
private static int __managerId = 0;
public static final short ACK = 0x51;
@@ -79,7 +79,7 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener {
_inSockets = new HashMap(16);
_outSockets = new HashMap(16);
_acceptTimeout = ACCEPT_TIMEOUT_DEFAULT;
- _listeners = new ArrayList(1);
+ // _listeners = new ArrayList(1);
setSession(session);
setDefaultOptions(buildOptions(opts));
_context.statManager().createRateStat("streaming.lifetime", "How long before the socket is closed?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
index 157e48793..b904243b1 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/I2PSocketManagerFull.java
@@ -230,8 +230,8 @@ public class I2PSocketManagerFull implements I2PSocketManager {
*
*/
public void destroySocketManager() {
- _connectionManager.disconnectAllHard();
_connectionManager.setAllowIncomingConnections(false);
+ _connectionManager.disconnectAllHard();
// should we destroy the _session too?
// yes, since the old lib did (and SAM wants it to, and i dont know why not)
if ( (_session != null) && (!_session.isClosed()) ) {
diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java
index a5d8ed94d..5be6d2a6b 100644
--- a/core/java/src/net/i2p/client/I2PSessionImpl.java
+++ b/core/java/src/net/i2p/client/I2PSessionImpl.java
@@ -101,7 +101,12 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
private boolean _dateReceived;
/** lock that we wait upon, that the SetDateMessageHandler notifies */
private final Object _dateReceivedLock = new Object();
-
+
+ /** whether the session connection is in the process of being opened */
+ protected boolean _opening;
+
+ /** monitor for waiting until opened */
+ private final Object _openingWait = new Object();
/**
* thread that we tell when new messages are available who then tells us
* to fetch them. The point of this is so that the fetch doesn't block the
@@ -136,6 +141,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
_log = context.logManager().getLog(I2PSessionImpl.class);
_handlerMap = new I2PClientMessageHandlerMap(context);
_closed = true;
+ _opening = false;
_closing = false;
_producer = new I2CPMessageProducer(context);
_availabilityNotifier = new AvailabilityNotifier();
@@ -212,6 +218,17 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
return _leaseSet;
}
+ void setOpening(boolean ls) {
+ _opening = ls;
+ synchronized (_openingWait) {
+ _openingWait.notifyAll();
+ }
+ }
+
+ boolean getOpening() {
+ return _opening;
+ }
+
/**
* Load up the destKeyFile for our Destination, PrivateKey, and SigningPrivateKey
*
@@ -235,6 +252,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
* not reachable
*/
public void connect() throws I2PSessionException {
+ setOpening(true);
_closed = false;
_availabilityNotifier.stopNotifying();
I2PThread notifier = new I2PThread(_availabilityNotifier);
@@ -294,11 +312,14 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
+ (connected - startConnect)
+ "ms - ready to participate in the network!");
startIdleMonitor();
+ setOpening(false);
} catch (UnknownHostException uhe) {
_closed = true;
+ setOpening(false);
throw new I2PSessionException(getPrefix() + "Invalid session configuration", uhe);
} catch (IOException ioe) {
_closed = true;
+ setOpening(false);
throw new I2PSessionException(getPrefix() + "Problem connecting to " + _hostname + " on port " + _portNum, ioe);
}
}
@@ -547,13 +568,28 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
}
/**
- * Tear down the session, and do NOT reconnect
+ * Tear down the session, and do NOT reconnect.
+ *
+ * Blocks if session has not been fully started.
*/
public void destroySession() {
destroySession(true);
}
+ /**
+ * Tear down the session, and do NOT reconnect.
+ *
+ * Blocks if session has not been fully started.
+ */
public void destroySession(boolean sendDisconnect) {
+ while (_opening) {
+ synchronized (_openingWait) {
+ try {
+ _openingWait.wait(1000);
+ } catch (InterruptedException ie) { // nop
+ }
+ }
+ }
if (_closed) return;
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "Destroy the session", new Exception("DestroySession()"));
diff --git a/history.txt b/history.txt
index c2ec1c391..f7210dba6 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,15 @@
+2009-07-16 sponge
+ * ministreaming:
+ - small pedantic fix
+ * streaming:
+ - Fix a deadly race condition.
+ - Some small pedantic fixes.
+ * core:
+ - Fix a deadly race condition.
+ * BOB:
+ - Fixed some races that occured from fixing races in streaming and core.
+ - Some badly needed code refactoring to depend less on the database.
+
2009-07-15 zzz
* Console:
- Make light the default theme
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 3e5e8985d..983dd2f06 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
- public final static long BUILD = 12;
+ public final static long BUILD = 13;
/** for example "-test" */
public final static String EXTRA = "";
public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;