2009-05-06 sponge

* Hopefully the last fixes for BOB.
    * Fixes to prevent race in client-side I2CP and Notifier.
This commit is contained in:
sponge
2009-05-06 05:34:33 +00:00
parent 7e3bda9d4d
commit eba6ca5430
9 changed files with 430 additions and 421 deletions

View File

@ -25,6 +25,8 @@ package net.i2p.BOB;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.i2p.I2PException; import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket; import net.i2p.client.streaming.I2PSocket;
@ -78,51 +80,59 @@ public class I2Plistener implements Runnable {
public void run() { public void run() {
boolean g = false; boolean g = false;
I2PSocket sessSocket = null; I2PSocket sessSocket = null;
int conn = 0;
try {
die:
{
die: { serverSocket.setSoTimeout(50);
boolean spin = true;
while (spin) {
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 { try {
runlock(); rlock();
} catch (Exception e2) { } catch (Exception e) {
break die; break die;
} }
break die;
}
try {
try { try {
sessSocket = serverSocket.accept(); spin = info.get("RUNNING").equals(Boolean.TRUE);
g = true; } catch (Exception e) {
} catch (ConnectException ce) { try {
g = false; runlock();
} catch (SocketTimeoutException ste) { } catch (Exception e2) {
g = false; break die;
} }
if (g) { break die;
g = false;
// toss the connection to a new thread.
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database);
Thread t = new Thread(conn_c, "BOBI2PtoTCP");
t.start();
} }
try {
try {
sessSocket = serverSocket.accept();
g = true;
} catch (ConnectException ce) {
g = false;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
g = false;
conn++;
// toss the connection to a new thread.
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
t.start();
}
} catch (Exception e) { } catch (Exception e) {
// System.out.println("Exception " + e); // System.out.println("Exception " + e);
}
} }
} }
} } finally {
try {
serverSocket.close();
} catch (I2PException ex) {
}
// System.out.println("I2Plistener: Close"); // System.out.println("I2Plistener: Close");
// System.out.println("I2Plistener: Done."); }
} }
} }

View File

@ -70,90 +70,99 @@ public class I2PtoTCP implements Runnable {
String host; String host;
int port; int port;
boolean tell; boolean tell;
die: { InputStream in = null;
try { OutputStream out = null;
InputStream Iin = null;
OutputStream Iout = null;
try {
die:
{
try { try {
rlock();
} catch(Exception e) {
break die;
}
try {
host = info.get("OUTHOST").toString();
port = Integer.parseInt(info.get("OUTPORT").toString());
tell = info.get("QUIET").equals(Boolean.FALSE);
} catch(Exception e) {
runlock();
break die;
}
try {
runlock();
} catch(Exception e) {
break die;
}
sock = new Socket(host, port);
// make readers/writers
InputStream in = sock.getInputStream();
OutputStream out = sock.getOutputStream();
InputStream Iin = I2P.getInputStream();
OutputStream Iout = I2P.getOutputStream();
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
if(tell) {
// tell who is connecting
out.write(I2P.getPeerDestination().toBase64().getBytes());
out.write(10); // nl
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
Thread t = new Thread(conn_c, "TCPioA");
Thread q = new Thread(conn_a, "TCPioB");
// Fire!
t.start();
q.start();
while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
try { try {
Thread.sleep(10); //sleep for 10 ms rlock();
} catch(InterruptedException e) { } catch (Exception e) {
break die;
}
try {
host = info.get("OUTHOST").toString();
port = Integer.parseInt(info.get("OUTPORT").toString());
tell = info.get("QUIET").equals(Boolean.FALSE);
} catch (Exception e) {
runlock();
break die;
}
try {
runlock();
} catch (Exception e) {
break die;
}
sock = new Socket(host, port);
// make readers/writers
in = sock.getInputStream();
out = sock.getOutputStream();
Iin = I2P.getInputStream();
Iout = I2P.getOutputStream();
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
if (tell) {
// tell who is connecting
out.write(I2P.getPeerDestination().toBase64().getBytes());
out.write(10); // nl
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
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
Thread q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire!
t.start();
q.start();
while (t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
try { try {
in.close(); Thread.sleep(10); //sleep for 10 ms
} catch(Exception ex) { } catch (InterruptedException e) {
} break die;
try {
out.close();
} catch(Exception ex) {
}
try {
Iin.close();
} catch(Exception ex) {
}
try {
Iout.close();
} catch(Exception ex) {
} }
} }
}
// System.out.println("I2PtoTCP: Going away..."); // System.out.println("I2PtoTCP: Going away...");
} catch(Exception e) { } catch (Exception e) {
// System.out.println("I2PtoTCP: Owch! damn!"); // System.out.println("I2PtoTCP: Owch! damn!");
break die; break die;
}
} // die
} finally {
try {
in.close();
} catch (Exception ex) {
}
try {
out.close();
} catch (Exception ex) {
}
try {
Iin.close();
} catch (Exception ex) {
}
try {
Iout.close();
} catch (Exception ex) {
}
try {
// System.out.println("I2PtoTCP: Close I2P");
I2P.close();
} catch (Exception e) {
tell = false;
}
//System.out.println("I2PtoTCP: Closed I2P");
try {
// System.out.println("I2PtoTCP: Close sock");
sock.close();
} catch (Exception e) {
tell = false;
} }
} // die
try {
// System.out.println("I2PtoTCP: Close I2P");
I2P.close();
} catch(Exception e) {
tell = false;
}
//System.out.println("I2PtoTCP: Closed I2P");
try {
// System.out.println("I2PtoTCP: Close sock");
sock.close();
} catch(Exception e) {
tell = false;
}
// System.out.println("I2PtoTCP: Done"); // System.out.println("I2PtoTCP: Done");
}
} }
} }

View File

@ -29,8 +29,6 @@ import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.util.Properties; import java.util.Properties;
import net.i2p.I2PException; import net.i2p.I2PException;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory; import net.i2p.client.streaming.I2PSocketManagerFactory;
@ -50,7 +48,7 @@ public class MUXlisten implements Runnable {
private ByteArrayInputStream prikey; private ByteArrayInputStream prikey;
private ThreadGroup tg; private ThreadGroup tg;
private String N; private String N;
private ServerSocket listener; private ServerSocket listener = null;
private int backlog = 50; // should this be more? less? private int backlog = 50; // should this be more? less?
boolean go_out; boolean go_out;
boolean come_in; boolean come_in;
@ -133,187 +131,162 @@ public class MUXlisten implements Runnable {
*/ */
public void run() { public void run() {
I2PServerSocket SS = null; I2PServerSocket SS = null;
int ticks = 100; // Allow 10 seconds, no more. Thread t = null;
Thread q = null;
try { try {
wlock();
try { try {
info.add("RUNNING", new Boolean(true)); wlock();
try {
info.add("RUNNING", new Boolean(true));
} catch (Exception e) {
wunlock();
return;
}
} catch (Exception e) {
return;
}
try {
wunlock();
} catch (Exception e) { } catch (Exception e) {
wunlock();
return; return;
} }
} catch (Exception e) {
return;
}
try {
wunlock();
} catch (Exception e) {
return;
}
// socketManager.addDisconnectListener(new DisconnectListener()); // socketManager.addDisconnectListener(new DisconnectListener());
quit: quit:
{ {
try { try {
tg = new ThreadGroup(N); tg = new ThreadGroup(N);
die: 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
if (go_out) { if (go_out) {
// I2P -> TCP // I2P -> TCP
SS = socketManager.getServerSocket(); SS = socketManager.getServerSocket();
I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log); I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log);
Thread t = new Thread(tg, conn, "BOBI2Plistener " + N); t = new Thread(tg, conn, "BOBI2Plistener " + N);
t.start(); t.start();
}
if (come_in) {
// TCP -> I2P
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log);
Thread q = new Thread(tg, conn, "BOBTCPlistener" + N);
q.start();
}
try {
wlock();
try {
info.add("STARTING", new Boolean(false));
} catch (Exception e) {
wunlock();
break die;
} }
} catch (Exception e) {
break die; if (come_in) {
} // TCP -> I2P
try { TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log);
wunlock(); q = new Thread(tg, conn, "BOBTCPlistener " + N);
} catch (Exception e) { q.start();
break die;
}
boolean spin = true;
while (spin) {
try {
Thread.sleep(1000); //sleep for 1 second
} catch (InterruptedException e) {
break die;
} }
try { try {
rlock(); wlock();
try { try {
spin = info.get("STOPPING").equals(Boolean.FALSE); info.add("STARTING", new Boolean(false));
} catch (Exception e) { } catch (Exception e) {
runlock(); wunlock();
break die; break die;
} }
} catch (Exception e) { } catch (Exception e) {
break die; break die;
} }
try { try {
runlock();
} catch (Exception e) {
break die;
}
}
try {
wlock();
try {
info.add("RUNNING", new Boolean(false));
} catch (Exception e) {
wunlock(); wunlock();
} catch (Exception e) {
break die; break die;
} }
} catch (Exception e) { boolean spin = true;
break die; while (spin) {
} try {
try { Thread.sleep(1000); //sleep for 1 second
wunlock(); } catch (InterruptedException e) {
} catch (Exception e) { break die;
break die; }
} try {
} // die rlock();
try {
spin = info.get("STOPPING").equals(Boolean.FALSE);
} catch (Exception e) {
runlock();
break die;
}
} catch (Exception e) {
break die;
}
try {
runlock();
} catch (Exception e) {
break die;
}
}
if (SS != null) { try {
try { wlock();
SS.close(); try {
} catch (I2PException ex) { info.add("RUNNING", new Boolean(false));
//Logger.getLogger(MUXlisten.class.getName()).log(Level.SEVERE, null, ex); } catch (Exception e) {
} wunlock();
} break die;
if (this.come_in) { }
try { } catch (Exception e) {
listener.close(); break die;
} catch (IOException e) { }
} try {
} wunlock();
} catch (Exception e) {
break die;
}
} // die
I2PSession session = socketManager.getSession(); // I2PSession session = socketManager.getSession();
if (session != null) { // if (session != null) {
// System.out.println("I2Plistener: destroySession"); // System.out.println("I2Plistener: destroySession");
try { // try {
session.destroySession(); // session.destroySession();
} catch (I2PSessionException ex) { // } catch (I2PSessionException ex) {
// nop // nop
}
}
try {
socketManager.destroySocketManager();
} catch (Exception e) {
// nop
}
// Wait for child threads and thread groups to die
// System.out.println("MUXlisten: waiting for children");
// if (tg.activeCount() + tg.activeGroupCount() != 0) {
// tg.interrupt(); // give my stuff a small smack.
// while ((tg.activeCount() + tg.activeGroupCount() != 0) && ticks != 0) {
// ticks--;
// try {
// Thread.sleep(100); //sleep for 100 ms (One tenth second)
// } catch (InterruptedException ex) {
// break quit;
// }
// }
// if (tg.activeCount() + tg.activeGroupCount() != 0) {
// break quit; // Uh-oh.
// } // }
// }
// try {
// socketManager.destroySocketManager();
//} catch (Exception e) {
// nop
//} //}
//tg.destroy(); } catch (Exception e) {
// Zap reference to the ThreadGroup so the JVM can GC it. // System.out.println("MUXlisten: Caught an exception" + e);
//tg = null; break quit;
} catch (Exception e) { }
// System.out.println("MUXlisten: Caught an exception" + e); } // quit
break quit; } finally {
} // allow threads above this one to catch the stop signal.
} // quit
// zero out everything.
try {
wlock();
try { try {
info.add("STARTING", new Boolean(false)); Thread.sleep(250);
info.add("STOPPING", new Boolean(false)); } catch (InterruptedException ex) {
info.add("RUNNING", new Boolean(false)); }
} catch (Exception e) { // zero out everything.
wunlock(); try {
return; wlock();
try {
info.add("STARTING", new Boolean(false));
info.add("STOPPING", new Boolean(false));
info.add("RUNNING", new Boolean(false));
} catch (Exception e) {
wunlock();
return;
}
wunlock();
} catch (Exception e) {
} }
wunlock();
} catch (Exception e) {
}
// This is here to catch when something fucks up REALLY bad, like those annoying stuck threads! //try {
if (tg != null) { // Thread.sleep(1000 * 20); // how long?? is this even needed??
// tg.interrupt(); // give my stuff a small smack again. //} catch (InterruptedException ex) {
//}
if (SS != null) { if (SS != null) {
try { try {
SS.close(); SS.close();
} catch (I2PException ex) { } catch (I2PException ex) {
//Logger.getLogger(MUXlisten.class.getName()).log(Level.SEVERE, null, ex);
} }
} }
if (this.come_in) { if (listener != null) {
try { try {
listener.close(); listener.close();
} catch (IOException e) { } catch (IOException e) {
@ -323,50 +296,46 @@ public class MUXlisten implements Runnable {
socketManager.destroySocketManager(); socketManager.destroySocketManager();
} catch (Exception e) { } catch (Exception e) {
// nop // nop
} }
if (tg.activeCount() + tg.activeGroupCount() != 0) { // This is here to catch when something fucks up REALLY bad, like those annoying stuck threads!
int foo = tg.activeCount() + tg.activeGroupCount(); if (tg != null) {
int bar = foo;
String boner = tg.getName(); String boner = tg.getName();
System.out.println("BOB: MUXlisten: Waiting on threads for " + boner); // tg.interrupt(); // give my stuff a small smack again.
System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); if (tg.activeCount() + tg.activeGroupCount() != 0) {
visit(tg, 0, boner); int foo = tg.activeCount() + tg.activeGroupCount();
System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n\n"); int bar = foo;
// Happily spin forever :-( // hopefully no longer needed!
while ((tg.activeCount() + tg.activeGroupCount() != 0)) { // System.out.println("BOB: MUXlisten: Waiting on threads for " + boner);
foo = tg.activeCount() + tg.activeGroupCount(); // System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
if (foo != bar) { // visit(tg, 0, boner);
System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); // System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n\n");
visit(tg, 0, boner); // Happily spin forever :-(
System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n\n"); while ((tg.activeCount() + tg.activeGroupCount() != 0)) {
} foo = tg.activeCount() + tg.activeGroupCount();
bar = foo; // if (foo != bar) {
try { // System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner);
// visit(tg, 0, boner);
// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n\n");
// }
bar = foo;
try { try {
socketManager.destroySocketManager(); Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch (Exception e) { } catch (InterruptedException ex) {
// nop // nop
} }
} catch (Exception e) {
// nop
}
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch (InterruptedException ex) {
// nop
} }
} }
System.out.println("BOB: MUXlisten: Threads went away. Success: " + boner); System.out.println("BOB: MUXlisten: Threads went away. Success: " + boner);
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
} }
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
} }
} }
// Debugging... // Debugging...
/** /**
* Find the root thread group and print them all. * Find the root thread group and print them all.
* *
*/ */

View File

@ -29,6 +29,8 @@ import java.net.Socket;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
// import net.i2p.client.I2PSession; // import net.i2p.client.I2PSession;
// import net.i2p.client.I2PSessionException; // import net.i2p.client.I2PSessionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -80,71 +82,80 @@ public class TCPlistener implements Runnable {
public void run() { public void run() {
boolean g = false; boolean g = false;
boolean spin = true; boolean spin = true;
int conn = 0;
die: { try {
try { die:
rlock(); {
} catch (Exception e) {
break die;
}
try {
if (info.exists("OUTPORT")) {
tgwatch = 2;
}
} catch (Exception e) {
try { try {
runlock(); rlock();
} catch (Exception e2) { } catch (Exception e) {
break die; break die;
} }
break die; try {
} if (info.exists("OUTPORT")) {
try { tgwatch = 2;
runlock(); }
} catch (Exception e) { } catch (Exception e) {
break die;
}
try {
Socket server = new Socket();
listener.setSoTimeout(50); // We don't block, we cycle and check.
while (spin) {
try { try {
rlock(); runlock();
} catch (Exception e) { } catch (Exception e2) {
break die; break die;
} }
try { break die;
spin = info.get("RUNNING").equals(Boolean.TRUE); }
} catch (Exception e) { try {
runlock();
} catch (Exception e) {
break die;
}
try {
Socket server = new Socket();
listener.setSoTimeout(50); // We don't block, we cycle and check.
while (spin) {
try { try {
runlock(); rlock();
} catch (Exception e2) { } catch (Exception e) {
break die; break die;
} }
break die; try {
spin = info.get("RUNNING").equals(Boolean.TRUE);
} catch (Exception e) {
try {
runlock();
} catch (Exception e2) {
break die;
}
break die;
}
try {
server = listener.accept();
g = true;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
conn++;
// toss the connection to a new thread.
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server);
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
t.start();
g = false;
}
} }
try {
server = listener.accept();
g = true;
} catch (SocketTimeoutException ste) {
g = false;
}
if (g) {
// toss the connection to a new thread.
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server);
Thread t = new Thread(conn_c, "BOBTCPtoI2P");
t.start();
g = false;
}
}
listener.close();
} catch (IOException ioe) {
try {
listener.close(); listener.close();
} catch (IOException e) { } catch (IOException ioe) {
try {
listener.close();
} catch (IOException e) {
}
} }
} }
} finally {
try {
listener.close();
} catch (IOException ex) {
}
//System.out.println("TCPlistener: " + Thread.currentThread().getName() + "Done.");
} }
//System.out.println("TCPlistener: Done.");
} }
} }

