I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 2f6ae994 authored by sponge's avatar sponge
Browse files

2009-06-05 sponge

    * BOB now cleans up tunnels, although they can take up to 5 minutes to
      disapear. This is due to the fact that the streaming lib doesn't
      actually remove the connections properly and kill them off when the
      manager is destroyed. I'm not certain if this is a bug, or a feature,
      but it sure is annoying, and you have to wait for the connections to
      time out. What should happen is the streaming lib should cause an IO
      error to the pending read or write.
parent 7725b9e8
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1"> <project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
<file>file:/root/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/BOB.java</file>
<file>file:/root/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/DoCMDS.java</file>
<file>file:/root/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/MUXlisten.java</file>
</open-files>
</project-private> </project-private>
...@@ -36,7 +36,6 @@ import net.i2p.I2PException; ...@@ -36,7 +36,6 @@ import net.i2p.I2PException;
import net.i2p.client.I2PClientFactory; import net.i2p.client.I2PClientFactory;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SimpleStore;
/** /**
* Simplistic command parser for BOB * Simplistic command parser for BOB
...@@ -98,6 +97,7 @@ public class DoCMDS implements Runnable { ...@@ -98,6 +97,7 @@ public class DoCMDS implements Runnable {
private static final String C_status = "status"; private static final String C_status = "status";
private static final String C_stop = "stop"; private static final String C_stop = "stop";
private static final String C_verify = "verify"; private static final String C_verify = "verify";
private static final String C_visit = "visit";
private static final String C_zap = "zap"; private static final String C_zap = "zap";
/* all the coomands available, plus description */ /* all the coomands available, plus description */
...@@ -124,6 +124,7 @@ public class DoCMDS implements Runnable { ...@@ -124,6 +124,7 @@ public class DoCMDS implements Runnable {
{C_status, C_status + " nickname * Display status of a nicknamed tunnel."}, {C_status, C_status + " nickname * Display status of a nicknamed tunnel."},
{C_stop, C_stop + " * Stops the current nicknamed tunnel."}, {C_stop, C_stop + " * Stops the current nicknamed tunnel."},
{C_verify, C_verify + " BASE64_key * Verifies BASE64 destination."}, {C_verify, C_verify + " BASE64_key * Verifies BASE64 destination."},
{C_visit, C_visit + " * Thread dump to wrapper.log."},
{C_zap, C_zap + " * Shuts down BOB."}, {C_zap, C_zap + " * Shuts down BOB."},
{"", "COMMANDS: " + // this is ugly, but... {"", "COMMANDS: " + // this is ugly, but...
C_help + " " + C_help + " " +
...@@ -148,13 +149,14 @@ public class DoCMDS implements Runnable { ...@@ -148,13 +149,14 @@ public class DoCMDS implements Runnable {
C_status + " " + C_status + " " +
C_stop + " " + C_stop + " " +
C_verify + " " + C_verify + " " +
C_visit + " " +
C_zap C_zap
}, },
{" ", " "} // end of list {" ", " "} // end of list
}; };
/** /**
* @parm LIVE * @param LIVE
* @param server * @param server
* @param props * @param props
* @param database * @param database
...@@ -438,6 +440,9 @@ public class DoCMDS implements Runnable { ...@@ -438,6 +440,9 @@ public class DoCMDS implements Runnable {
} }
} }
} else if (Command.equals(C_visit)) {
visitAllThreads();
out.println("OK ");
} else if (Command.equals(C_getdest)) { } else if (Command.equals(C_getdest)) {
if (ns) { if (ns) {
if (dk) { if (dk) {
...@@ -1274,7 +1279,7 @@ public class DoCMDS implements Runnable { ...@@ -1274,7 +1279,7 @@ public class DoCMDS implements Runnable {
} else { } else {
MUXlisten tunnel; MUXlisten tunnel;
try { try {
while(!lock.compareAndSet(false, true)) { while (!lock.compareAndSet(false, true)) {
// wait // wait
} }
tunnel = new MUXlisten(lock, database, nickinfo, _log); tunnel = new MUXlisten(lock, database, nickinfo, _log);
...@@ -1445,4 +1450,48 @@ public class DoCMDS implements Runnable { ...@@ -1445,4 +1450,48 @@ public class DoCMDS implements Runnable {
ioe.printStackTrace(); ioe.printStackTrace();
} }
} }
// Debugging... None of this is normally used.
/**
* Find the root thread group and print them all.
*
*/
private void visitAllThreads() {
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null) {
root = root.getParent();
}
// Visit each thread group
visit(root, 0, root.getName());
}
/**
* Recursively visits all thread groups under `group' and dumps them.
* @param group ThreadGroup to visit
* @param level Current level
*/
private static void visit(ThreadGroup group, int level, String tn) {
// Get threads in `group'
int numThreads = group.activeCount();
Thread[] threads = new Thread[numThreads * 2];
numThreads = group.enumerate(threads, false);
String indent = "------------------------------------".substring(0, level) + "-> ";
// Enumerate each thread in `group' and print it.
for (int i = 0; i < numThreads; i++) {
// Get thread
Thread thread = threads[i];
System.out.println("BOB: " + indent + tn + ": " +thread.toString());
}
// Get thread subgroups of `group'
int numGroups = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
numGroups = group.enumerate(groups, false);
// Recursively visit each subgroup
for (int i = 0; i < numGroups; i++) {
visit(groups[i], level + 1, groups[i].getName());
}
}
} }
...@@ -74,6 +74,8 @@ public class I2PtoTCP implements Runnable { ...@@ -74,6 +74,8 @@ public class I2PtoTCP implements Runnable {
OutputStream out = null; OutputStream out = null;
InputStream Iin = null; InputStream Iin = null;
OutputStream Iout = null; OutputStream Iout = null;
Thread t = null;
Thread q = null;
try { try {
die: die:
{ {
...@@ -113,17 +115,33 @@ public class I2PtoTCP implements Runnable { ...@@ -113,17 +115,33 @@ public class I2PtoTCP implements Runnable {
// setup to cross the streams // setup to cross the streams
TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P
TCPio conn_a = new TCPio(Iin, out /* , info, database */); // I2P -> app TCPio conn_a = new TCPio(Iin, out /* , info, database */); // I2P -> app
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA"); t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
Thread q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB"); q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire! // Fire!
t.start(); t.start();
q.start(); q.start();
while (t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread boolean spin = true;
while (t.isAlive() && q.isAlive() && spin) { // AND is used here to kill off the other thread
try { try {
Thread.sleep(10); //sleep for 10 ms Thread.sleep(10); //sleep for 10 ms
} catch (InterruptedException e) { } catch (InterruptedException e) {
break die; 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..."); // System.out.println("I2PtoTCP: Going away...");
} catch (Exception e) { } catch (Exception e) {
...@@ -132,6 +150,14 @@ public class I2PtoTCP implements Runnable { ...@@ -132,6 +150,14 @@ public class I2PtoTCP implements Runnable {
} }
} // die } // die
} finally { } finally {
try {
t.interrupt();
} catch (Exception e) {
}
try {
q.interrupt();
} catch (Exception e) {
}
try { try {
in.close(); in.close();
} catch (Exception ex) { } catch (Exception ex) {
......
...@@ -159,7 +159,6 @@ public class MUXlisten implements Runnable { ...@@ -159,7 +159,6 @@ public class MUXlisten implements Runnable {
{ {
try { try {
tg = new ThreadGroup(N); tg = new ThreadGroup(N);
die:
{ {
// toss the connections to a new threads. // toss the connections to a new threads.
// will wrap with TCP and UDP when UDP works // will wrap with TCP and UDP when UDP works
...@@ -185,22 +184,22 @@ public class MUXlisten implements Runnable { ...@@ -185,22 +184,22 @@ public class MUXlisten implements Runnable {
info.add("STARTING", new Boolean(false)); info.add("STARTING", new Boolean(false));
} catch (Exception e) { } catch (Exception e) {
wunlock(); wunlock();
break die; break quit;
} }
} catch (Exception e) { } catch (Exception e) {
break die; break quit;
} }
try { try {
wunlock(); wunlock();
} catch (Exception e) { } catch (Exception e) {
break die; break quit;
} }
boolean spin = true; boolean spin = true;
while (spin) { while (spin) {
try { try {
Thread.sleep(1000); //sleep for 1 second Thread.sleep(1000); //sleep for 1 second
} catch (InterruptedException e) { } catch (InterruptedException e) {
break die; break quit;
} }
try { try {
rlock(); rlock();
...@@ -208,35 +207,17 @@ public class MUXlisten implements Runnable { ...@@ -208,35 +207,17 @@ public class MUXlisten implements Runnable {
spin = info.get("STOPPING").equals(Boolean.FALSE); spin = info.get("STOPPING").equals(Boolean.FALSE);
} catch (Exception e) { } catch (Exception e) {
runlock(); runlock();
break die; break quit;
} }
} catch (Exception e) { } catch (Exception e) {
break die; break quit;
} }
try { try {
runlock(); runlock();
} catch (Exception e) { } catch (Exception e) {
break die; break quit;
} }
} }
/* cleared in the finally...
try {
wlock();
try {
info.add("RUNNING", new Boolean(false));
} catch (Exception e) {
wunlock();
break die;
}
} catch (Exception e) {
break die;
}
try {
wunlock();
} catch (Exception e) {
break die;
}
*/
} // die } // die
} catch (Exception e) { } catch (Exception e) {
...@@ -278,11 +259,6 @@ public class MUXlisten implements Runnable { ...@@ -278,11 +259,6 @@ public class MUXlisten implements Runnable {
} }
} }
try {
socketManager.destroySocketManager();
} catch (Exception e) {
// nop
}
// Some grace time. // Some grace time.
try { try {
Thread.sleep(250); Thread.sleep(250);
...@@ -293,25 +269,27 @@ public class MUXlisten implements Runnable { ...@@ -293,25 +269,27 @@ public class MUXlisten implements Runnable {
// Wait around till all threads are collected. // Wait around till all threads are collected.
if (tg != null) { if (tg != null) {
String boner = tg.getName(); String boner = tg.getName();
System.out.println("BOB: MUXlisten: Starting thread collection for: " + boner);
_log.warn("BOB: MUXlisten: Starting thread collection for: " + boner); _log.warn("BOB: MUXlisten: Starting thread collection for: " + boner);
// tg.interrupt(); // give my stuff a small smack again. // tg.interrupt(); // give my stuff a small smack again.
if (tg.activeCount() + tg.activeGroupCount() != 0) { if (tg.activeCount() + tg.activeGroupCount() != 0) {
visit(tg, 0, boner);
int foo = tg.activeCount() + tg.activeGroupCount(); int foo = tg.activeCount() + tg.activeGroupCount();
// hopefully no longer needed! // hopefully no longer needed!
// int bar = foo; int bar = foo;
// System.out.println("BOB: MUXlisten: Waiting on threads for " + boner); System.out.println("BOB: MUXlisten: Waiting on threads for " + boner);
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
// visit(tg, 0, boner); visit(tg, 0, boner);
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n"); System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n");
// Happily spin forever :-( // Happily spin forever :-(
while (foo != 0) { while (foo != 0) {
foo = tg.activeCount() + tg.activeGroupCount(); foo = tg.activeCount() + tg.activeGroupCount();
// if (foo != bar) { if (foo != bar && foo != 0) {
// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
// visit(tg, 0, boner); visit(tg, 0, boner);
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n"); System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n");
// } }
// bar = foo; bar = foo;
try { try {
Thread.sleep(100); //sleep for 100 ms (One tenth second) Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
...@@ -319,11 +297,18 @@ public class MUXlisten implements Runnable { ...@@ -319,11 +297,18 @@ public class MUXlisten implements Runnable {
} }
} }
} }
System.out.println("BOB: MUXlisten: Threads went away. Success: " + boner);
_log.warn("BOB: MUXlisten: Threads went away. Success: " + boner); _log.warn("BOB: MUXlisten: Threads went away. Success: " + boner);
tg.destroy(); tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it. // Zap reference to the ThreadGroup so the JVM can GC it.
tg = null; tg = null;
} }
try {
socketManager.destroySocketManager();
} catch (Exception e) {
// nop
}
} }
} }
......
...@@ -45,7 +45,7 @@ import net.i2p.i2ptunnel.I2PTunnel; ...@@ -45,7 +45,7 @@ import net.i2p.i2ptunnel.I2PTunnel;
public class TCPtoI2P implements Runnable { public class TCPtoI2P implements Runnable {
private I2PSocket I2P; private I2PSocket I2P;
// private NamedDB info, database; private NamedDB info, database;
private Socket sock; private Socket sock;
private I2PSocketManager socketManager; private I2PSocketManager socketManager;
...@@ -108,6 +108,16 @@ public class TCPtoI2P implements Runnable { ...@@ -108,6 +108,16 @@ public class TCPtoI2P implements Runnable {
out.flush(); out.flush();
} }
private void rlock() throws Exception {
database.getReadLock();
info.getReadLock();
}
private void runlock() throws Exception {
database.releaseReadLock();
info.releaseReadLock();
}
/** /**
* TCP stream to I2P stream thread starter * TCP stream to I2P stream thread starter
* *
...@@ -118,6 +128,8 @@ public class TCPtoI2P implements Runnable { ...@@ -118,6 +128,8 @@ public class TCPtoI2P implements Runnable {
OutputStream Iout = null; OutputStream Iout = null;
InputStream in = null; InputStream in = null;
OutputStream out = null; OutputStream out = null;
Thread t = null;
Thread q = null;
try { try {
try { try {
...@@ -145,15 +157,18 @@ public class TCPtoI2P implements Runnable { ...@@ -145,15 +157,18 @@ public class TCPtoI2P implements Runnable {
// setup to cross the streams // setup to cross the streams
TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P
TCPio conn_a = new TCPio(Iin, out /*, info, database */); // I2P -> app TCPio conn_a = new TCPio(Iin, out /*, info, database */); // I2P -> app
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA"); t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
Thread q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB"); q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire! // Fire!
t.start(); t.start();
q.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()) { // AND is used here to kill off the other thread
Thread.sleep(10); //sleep for 10 ms Thread.sleep(10); //sleep for 10 ms
rlock();
spin = info.get("RUNNING").equals(Boolean.TRUE);
runlock();
} }
} catch (I2PException e) { } catch (I2PException e) {
Emsg("ERROR " + e.toString(), out); Emsg("ERROR " + e.toString(), out);
} catch (ConnectException e) { } catch (ConnectException e) {
...@@ -171,6 +186,14 @@ public class TCPtoI2P implements Runnable { ...@@ -171,6 +186,14 @@ public class TCPtoI2P implements Runnable {
// bail on anything else // bail on anything else
} }
} finally { } finally {
try {
t.interrupt();
} catch (Exception e) {
}
try {
q.interrupt();
} catch (Exception e) {
}
try { try {
in.close(); in.close();
} catch (Exception e) { } catch (Exception e) {
......
2009-06-05 sponge
* BOB now cleans up tunnels, although they can take up to 5 minutes to
disapear. This is due to the fact that the streaming lib doesn't
actually remove the connections properly and kill them off when the
manager is destroyed. I'm not certain if this is a bug, or a feature,
but it sure is annoying, and you have to wait for the connections to
time out. What should happen is the streaming lib should cause an IO
error to the pending read or write.
2009-05-30 zzz 2009-05-30 zzz
* Console: * Console:
- config.jsp now cause graceful restart - config.jsp now cause graceful restart
......
...@@ -18,7 +18,7 @@ public class RouterVersion { ...@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 10; public final static long BUILD = 11;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";
public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment