forked from I2P_Developers/i2p.i2p
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:
@ -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.");
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -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.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user