View File

@ -64,17 +64,17 @@ public class TCPtoI2P implements Runnable {
S = new String(); S = new String();
while(true) { while (true) {
b = in.read(); b = in.read();
if(b == 13) { if (b == 13) {
//skip CR //skip CR
continue; continue;
} }
if(b < 20 || b > 126) { if (b < 20 || b > 126) {
// exit on anything not legal // exit on anything not legal
break; break;
} }
c = (char)(b & 0x7f); // We only really give a fuck about ASCII c = (char) (b & 0x7f); // We only really give a fuck about ASCII
S = new String(S + c); S = new String(S + c);
} }
return S; return S;
@ -118,85 +118,87 @@ public class TCPtoI2P implements Runnable {
OutputStream Iout = null; OutputStream Iout = null;
InputStream in = null; InputStream in = null;
OutputStream out = null; OutputStream out = null;
try { try {
in = sock.getInputStream();
out = sock.getOutputStream();
try { try {
line = lnRead(in);
input = line.toLowerCase();
Destination dest = null;
if(input.endsWith(".i2p")) {
dest = I2PTunnel.destFromName(input);
line = dest.toBase64();
}
dest = new Destination();
dest.fromBase64(line);
in = sock.getInputStream();
out = sock.getOutputStream();
try { try {
// get a client socket line = lnRead(in);
I2P = socketManager.connect(dest); input = line.toLowerCase();
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default Destination dest = null;
// make readers/writers
Iin = I2P.getInputStream(); if (input.endsWith(".i2p")) {
Iout = I2P.getOutputStream(); dest = I2PTunnel.destFromName(input);
// setup to cross the streams line = dest.toBase64();
TCPio conn_c = new TCPio(in, Iout /*, info, database */); // app -> I2P }
TCPio conn_a = new TCPio(Iin, out /*, info, database */); // I2P -> app dest = new Destination();
Thread t = new Thread(conn_c, "TCPioA"); dest.fromBase64(line);
Thread q = new Thread(conn_a, "TCPioB");
// Fire! try {
t.start(); // get a client socket
q.start(); I2P = socketManager.connect(dest);
while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
// make readers/writers
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
Thread t = new Thread(conn_c, Thread.currentThread().getName() + " TCPioA");
Thread q = new Thread(conn_a, Thread.currentThread().getName() + " TCPioB");
// Fire!
t.start();
q.start();
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
}
} catch (I2PException e) {
Emsg("ERROR " + e.toString(), out);
} catch (ConnectException e) {
Emsg("ERROR " + e.toString(), out);
} catch (NoRouteToHostException e) {
Emsg("ERROR " + e.toString(), out);
} catch (InterruptedIOException e) {
// We're breaking away.
} }
} catch(I2PException e) { } catch (Exception e) {
Emsg("ERROR " + e.toString(), out); Emsg("ERROR " + e.toString(), out);
} catch(ConnectException e) {
Emsg("ERROR " + e.toString(), out);
} catch(NoRouteToHostException e) {
Emsg("ERROR " + e.toString(), out);
} catch(InterruptedIOException e) {
// We're breaking away.
} }
} catch (Exception e) {
} catch(Exception e) { // bail on anything else
Emsg("ERROR " + e.toString(), out); }
} finally {
try {
in.close();
} catch (Exception e) {
}
try {
out.close();
} catch (Exception e) {
}
try {
Iin.close();
} catch (Exception e) {
}
try {
Iout.close();
} catch (Exception e) {
}
try {
// System.out.println("TCPtoI2P: Close I2P");
I2P.close();
} catch (Exception e) {
} }
} catch(Exception e) {
// bail on anything else
}
try {
in.close();
} catch(Exception e) {
}
try {
out.close();
} catch(Exception e) {
}
try {
Iin.close();
} catch(Exception e) {
}
try {
Iout.close();
} catch(Exception e) {
}
try {
// System.out.println("TCPtoI2P: Close I2P");
I2P.close();
} catch(Exception e) {
}
try { try {
// System.out.println("TCPtoI2P: Close sock"); // System.out.println("TCPtoI2P: Close sock");
sock.close(); sock.close();
} catch(Exception e) { } catch (Exception e) {
}
} }
// System.out.println("TCPtoI2P: Done."); // System.out.println("TCPtoI2P: Done.");
} }
} }

View File

@ -202,20 +202,23 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession {
private LinkedBlockingQueue<MsgData> _msgs; private LinkedBlockingQueue<MsgData> _msgs;
private AtomicBoolean _alive = new AtomicBoolean(false); private AtomicBoolean _alive = new AtomicBoolean(false);
private static final int POISON_SIZE = -99999; private static final int POISON_SIZE = -99999;
private AtomicBoolean stopping = new AtomicBoolean(false);
public MuxedAvailabilityNotifier() { public MuxedAvailabilityNotifier() {
_msgs = new LinkedBlockingQueue(); _msgs = new LinkedBlockingQueue();
} }
@Override @Override
public void stopNotifying() { public void stopNotifying() {
if(stopping.get()) return;
stopping.set(true);
boolean again = true; boolean again = true;
_msgs.clear(); // _msgs.clear();
// Thread.yield(); // Thread.yield();
if (_alive.get()) { if (_alive.get()) {
// System.out.println("I2PSessionMuxedImpl.stopNotifying()"); // System.out.println("I2PSessionMuxedImpl.stopNotifying()");
_msgs.clear();
while(again) { while(again) {
_msgs.clear();
try { try {
_msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0)); _msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0));
again = false; again = false;
@ -226,6 +229,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession {
} }
} }
_alive.set(false); _alive.set(false);
stopping.set(false); // Do we need this?
} }
/** unused */ /** unused */

View File

@ -115,8 +115,8 @@ public class I2CPMessageReader {
} }
private class I2CPMessageReaderRunner implements Runnable { private class I2CPMessageReaderRunner implements Runnable {
private boolean _doRun; private volatile boolean _doRun;
private boolean _stayAlive; private volatile boolean _stayAlive;
public I2CPMessageReaderRunner() { public I2CPMessageReaderRunner() {
_doRun = true; _doRun = true;

View File

@ -1,3 +1,7 @@
2009-05-06 sponge
* Hopefully the last fixes for BOB.
* Fixes to prevent race in client-side I2CP and Notifier.
2009-05-03 sponge 2009-05-03 sponge
* More hopeful fixes for BOB. * More hopeful fixes for BOB.
* Added new Robert ID to snark * Added new Robert ID to snark

View File

@ -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 = 7; public final static long BUILD = 8;
/** 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;