diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java index 6033e303bf2593c000884527ed5f0fdbd4311cf7..099d69fecac4e6d6a6378aac9be51a6216891b14 100644 --- a/apps/BOB/src/net/i2p/BOB/DoCMDS.java +++ b/apps/BOB/src/net/i2p/BOB/DoCMDS.java @@ -46,7 +46,7 @@ public class DoCMDS implements Runnable { // FIX ME // I need a better way to do versioning, but this will do for now. - public static final String BMAJ = "00", BMIN = "00", BREV = "03", BEXT = ""; + public static final String BMAJ = "00", BMIN = "00", BREV = "04", BEXT = ""; public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT; private Socket server; private Properties props; diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java index 1561b7a222891c3d147453e3d97dc4a3ec9547a8..c59683270e585b5127ba8020ee4768a49fec6a02 100644 --- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java +++ b/apps/BOB/src/net/i2p/BOB/I2Plistener.java @@ -70,7 +70,7 @@ public class I2Plistener implements Runnable { boolean g = false; I2PSocket sessSocket = null; - serverSocket.setSoTimeout(100); + serverSocket.setSoTimeout(50); database.getReadLock(); info.getReadLock(); if(info.exists("INPORT")) { diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java index bd52e27fd2deac44d2a0f06b1e20aaa5be4f832f..89ab53fe62f9f8fad5afee5c08d1a511b2a735c9 100644 --- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java +++ b/apps/BOB/src/net/i2p/BOB/MUXlisten.java @@ -173,7 +173,7 @@ die: { boolean spin = true; while(spin) { try { - Thread.sleep(1000); //sleep for 1000 ms (One second) + Thread.sleep(200); //sleep for 200 ms (Two thenths second) } catch(InterruptedException e) { // nop } @@ -213,14 +213,21 @@ die: { } } // die + try { + Thread.sleep(500); //sleep for 500 ms (One half second) + } catch(InterruptedException ex) { + // nop + } // wait for child threads and thread groups to die // System.out.println("MUXlisten: waiting for children"); - while(tg.activeCount() + tg.activeGroupCount() != 0) { + if(tg.activeCount() + tg.activeGroupCount() != 0) { tg.interrupt(); // unwedge any blocking threads. - try { - Thread.sleep(100); //sleep for 100 ms (One tenth second) - } catch(InterruptedException ex) { - // nop + while(tg.activeCount() + tg.activeGroupCount() != 0) { + try { + Thread.sleep(100); //sleep for 100 ms (One tenth second) + } catch(InterruptedException ex) { + // nop + } } } tg.destroy(); @@ -260,17 +267,33 @@ die: { } // This is here to catch when something fucks up REALLY bad. if(tg != null) { - while(tg.activeCount() + tg.activeGroupCount() != 0) { + if(tg.activeCount() + tg.activeGroupCount() != 0) { tg.interrupt(); // unwedge any blocking threads. + while(tg.activeCount() + tg.activeGroupCount() != 0) { try { Thread.sleep(100); //sleep for 100 ms (One tenth second) } catch(InterruptedException ex) { // nop } + } } tg.destroy(); // Zap reference to the ThreadGroup so the JVM can GC it. tg = null; } + + // Lastly try to close things again. + if(this.come_in) { + try { + listener.close(); + } catch(IOException e) { + } + } + try { + socketManager.destroySocketManager(); + } catch(Exception e) { + // nop + } + } } diff --git a/apps/BOB/src/net/i2p/BOB/TCPio.java b/apps/BOB/src/net/i2p/BOB/TCPio.java index 25290bcdcf1d15630848a5c414a11989482f229d..41bb7cbe494d658cd828728c87a2debc4672b6f0 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPio.java +++ b/apps/BOB/src/net/i2p/BOB/TCPio.java @@ -56,9 +56,28 @@ public class TCPio implements Runnable { * Copy from source to destination... * and yes, we are totally OK to block here on writes, * The OS has buffers, and I intend to use them. + * We send an interrupt signal to the threadgroup to + * unwedge any pending writes. * */ public void run() { + /* + * NOTE: + * The write method of OutputStream calls the write method of + * one argument on each of the bytes to be written out. + * Subclasses are encouraged to override this method and provide + * a more efficient implementation. + * + * So, is this really a performance problem? + * Should we expand to several bytes? + * I don't believe there would be any gain, since read method + * has the same reccomendations. If anyone has a better way to + * do this, I'm interested in performance improvements. + * + * --Sponge + * + */ + int b; byte a[] = new byte[1]; boolean spin = true; diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java index 99ae047d31cb10f7d698d28a59e0ae09ed65fe06..30380a55dd0241fb104fb36a71dfbfaa4c6959de 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java +++ b/apps/BOB/src/net/i2p/BOB/TCPlistener.java @@ -77,7 +77,7 @@ public class TCPlistener implements Runnable { } try { Socket server = new Socket(); - listener.setSoTimeout(1000); + listener.setSoTimeout(50); // Half of the expected time from MUXlisten info.releaseReadLock(); database.releaseReadLock(); while(spin) { diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java index aa95e526c809a166f44bd219064a271d413adc7d..7e12aa30a6162737cd26f32e499b6e9e22d68287 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java @@ -16,6 +16,7 @@ import net.i2p.data.DataFormatException; import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.Hash; +import net.i2p.data.Base32; import net.i2p.util.EventDispatcher; import net.i2p.util.I2PThread; import net.i2p.util.Log; @@ -36,26 +37,27 @@ import net.i2p.util.Log; * "custom options" section of i2ptunnel. * - ircserver.cloakKey unset: Cloak with a random value that is persistent for * the life of this tunnel. This is the default. - * - ircserver.cloakKey=none: Don't cloak. Users may be correlated with their - * (probably) shared clients destination. - * Of course if the ircd does cloaking than this is ok. * - ircserver.cloakKey=somepassphrase: Cloak with the hash of the passphrase. Use this to * have consistent mangling across restarts, or to * have multiple IRC servers cloak consistently to * be able to track users even when they switch servers. * Note: don't quote or put spaces in the passphrase, * the i2ptunnel gui can't handle it. + * - ircserver.fakeHostname=%f.b32.i2p: Set the fake hostname sent by I2PTunnel, + * %f is the full B32 destination hash + * %c is the cloaked hash. * * There is no outbound filtering. * * @author zzz */ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { - + public static final String PROP_CLOAK="ircserver.cloakKey"; + public static final String PROP_HOSTNAME="ircserver.fakeHostname"; + public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p"; + private static final Log _log = new Log(I2PTunnelIRCServer.class); - private static final String PROP_CLOAK="ircserver.cloakKey"; - private boolean _cloak; - private byte[] _cloakKey; // 32 bytes of stuff to scramble the dest with + /** * @throws IllegalArgumentException if the I2PTunnel does not contain @@ -71,15 +73,14 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { private void initCloak(I2PTunnel tunnel) { Properties opts = tunnel.getClientOptions(); String passphrase = opts.getProperty(PROP_CLOAK); - _cloak = passphrase == null || !"none".equals(passphrase); - if (_cloak) { - if (passphrase == null) { - _cloakKey = new byte[Hash.HASH_LENGTH]; - tunnel.getContext().random().nextBytes(_cloakKey); - } else { - _cloakKey = SHA256Generator.getInstance().calculateHash(passphrase.trim().getBytes()).getData(); - } + if (passphrase == null) { + this.cloakKey = new byte[Hash.HASH_LENGTH]; + tunnel.getContext().random().nextBytes(this.cloakKey); + } else { + this.cloakKey = SHA256Generator.getInstance().calculateHash(passphrase.trim().getBytes()).getData(); } + + this.hostname = opts.getProperty(PROP_HOSTNAME, PROP_HOSTNAME_DEFAULT); } protected void blockingHandle(I2PSocket socket) { @@ -122,16 +123,17 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { * */ String cloakDest(Destination d) { - Hash h; - if (_cloak) { - byte[] b = new byte[d.size() + _cloakKey.length]; - System.arraycopy(b, 0, d.toByteArray(), 0, d.size()); - System.arraycopy(b, d.size(), _cloakKey, 0, _cloakKey.length); - h = SHA256Generator.getInstance().calculateHash(b); - } else { - h = d.calculateHash(); - } - return h.toBase64().substring(0, 8) + ".i2p"; + String hf; + String hc; + + byte[] b = new byte[d.size() + this.cloakKey.length]; + System.arraycopy(b, 0, d.toByteArray(), 0, d.size()); + System.arraycopy(b, d.size(), this.cloakKey, 0, this.cloakKey.length); + hc = Base32.encode(SHA256Generator.getInstance().calculateHash(b).getData()); + + hf = Base32.encode(d.calculateHash().getData()); + + return this.hostname.replace("%f", hf).replace("%c", hc); } /** keep reading until we see USER or SERVER */ @@ -156,9 +158,10 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { if(field[0].charAt(0)==':') idx++; - try { command = field[idx++]; } - catch (IndexOutOfBoundsException ioobe) // wtf, server sent borked command? - { + try { + command = field[idx++]; + } catch (IndexOutOfBoundsException ioobe) { + // wtf, server sent borked command? throw new IOException("Dropping defective message: index out of bounds while extracting command."); } @@ -169,7 +172,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { // => // USER zzz1 abcd1234.i2p localhost :zzz // this whole class is for these two lines... - buf.append("USER ").append(field[idx]).append(' ').append(newHostname).append(".i2p "); + buf.append("USER ").append(field[idx]).append(' ').append(newHostname); + buf.append(' '); buf.append(field[idx+2]).append(' ').append(field[idx+3]).append("\r\n"); break; } @@ -181,4 +185,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable { _log.debug("All done, sending: " + buf.toString()); return buf.toString(); } + + private byte[] cloakKey; // 32 bytes of stuff to scramble the dest with + private String hostname; } diff --git a/core/java/src/net/i2p/data/PrivateKeyFile.java b/core/java/src/net/i2p/data/PrivateKeyFile.java index d9e52aecc04325b9427cd27df7ccc9fd11aa0c35..b5d68ee41194f8eb27bb5c7926ad461517281985 100644 --- a/core/java/src/net/i2p/data/PrivateKeyFile.java +++ b/core/java/src/net/i2p/data/PrivateKeyFile.java @@ -261,7 +261,7 @@ public class PrivateKeyFile { public String toString() { StringBuffer s = new StringBuffer(128); s.append("Dest: "); - s.append(this.dest.toBase64()); + s.append(this.dest != null ? this.dest.toBase64() : "null"); s.append("\nContains: "); s.append(this.dest); s.append("\nPrivate Key: "); diff --git a/history.txt b/history.txt index 62c4430e9197ee1d30fbb0592be178e0792ecdc0..e5bfe64788e824c9130b5b5339d5b27e5d389be6 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,54 @@ +2009-03-16 zzz + * help.jsp: Add some + * I2PTunnel: Cleanup + * I2PTunnelHTTPClient: Fix NPE on delayed open + * I2PTunnelHTTPServer: Maybe catch an NPE + * SOCKS: Allow .onion addresses for onioncat testing + * Tunnel: Catch a rare AIOOB + +2009-03-09 zzz + * Client: + - Clean up retry code + - Bring I2CP listen error to the summary bar + http://forum.i2p/viewtopic.php?t=3133 + * I2PSnark: Remove the http from the add torrent box + * I2PTunnel: + - Add persistent key option for standard and IRC clients + - Add delay-open option for clients + - Get regenerate-dest-on-reconnect working + - Add default key file name + - Add link to addressbook + - I2PSink: Send protocol byte + * OCMOSJ: + - Change from 5% reply requests to at least + once per minute, in hopes of reducing IRC drops + - More clean up of the cache cleaning + * Routerconsole: Don't OOM configpeer.jsp on huge blocklists + +2009-02-26 zzz + * I2CP Client: Add support for muxing + * I2PTunnel: + - Add new IRCServer tunnel type + - Add SOCKS 4/4a support + - Catch OOMs in HTTPServer + - Name the IRCClient filter threads + - Port Streamr to I2PTunnel + - The beginnings of SOCKS UDP support + * Naming: Add reverse lookup by hash + * OCMOSJ: Clean up the cache cleaning + * Router: Move addShutdownTask from Router to I2PAppContext + so that apps can register more easily + * Routerconsole: + - Thread hard shutdown and restart requests from the routerconsole, + and add a delay even if no tunnels, to allow time for a UI response + - Sort the summary bar destinations + - Move dest-to-hash converter to new helper class so we can + use it in i2ptunnel + +2009-02-22 sponge + * BOB: Orphan tunnel issue fix, bump BOB version + * bump to Build 6 + 2009-02-16 zzz * Streaming lib: Plug timer leak, don't send keepalives after close, don't disconnect hard after close diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 5203f2360b8c639e5b7467177c7101dc9a20b67e..6ade2ee81032a9681f7555a074bd3834bd9d4d64 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -17,7 +17,7 @@ import net.i2p.CoreVersion; public class RouterVersion { public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 5; + public final static long BUILD = 9; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID);