From 40637e0f282da7df11dec958293824acfb5bc07b Mon Sep 17 00:00:00 2001 From: zzz Date: Sat, 2 May 2009 03:38:01 +0000 Subject: [PATCH 01/10] slow down the ff volunteers --- .../i2p/router/networkdb/kademlia/FloodfillMonitorJob.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java index 26eaa2fad..a1a74fc86 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java @@ -46,7 +46,12 @@ class FloodfillMonitorJob extends JobImpl { getContext().router().rebuildRouterInfo(); if (_log.shouldLog(Log.INFO)) _log.info("Should we be floodfill? " + ff); - requeue((REQUEUE_DELAY / 2) + getContext().random().nextInt(REQUEUE_DELAY)); + int delay = (REQUEUE_DELAY / 2) + getContext().random().nextInt(REQUEUE_DELAY); + // there's a lot of eligible non-floodfills, keep them from all jumping in at once + // To do: somehow assess the size of the network to make this adaptive? + if (!ff) + delay *= 3; + requeue(delay); } private boolean shouldBeFloodfill() { From 29fe221fe690c222a6c9d5f03b839e4b5d4a73e0 Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 5 May 2009 21:02:03 +0000 Subject: [PATCH 02/10] name the addressbook thread --- apps/addressbook/java/src/addressbook/Servlet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/addressbook/java/src/addressbook/Servlet.java b/apps/addressbook/java/src/addressbook/Servlet.java index 50bc1eb6d..34af69c1c 100644 --- a/apps/addressbook/java/src/addressbook/Servlet.java +++ b/apps/addressbook/java/src/addressbook/Servlet.java @@ -54,9 +54,10 @@ public class Servlet extends GenericServlet { args[0] = config.getInitParameter("home"); DaemonThread thread = new DaemonThread(args); thread.setDaemon(true); + thread.setName("Addressbook"); thread.start(); System.out.println("INFO: Starting Addressbook " + Daemon.VERSION); System.out.println("INFO: config root under " + args[0]); } -} \ No newline at end of file +} From 7d91bdba1edc1944d704bf3775f9b6c3ef365e57 Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 5 May 2009 21:03:36 +0000 Subject: [PATCH 03/10] * Throttle: Throttle at 90% so we throttle before we WRED --- .../src/net/i2p/router/RouterThrottleImpl.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java index fc38b1695..acab90a64 100644 --- a/router/java/src/net/i2p/router/RouterThrottleImpl.java +++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java @@ -262,6 +262,7 @@ class RouterThrottleImpl implements RouterThrottle { } private static final int DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE = 40; // .067KBps + /** also limited to 90% - see below */ private static final int MIN_AVAILABLE_BPS = 4*1024; // always leave at least 4KBps free when allowing private static final String LIMIT_STR = "Rejecting tunnels: Bandwidth limit"; @@ -282,8 +283,11 @@ class RouterThrottleImpl implements RouterThrottle { int used1mOut = _context.router().get1mRate(true); // Check the inbound and outbound total bw available (separately) - int availBps = (maxKBpsIn*1024) - usedIn; - availBps = Math.min(availBps, (maxKBpsOut*1024) - usedOut); + // We block all tunnels when share bw is over (max * 0.9) - 4KB + // This gives reasonable growth room for existing tunnels on both low and high + // bandwidth routers. We want to be rejecting tunnels more aggressively than + // dropping packets with WRED + int availBps = Math.min((maxKBpsIn*1024*9/10) - usedIn, (maxKBpsOut*1024*9/10) - usedOut); if (availBps < MIN_AVAILABLE_BPS) { if (_log.shouldLog(Log.WARN)) _log.warn("Reject, avail (" + availBps + ") less than min"); setTunnelStatus(LIMIT_STR); @@ -303,8 +307,7 @@ class RouterThrottleImpl implements RouterThrottle { _context.statManager().addRateData("router.throttleTunnelBytesAllowed", availBps, (long)bytesAllocated); // Now see if 1m rates are too high - long overage = used1mIn - (maxKBpsIn*1024); - overage = Math.max(overage, used1mOut - (maxKBpsOut*1024)); + long overage = Math.max(used1mIn - (maxKBpsIn*1024), used1mOut - (maxKBpsOut*1024)); if ( (overage > 0) && ((overage/(float)(maxKBps*1024f)) > _context.random().nextFloat()) ) { if (_log.shouldLog(Log.WARN)) _log.warn("Reject tunnel, 1m rate (" + overage + " over) indicates overload."); @@ -312,7 +315,8 @@ class RouterThrottleImpl implements RouterThrottle { return false; } - float maxBps = maxKBps * 1024f; + // limit at 90% - 4KBps (see above) + float maxBps = (maxKBps * 1024f * 0.9f) - MIN_AVAILABLE_BPS; float pctFull = (maxBps - availBps) / (maxBps); double probReject = Math.pow(pctFull, 16); // steep curve double rand = _context.random().nextFloat(); From e7913061e9168afddcd9bee6de4be43687ed1bdf Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 5 May 2009 21:04:46 +0000 Subject: [PATCH 04/10] * Console: More IE button fixes, try harder to not 404 the iframe --- apps/routerconsole/jsp/summaryframe.jsp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/routerconsole/jsp/summaryframe.jsp b/apps/routerconsole/jsp/summaryframe.jsp index 627fe328c..54126ef72 100644 --- a/apps/routerconsole/jsp/summaryframe.jsp +++ b/apps/routerconsole/jsp/summaryframe.jsp @@ -16,7 +16,9 @@ // try hard to avoid an error page in the iframe after shutdown String action = request.getParameter("action"); String d = request.getParameter("refresh"); - boolean shutdownSoon = "shutdownImmediate".equals(action) || "restartImmediate".equals(action); + // Normal browsers send value, IE sends button label + boolean shutdownSoon = "shutdownImmediate".equals(action) || "restartImmediate".equals(action) || + "Shutdown immediately".equals(action) || "Restart immediately".equals(action); if (!shutdownSoon) { if (d == null || "".equals(d)) { d = System.getProperty("routerconsole.summaryRefresh"); @@ -30,6 +32,14 @@ if (!"0".equals(d)) { // doesn't work for restart or shutdown with no expl. tunnels, // since the call to ConfigRestartBean.renderStatus() hasn't happened yet... + // So we delay slightly + if ("restart".equalsIgnoreCase(action) || "shutdown".equalsIgnoreCase(action)) { + synchronized(this) { + try { + wait(1000); + } catch(InterruptedException ie) {} + } + } long timeleft = net.i2p.router.web.ConfigRestartBean.getRestartTimeRemaining(); long delay = 60; try { delay = Long.parseLong(d); } catch (NumberFormatException nfe) {} From 95a38779decacbc15f508729352fb3f38b4c0b6d Mon Sep 17 00:00:00 2001 From: zzz Date: Tue, 5 May 2009 22:24:19 +0000 Subject: [PATCH 05/10] * Console: Disable idle options for streamr client, it will never be idle because it pings the server --- apps/i2ptunnel/jsp/editClient.jsp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp index 915da5db9..4f0a5a338 100644 --- a/apps/i2ptunnel/jsp/editClient.jsp +++ b/apps/i2ptunnel/jsp/editClient.jsp @@ -284,6 +284,7 @@ + <% if (!"streamrclient".equals(tunnelType)) { // streamr client sends pings so it will never be idle %>

@@ -362,6 +363,7 @@ class="tickbox" /> + <% } // !streamrclient %>

From eba6ca5430393e0ae623b96f1f28a28af395cab9 Mon Sep 17 00:00:00 2001 From: sponge Date: Wed, 6 May 2009 05:34:33 +0000 Subject: [PATCH 06/10] 2009-05-06 sponge * Hopefully the last fixes for BOB. * Fixes to prevent race in client-side I2CP and Notifier. --- apps/BOB/src/net/i2p/BOB/I2Plistener.java | 80 +++-- apps/BOB/src/net/i2p/BOB/I2PtoTCP.java | 161 +++++---- apps/BOB/src/net/i2p/BOB/MUXlisten.java | 329 ++++++++---------- apps/BOB/src/net/i2p/BOB/TCPlistener.java | 115 +++--- apps/BOB/src/net/i2p/BOB/TCPtoI2P.java | 146 ++++---- .../net/i2p/client/I2PSessionMuxedImpl.java | 10 +- .../net/i2p/data/i2cp/I2CPMessageReader.java | 4 +- history.txt | 4 + .../src/net/i2p/router/RouterVersion.java | 2 +- 9 files changed, 430 insertions(+), 421 deletions(-) diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java index 3bb94e0b3..caaadc76d 100644 --- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java +++ b/apps/BOB/src/net/i2p/BOB/I2Plistener.java @@ -25,6 +25,8 @@ package net.i2p.BOB; import java.net.ConnectException; import java.net.SocketTimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; import net.i2p.I2PException; import net.i2p.client.streaming.I2PServerSocket; import net.i2p.client.streaming.I2PSocket; @@ -78,51 +80,59 @@ public class I2Plistener implements Runnable { public void run() { boolean g = false; 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 { - runlock(); - } catch (Exception e2) { + rlock(); + } catch (Exception e) { break die; } - break die; - } - try { try { - sessSocket = serverSocket.accept(); - g = true; - } catch (ConnectException ce) { - g = false; - } catch (SocketTimeoutException ste) { - g = false; - } - if (g) { - 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(); + spin = info.get("RUNNING").equals(Boolean.TRUE); + } catch (Exception e) { + try { + runlock(); + } catch (Exception e2) { + break die; + } + break die; } + 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) { - // System.out.println("Exception " + e); + } catch (Exception e) { + // System.out.println("Exception " + e); + } } } - } + } finally { + try { + serverSocket.close(); + } catch (I2PException ex) { + } // System.out.println("I2Plistener: Close"); - // System.out.println("I2Plistener: Done."); + } } } diff --git a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java index ad5e2701b..73e936c61 100644 --- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java +++ b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java @@ -70,90 +70,99 @@ public class I2PtoTCP implements Runnable { String host; int port; boolean tell; -die: { - try { + InputStream in = null; + OutputStream out = null; + InputStream Iin = null; + OutputStream Iout = null; + try { + die: + { 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 { - Thread.sleep(10); //sleep for 10 ms - } catch(InterruptedException e) { + 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 + 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 { - in.close(); - } catch(Exception ex) { - } - try { - out.close(); - } catch(Exception ex) { - } - try { - Iin.close(); - } catch(Exception ex) { - } - try { - Iout.close(); - } catch(Exception ex) { + Thread.sleep(10); //sleep for 10 ms + } catch (InterruptedException e) { + break die; } } - } // System.out.println("I2PtoTCP: Going away..."); - } catch(Exception e) { - // System.out.println("I2PtoTCP: Owch! damn!"); - break die; + } catch (Exception e) { + // System.out.println("I2PtoTCP: Owch! damn!"); + 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"); + } } } diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java index 776dbf28a..91028e7cb 100644 --- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java +++ b/apps/BOB/src/net/i2p/BOB/MUXlisten.java @@ -29,8 +29,6 @@ import java.net.InetAddress; import java.net.ServerSocket; import java.util.Properties; 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.I2PSocketManager; import net.i2p.client.streaming.I2PSocketManagerFactory; @@ -50,7 +48,7 @@ public class MUXlisten implements Runnable { private ByteArrayInputStream prikey; private ThreadGroup tg; private String N; - private ServerSocket listener; + private ServerSocket listener = null; private int backlog = 50; // should this be more? less? boolean go_out; boolean come_in; @@ -133,187 +131,162 @@ public class MUXlisten implements Runnable { */ public void run() { I2PServerSocket SS = null; - int ticks = 100; // Allow 10 seconds, no more. + Thread t = null; + Thread q = null; try { - wlock(); 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) { - wunlock(); return; } - } catch (Exception e) { - return; - } - try { - wunlock(); - } catch (Exception e) { - return; - } // socketManager.addDisconnectListener(new DisconnectListener()); - quit: - { - try { - tg = new ThreadGroup(N); - die: - { - // toss the connections to a new threads. - // will wrap with TCP and UDP when UDP works + quit: + { + try { + tg = new ThreadGroup(N); + die: + { + // toss the connections to a new threads. + // will wrap with TCP and UDP when UDP works - if (go_out) { - // I2P -> TCP - SS = socketManager.getServerSocket(); - I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log); - Thread t = new Thread(tg, conn, "BOBI2Plistener " + N); - 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; + if (go_out) { + // I2P -> TCP + SS = socketManager.getServerSocket(); + I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log); + t = new Thread(tg, conn, "BOBI2Plistener " + N); + t.start(); } - } catch (Exception e) { - break die; - } - try { - wunlock(); - } catch (Exception e) { - break die; - } - boolean spin = true; - while (spin) { - try { - Thread.sleep(1000); //sleep for 1 second - } catch (InterruptedException e) { - break die; + + if (come_in) { + // TCP -> I2P + TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log); + q = new Thread(tg, conn, "BOBTCPlistener " + N); + q.start(); } + try { - rlock(); + wlock(); try { - spin = info.get("STOPPING").equals(Boolean.FALSE); + info.add("STARTING", new Boolean(false)); } catch (Exception e) { - runlock(); + wunlock(); break die; } } catch (Exception e) { break die; } try { - runlock(); - } catch (Exception e) { - break die; - } - } - - try { - wlock(); - try { - info.add("RUNNING", new Boolean(false)); - } catch (Exception e) { wunlock(); + } catch (Exception e) { break die; } - } catch (Exception e) { - break die; - } - try { - wunlock(); - } catch (Exception e) { - break die; - } - } // die + boolean spin = true; + while (spin) { + try { + Thread.sleep(1000); //sleep for 1 second + } catch (InterruptedException e) { + break die; + } + try { + 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 { - SS.close(); - } catch (I2PException ex) { - //Logger.getLogger(MUXlisten.class.getName()).log(Level.SEVERE, null, ex); - } - } - if (this.come_in) { - try { - listener.close(); - } catch (IOException e) { - } - } + 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 - I2PSession session = socketManager.getSession(); - if (session != null) { - // System.out.println("I2Plistener: destroySession"); - try { - session.destroySession(); - } catch (I2PSessionException ex) { - // 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. + // I2PSession session = socketManager.getSession(); + // if (session != null) { + // System.out.println("I2Plistener: destroySession"); + // try { + // session.destroySession(); + // } catch (I2PSessionException ex) { + // nop // } + // } + // try { + // socketManager.destroySocketManager(); + //} catch (Exception e) { + // nop //} - //tg.destroy(); - // Zap reference to the ThreadGroup so the JVM can GC it. - //tg = null; - } catch (Exception e) { - // System.out.println("MUXlisten: Caught an exception" + e); - break quit; - } - } // quit - - // zero out everything. - try { - wlock(); + } catch (Exception e) { + // System.out.println("MUXlisten: Caught an exception" + e); + break quit; + } + } // quit + } finally { + // allow threads above this one to catch the stop signal. try { - info.add("STARTING", new Boolean(false)); - info.add("STOPPING", new Boolean(false)); - info.add("RUNNING", new Boolean(false)); - } catch (Exception e) { - wunlock(); - return; + Thread.sleep(250); + } 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) { + 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! - if (tg != null) { - // tg.interrupt(); // give my stuff a small smack again. + //try { + // Thread.sleep(1000 * 20); // how long?? is this even needed?? + //} catch (InterruptedException ex) { + //} + if (SS != null) { try { SS.close(); } catch (I2PException ex) { - //Logger.getLogger(MUXlisten.class.getName()).log(Level.SEVERE, null, ex); } } - if (this.come_in) { + if (listener != null) { try { listener.close(); } catch (IOException e) { @@ -323,50 +296,46 @@ public class MUXlisten implements Runnable { socketManager.destroySocketManager(); } catch (Exception e) { // nop - } - if (tg.activeCount() + tg.activeGroupCount() != 0) { - int foo = tg.activeCount() + tg.activeGroupCount(); - int bar = foo; + } + // This is here to catch when something fucks up REALLY bad, like those annoying stuck threads! + if (tg != null) { String boner = tg.getName(); - System.out.println("BOB: MUXlisten: Waiting on threads for " + boner); - 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"); - // Happily spin forever :-( - while ((tg.activeCount() + tg.activeGroupCount() != 0)) { - foo = tg.activeCount() + tg.activeGroupCount(); - if (foo != bar) { - 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 { + // tg.interrupt(); // give my stuff a small smack again. + if (tg.activeCount() + tg.activeGroupCount() != 0) { + int foo = tg.activeCount() + tg.activeGroupCount(); + int bar = foo; + // hopefully no longer needed! + // System.out.println("BOB: MUXlisten: Waiting on threads for " + boner); + // 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"); + // Happily spin forever :-( + while ((tg.activeCount() + tg.activeGroupCount() != 0)) { + foo = tg.activeCount() + tg.activeGroupCount(); + // if (foo != bar) { + // 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 { - socketManager.destroySocketManager(); - } catch (Exception e) { + Thread.sleep(100); //sleep for 100 ms (One tenth second) + } catch (InterruptedException ex) { // 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); + 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... - /** + /** * Find the root thread group and print them all. * */ diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java index 4ce888090..0ac67d277 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java +++ b/apps/BOB/src/net/i2p/BOB/TCPlistener.java @@ -29,6 +29,8 @@ import java.net.Socket; import java.net.SocketTimeoutException; // import net.i2p.client.I2PSession; // 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.I2PSocketManager; import net.i2p.util.Log; @@ -80,71 +82,80 @@ public class TCPlistener implements Runnable { public void run() { boolean g = false; boolean spin = true; - -die: { - try { - rlock(); - } catch (Exception e) { - break die; - } - try { - if (info.exists("OUTPORT")) { - tgwatch = 2; - } - } catch (Exception e) { + int conn = 0; + try { + die: + { try { - runlock(); - } catch (Exception e2) { + rlock(); + } catch (Exception e) { break die; } - break die; - } - 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 { + if (info.exists("OUTPORT")) { + tgwatch = 2; + } + } catch (Exception e) { try { - rlock(); - } catch (Exception e) { + runlock(); + } catch (Exception e2) { break die; } - try { - spin = info.get("RUNNING").equals(Boolean.TRUE); - } catch (Exception e) { + break die; + } + 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 { - runlock(); - } catch (Exception e2) { + rlock(); + } catch (Exception e) { 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(); - } 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."); } } diff --git a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java index 5fefae017..f3f2c7445 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java +++ b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java @@ -64,17 +64,17 @@ public class TCPtoI2P implements Runnable { S = new String(); - while(true) { + while (true) { b = in.read(); - if(b == 13) { + if (b == 13) { //skip CR continue; } - if(b < 20 || b > 126) { + if (b < 20 || b > 126) { // exit on anything not legal 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); } return S; @@ -118,85 +118,87 @@ public class TCPtoI2P implements Runnable { OutputStream Iout = null; InputStream in = null; OutputStream out = null; - try { - - in = sock.getInputStream(); - out = sock.getOutputStream(); 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 { - // get a client socket - I2P = socketManager.connect(dest); - 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, "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 + 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); + + try { + // get a client socket + I2P = socketManager.connect(dest); + 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 + } + + } 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); - } 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) { - Emsg("ERROR " + e.toString(), out); + } catch (Exception e) { + // bail on anything else + } + } 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 { - // System.out.println("TCPtoI2P: Close sock"); - sock.close(); - } catch(Exception e) { + try { + // System.out.println("TCPtoI2P: Close sock"); + sock.close(); + } catch (Exception e) { + } } - // System.out.println("TCPtoI2P: Done."); + // System.out.println("TCPtoI2P: Done."); } } diff --git a/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java b/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java index eda48e754..aeef4e38e 100644 --- a/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java @@ -202,20 +202,23 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { private LinkedBlockingQueue _msgs; private AtomicBoolean _alive = new AtomicBoolean(false); private static final int POISON_SIZE = -99999; - + private AtomicBoolean stopping = new AtomicBoolean(false); + public MuxedAvailabilityNotifier() { _msgs = new LinkedBlockingQueue(); } @Override public void stopNotifying() { + if(stopping.get()) return; + stopping.set(true); boolean again = true; - _msgs.clear(); + // _msgs.clear(); // Thread.yield(); if (_alive.get()) { // System.out.println("I2PSessionMuxedImpl.stopNotifying()"); + _msgs.clear(); while(again) { - _msgs.clear(); try { _msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0)); again = false; @@ -226,6 +229,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { } } _alive.set(false); + stopping.set(false); // Do we need this? } /** unused */ diff --git a/core/java/src/net/i2p/data/i2cp/I2CPMessageReader.java b/core/java/src/net/i2p/data/i2cp/I2CPMessageReader.java index 5c79d94f3..461c4b08a 100644 --- a/core/java/src/net/i2p/data/i2cp/I2CPMessageReader.java +++ b/core/java/src/net/i2p/data/i2cp/I2CPMessageReader.java @@ -115,8 +115,8 @@ public class I2CPMessageReader { } private class I2CPMessageReaderRunner implements Runnable { - private boolean _doRun; - private boolean _stayAlive; + private volatile boolean _doRun; + private volatile boolean _stayAlive; public I2CPMessageReaderRunner() { _doRun = true; diff --git a/history.txt b/history.txt index 102aef632..042ca5df7 100644 --- a/history.txt +++ b/history.txt @@ -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 * More hopeful fixes for BOB. * Added new Robert ID to snark diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 4ab27b06c..848b1dc38 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 = 7; + public final static long BUILD = 8; /** for example "-test" */ public final static String EXTRA = ""; public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; From a516d6474e21bdcd3e515c350ea8a6b858891505 Mon Sep 17 00:00:00 2001 From: mathiasdm Date: Wed, 6 May 2009 16:17:58 +0000 Subject: [PATCH 07/10] * Improvements to popup menu rightclick action * Added general configuration options (still not available by default) * General fixes * Added ant build options (irc says eche|on would like that ;)) --- apps/desktopgui/nbproject/build-impl.xml | 25 +- apps/desktopgui/nbproject/genfiles.properties | 4 +- .../desktopgui/src/desktopgui/GUIVersion.java | 2 +- .../src/gui/GeneralConfiguration.form | 138 ++++--- .../src/gui/GeneralConfiguration.java | 347 +++++++++++------- apps/desktopgui/src/gui/JPopupTrayIcon.java | 29 +- apps/desktopgui/src/gui/LogViewer.form | 1 + apps/desktopgui/src/gui/LogViewer.java | 3 +- apps/desktopgui/src/gui/SpeedSelector3.form | 3 +- apps/desktopgui/src/gui/SpeedSelector3.java | 2 +- apps/desktopgui/src/gui/Version.form | 27 +- apps/desktopgui/src/gui/Version.java | 22 +- .../resources/GeneralConfiguration.properties | 24 +- .../src/gui/resources/LogViewer.properties | 1 + .../gui/resources/SpeedSelector3.properties | 4 +- .../src/gui/resources/Version.properties | 1 + .../src/router/configuration/SpeedHelper.java | 7 + build.xml | 4 + history.txt | 6 + 19 files changed, 404 insertions(+), 246 deletions(-) diff --git a/apps/desktopgui/nbproject/build-impl.xml b/apps/desktopgui/nbproject/build-impl.xml index f8fea458d..039f8788f 100644 --- a/apps/desktopgui/nbproject/build-impl.xml +++ b/apps/desktopgui/nbproject/build-impl.xml @@ -152,7 +152,7 @@ is divided into following sections: - + @@ -218,13 +218,13 @@ is divided into following sections: - + - + @@ -255,6 +255,12 @@ is divided into following sections: + + + + + + @@ -264,7 +270,7 @@ is divided into following sections: - + @@ -311,6 +317,13 @@ is divided into following sections: =================== --> + + + + + + + @@ -331,7 +344,7 @@ is divided into following sections: - + @@ -345,7 +358,7 @@ is divided into following sections: - +