diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java index 16da28ce9c019e2b588cacf7d83d0983e260e6e0..4a13844cb400e0d09b2261844cbd0cdae369a5c7 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 = "05", BEXT = ""; + public static final String BMAJ = "00", BMIN = "00", BREV = "06", BEXT = ""; public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT; private Socket server; private Properties props; @@ -1263,11 +1263,11 @@ public class DoCMDS implements Runnable { tunnel = new MUXlisten(database, nickinfo, _log); Thread t = new Thread(tunnel); t.start(); - try { - Thread.sleep(1000 * 10); // Slow down the startup. - } catch(InterruptedException ie) { - // ignore it - } + // try { + // Thread.sleep(1000 * 10); // Slow down the startup. + // } catch(InterruptedException ie) { + // // ignore it + // } out.println("OK tunnel starting"); } catch (I2PException e) { out.println("ERROR starting tunnel: " + e); diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java index a8115893db8ca2f650bf976407356e647ecb0354..caaadc76d515aa31503bd41dc892fdb077f52cab 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,91 +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); -// try { -// if (info.exists("INPORT")) { -// tgwatch = 2; -// } -// } catch (Exception e) { -// try { -// runlock(); -// } catch (Exception e2) { -// break die; -// } -// break die; -// } - 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 (I2PException 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"); - - - // Previous level does this cleanup now. - // - // try { - // serverSocket.close(); - // } catch (I2PException e) { - // nop - //} - // need to kill off the socket manager too. - // I2PSession session = socketManager.getSession(); - // if (session != null) { - // System.out.println("I2Plistener: destroySession"); - // try { - // session.destroySession(); - // } catch (I2PSessionException ex) { - // nop - // } - //} - // System.out.println("I2Plistener: Waiting for children"); - // while (Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish - // try { - // Thread.sleep(100); //sleep for 100 ms (One tenth second) - // } catch (Exception e) { - // nop - // } - //} - - // 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 0984823b6e631ee19f8ff5a73e185fa3cdae808d..73e936c61b3cf7b77970820a63dbcdd9c8eb01bf 100644 --- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java +++ b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java @@ -23,7 +23,6 @@ */ package net.i2p.BOB; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; @@ -71,90 +70,99 @@ public class I2PtoTCP implements Runnable { String host; int port; boolean tell; -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; - } + InputStream in = null; + OutputStream out = null; + InputStream Iin = null; + OutputStream Iout = null; + try { + 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) { - try { - in.close(); - } catch(Exception ex) { - } - try { - out.close(); - } catch(Exception ex) { - } - try { - Iin.close(); - } catch(Exception ex) { - } + 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 { - 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 dc30c5445d0d31ca3e668e5b1cf14a491f21b112..f77d5bc82d887e15f0c92357a5695f56aaa3d372 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,234 +131,195 @@ public class MUXlisten implements Runnable { */ public void run() { I2PServerSocket SS = null; - int ticks = 1200; // Allow 120 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) { 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 (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(); + } - if (come_in) { - // TCP -> I2P - TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log); - Thread q = new Thread(tg, conn, "BOBTCPlistener" + N); - q.start(); - } + if (come_in) { + // TCP -> I2P + TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log); + q = new Thread(tg, conn, "BOBTCPlistener " + N); + q.start(); + } - try { - wlock(); try { - info.add("STARTING", new Boolean(false)); + wlock(); + try { + info.add("STARTING", new Boolean(false)); + } catch (Exception e) { + wunlock(); + break die; + } } catch (Exception e) { - wunlock(); break die; } - } 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) { + wunlock(); + } catch (Exception e) { break die; } - try { - rlock(); + boolean spin = true; + while (spin) { + try { + Thread.sleep(1000); //sleep for 1 second + } catch (InterruptedException e) { + break die; + } try { - spin = info.get("STOPPING").equals(Boolean.FALSE); + 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; } - } catch (Exception e) { - break die; } + try { - runlock(); + wlock(); + try { + info.add("RUNNING", new Boolean(false)); + } catch (Exception e) { + wunlock(); + break die; + } } 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 - - 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) { - } - } + } // die - I2PSession session = socketManager.getSession(); - if (session != null) { - // System.out.println("I2Plistener: destroySession"); - try { - session.destroySession(); - } catch (I2PSessionException ex) { - // nop - } + } catch (Exception e) { + // System.out.println("MUXlisten: Caught an exception" + e); + break quit; } + } // quit + } finally { + // Start cleanup. Allow threads above this one to catch the stop signal. + try { + Thread.sleep(250); + } catch (InterruptedException ex) { + } + // zero out everything. + try { + wlock(); try { - socketManager.destroySocketManager(); + info.add("STARTING", new Boolean(false)); + info.add("STOPPING", new Boolean(false)); + info.add("RUNNING", new Boolean(false)); } catch (Exception e) { - // nop + wunlock(); + return; } - // Wait for child threads and thread groups to die - // System.out.println("MUXlisten: waiting for children"); - if (tg.activeCount() + tg.activeGroupCount() != 0) { - while ((tg.activeCount() + tg.activeGroupCount() != 0) && ticks != 0) { - tg.interrupt(); // unwedge any blocking threads. - 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. - } - } - tg.destroy(); - // Zap reference to the ThreadGroup so the JVM can GC it. - tg = null; + wunlock(); } catch (Exception e) { - // System.out.println("MUXlisten: Caught an exception" + e); - break quit; } - } // quit - // This is here to catch when something fucks up REALLY bad. - if (tg != null) { + 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) { } } + try { socketManager.destroySocketManager(); } catch (Exception e) { // nop - } - ticks = 600; // 60 seconds - if (tg.activeCount() + tg.activeGroupCount() != 0) { - while ((tg.activeCount() + tg.activeGroupCount() != 0) && ticks != 0) { - tg.interrupt(); // unwedge any blocking threads. - ticks--; - try { - Thread.sleep(100); //sleep for 100 ms (One tenth second) - } catch (InterruptedException ex) { - // nop + } + // Wait around till all threads are collected. + if (tg != null) { + String boner = tg.getName(); + _log.warn("BOB: MUXlisten: Starting thread collection for: " + boner); + // tg.interrupt(); // give my stuff a small smack again. + if (tg.activeCount() + tg.activeGroupCount() != 0) { + int foo = tg.activeCount() + tg.activeGroupCount(); + // hopefully no longer needed! + // int bar = foo; + // System.out.println("BOB: MUXlisten: Waiting on threads for " + boner); + // System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); + // visit(tg, 0, boner); + // System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n"); + // Happily spin forever :-( + while (foo != 0) { + foo = tg.activeCount() + tg.activeGroupCount(); + // if (foo != bar) { + // System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); + // visit(tg, 0, boner); + // System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n"); + // } + // bar = foo; + try { + Thread.sleep(100); //sleep for 100 ms (One tenth second) + } catch (InterruptedException ex) { + // nop + } } } - } - if (tg.activeCount() + tg.activeGroupCount() == 0) { + _log.warn("BOB: MUXlisten: Threads went away. Success: " + boner); tg.destroy(); // Zap reference to the ThreadGroup so the JVM can GC it. tg = null; - } else { - System.out.println("BOB: MUXlisten: Can't kill threads. Please send the following dump to sponge@mail.i2p"); - System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN"); - visit(tg, 0); - System.out.println("BOB: MUXlisten: ThreadGroup dump END\n\n"); - } - } - - // This is here to catch when something fucks up REALLY bad. -// if (tg != null) { -// System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!"); -// System.out.println("BOB: MUXlisten: Please email the following dump to sponge@mail.i2p"); -// WrapperManager.requestThreadDump(); -// System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!"); -// System.out.println("BOB: MUXlisten: Please email the above dump to sponge@mail.i2p"); -// } - // 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) { } - } - // Debugging... - - /** + // Debugging... None of this is normally used. + /** * Find the root thread group and print them all. * */ @@ -371,7 +330,7 @@ die: } // Visit each thread group - visit(root, 0); + visit(root, 0, root.getName()); } /** @@ -379,7 +338,7 @@ die: * @param group ThreadGroup to visit * @param level Current level */ - private static void visit(ThreadGroup group, int level) { + private static void visit(ThreadGroup group, int level, String tn) { // Get threads in `group' int numThreads = group.activeCount(); Thread[] threads = new Thread[numThreads * 2]; @@ -389,7 +348,36 @@ die: for (int i = 0; i < numThreads; i++) { // Get thread Thread thread = threads[i]; - System.out.println("BOB: MUXlisten: " + indent + thread.toString()); + System.out.println("BOB: MUXlisten: " + tn + ": " + indent + thread.toString()); + } + + // Get thread subgroups of `group' + int numGroups = group.activeGroupCount(); + ThreadGroup[] groups = new ThreadGroup[numGroups * 2]; + numGroups = group.enumerate(groups, false); + + // Recursively visit each subgroup + for (int i = 0; i < numGroups; i++) { + visit(groups[i], level + 1, groups[i].getName()); + } + } + + private static void nuke(ThreadGroup group, int level) { + // Get threads in `group' + int numThreads = group.activeCount(); + Thread[] threads = new Thread[numThreads * 2]; + numThreads = group.enumerate(threads, false); + // Enumerate each thread in `group' and stop it. + for (int i = 0; i < numThreads; i++) { + // Get thread + Thread thread = threads[i]; + try { + if (thread.isAlive()) { + thread.stop(); + } + } catch (SecurityException se) { + //nop + } } // Get thread subgroups of `group' @@ -399,7 +387,14 @@ die: // Recursively visit each subgroup for (int i = 0; i < numGroups; i++) { - visit(groups[i], level + 1); + nuke(groups[i], level + 1); + } + try { + group.destroy(); + } catch (IllegalThreadStateException IE) { + //nop + } catch (SecurityException se) { + //nop } } } diff --git a/apps/BOB/src/net/i2p/BOB/TCPio.java b/apps/BOB/src/net/i2p/BOB/TCPio.java index d4b353c5498053592e88e8531c919ae2123d24bd..d92a5cef07f8d0025f184a7f0c9d125e8e56fe80 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPio.java +++ b/apps/BOB/src/net/i2p/BOB/TCPio.java @@ -87,23 +87,13 @@ public class TCPio implements Runnable { boolean spin = true; try { while(spin) { - // database.getReadLock(); - // info.getReadLock(); - // spin = info.get("RUNNING").equals(Boolean.TRUE); - // info.releaseReadLock(); - // database.releaseReadLock(); b = Ain.read(a, 0, 1); - // System.out.println(info.get("NICKNAME").toString() + " " + b); if(b > 0) { Aout.write(a, 0, b); } else if(b == 0) { Thread.yield(); // this should act like a mini sleep. if(Ain.available() == 0) { -// try { - // Thread.yield(); Thread.sleep(10); -// } catch(InterruptedException ex) { -// } } } else { /* according to the specs: @@ -119,19 +109,16 @@ public class TCPio implements Runnable { return; } } - // System.out.println("TCPio: RUNNING = false"); } catch(Exception e) { // Eject!!! Eject!!! //System.out.println("TCPio: Caught an exception " + e); try { Ain.close(); } catch (IOException ex) { -// Logger.getLogger(TCPio.class.getName()).log(Level.SEVERE, null, ex); } try { Aout.close(); } catch (IOException ex) { -// Logger.getLogger(TCPio.class.getName()).log(Level.SEVERE, null, ex); } return; } diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java index 78155eb787057f4e00e4e1beeed61fc57b9218e7..0ac67d277b8919d685ed335f2126c438260b6e19 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; @@ -73,16 +75,6 @@ public class TCPlistener implements Runnable { info.releaseReadLock(); } - private void wlock() throws Exception { - database.getWriteLock(); - info.getWriteLock(); - } - - private void wunlock() throws Exception { - info.releaseWriteLock(); - database.releaseWriteLock(); - } - /** * Simply listen on TCP port, and thread connections * @@ -90,124 +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); // Half of the expected time from MUXlisten - while (spin) { - try { - rlock(); - } catch (Exception e) { - break die; + try { + if (info.exists("OUTPORT")) { + tgwatch = 2; } + } catch (Exception e) { try { - spin = info.get("RUNNING").equals(Boolean.TRUE); - } catch (Exception e) { - try { - runlock(); - } catch (Exception e2) { - break die; - } + runlock(); + } catch (Exception e2) { break die; } - 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 /* , info, database */); - Thread t = new Thread(conn_c, "BOBTCPtoI2P"); - t.start(); - g = false; - } - } - //System.out.println("TCPlistener: destroySession"); - listener.close(); - } catch (IOException ioe) { - try { - listener.close(); - } catch (IOException e) { + break die; } - // Fatal failure, cause a stop event try { - rlock(); - try { - spin = info.get("RUNNING").equals(Boolean.TRUE); - } catch (Exception e) { - runlock(); - break die; - } + runlock(); } catch (Exception e) { break die; } - if (spin) { - try { - wlock(); + try { + Socket server = new Socket(); + listener.setSoTimeout(50); // We don't block, we cycle and check. + while (spin) { try { - info.add("STOPPING", new Boolean(true)); - info.add("RUNNING", new Boolean(false)); + rlock(); } catch (Exception e) { - wunlock(); break die; } - } catch (Exception e) { - break die; + try { + spin = info.get("RUNNING").equals(Boolean.TRUE); + } catch (Exception e) { + try { + runlock(); + } catch (Exception e2) { + break die; + } + break die; + } + 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; + } } + listener.close(); + } catch (IOException ioe) { try { - wunlock(); - } catch (Exception e) { - break die; + listener.close(); + } catch (IOException e) { } } } + } finally { + try { + listener.close(); + } catch (IOException ex) { + } + //System.out.println("TCPlistener: " + Thread.currentThread().getName() + "Done."); } - // Previous level does this cleanup now. - // - // need to kill off the socket manager too. - // I2PSession session = socketManager.getSession(); - // if (session != null) { - // try { - // session.destroySession(); - // } catch (I2PSessionException ex) { - // nop - // } - //} - //System.out.println("TCPlistener: Waiting for children"); - //while (Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish - // try { - // Thread.sleep(100); //sleep for 100 ms (One tenth second) - // } catch (Exception e) { - // // nop - // } - //} - //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 c376e16fe1bf8af9dd1e8f5ac25cd5d3a745936c..f3f2c74456ed3e3d1d6e4ccc7b07d99505ce0942 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,90 +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 -// 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); + + 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(InterruptedException e) { - // nop -// } + } + + } 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. } - // System.out.println("TCPtoI2P: Going away..."); - } 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) { + } catch (Exception e) { Emsg("ERROR " + e.toString(), out); } - - } 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/apps/desktopgui/nbproject/build-impl.xml b/apps/desktopgui/nbproject/build-impl.xml index f8fea458d1f346442380fd849ea37ea18712ff34..039f8788f1ca19268562c37f54c28030b53894f8 100644 --- a/apps/desktopgui/nbproject/build-impl.xml +++ b/apps/desktopgui/nbproject/build-impl.xml @@ -152,7 +152,7 @@ is divided into following sections: <attribute default="${includes}" name="includes"/> <attribute default="${excludes}" name="excludes"/> <attribute default="${javac.debug}" name="debug"/> - <attribute default="" name="sourcepath"/> + <attribute default="/does/not/exist" name="sourcepath"/> <element name="customize" optional="true"/> <sequential> <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}"> @@ -218,13 +218,13 @@ is divided into following sections: </sequential> </macrodef> </target> - <target name="-init-macrodef-nbjpda"> + <target depends="-init-debug-args" name="-init-macrodef-nbjpda"> <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> <attribute default="${main.class}" name="name"/> <attribute default="${debug.classpath}" name="classpath"/> <attribute default="" name="stopclassname"/> <sequential> - <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="dt_socket"> + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}"> <classpath> <path path="@{classpath}"/> </classpath> @@ -255,6 +255,12 @@ is divided into following sections: <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none"> <istrue value="${have-jdk-older-than-1.4}"/> </condition> + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem"> + <os family="windows"/> + </condition> + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}"> + <isset property="debug.transport"/> + </condition> </target> <target depends="-init-debug-args" name="-init-macrodef-debug"> <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> @@ -264,7 +270,7 @@ is divided into following sections: <sequential> <java classname="@{classname}" dir="${work.dir}" fork="true"> <jvmarg line="${debug-args-line}"/> - <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/> <jvmarg line="${run.jvmargs}"/> <classpath> <path path="@{classpath}"/> @@ -311,6 +317,13 @@ is divided into following sections: =================== --> <target depends="init" name="deps-jar" unless="no.deps"/> + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/> + <target depends="init" name="-check-automatic-build"> + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/> + </target> + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build"> + <antcall target="clean"/> + </target> <target depends="init,deps-jar" name="-pre-pre-compile"> <mkdir dir="${build.classes.dir}"/> </target> @@ -331,7 +344,7 @@ is divided into following sections: <!-- Empty placeholder for easier customization. --> <!-- You can override this target in the ../build.xml file. --> </target> - <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/> + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/> <target name="-pre-compile-single"> <!-- Empty placeholder for easier customization. --> <!-- You can override this target in the ../build.xml file. --> @@ -345,7 +358,7 @@ is divided into following sections: <!-- Empty placeholder for easier customization. --> <!-- You can override this target in the ../build.xml file. --> </target> - <target depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/> + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/> <!-- ==================== JAR BUILDING SECTION diff --git a/apps/desktopgui/nbproject/genfiles.properties b/apps/desktopgui/nbproject/genfiles.properties index 1b326007c72e7a85df4b7923826955a2cbbe1fd3..f6b0f837bcfabb640d6b0fd4fb85db89aa0b70da 100644 --- a/apps/desktopgui/nbproject/genfiles.properties +++ b/apps/desktopgui/nbproject/genfiles.properties @@ -3,6 +3,6 @@ build.xml.script.CRC32=9785bb9a build.xml.stylesheet.CRC32=be360661 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=c4b345cd -nbproject/build-impl.xml.script.CRC32=74d3fda2 -nbproject/build-impl.xml.stylesheet.CRC32=487672f9 +nbproject/build-impl.xml.data.CRC32=f630f8db +nbproject/build-impl.xml.script.CRC32=8c02c081 +nbproject/build-impl.xml.stylesheet.CRC32=65b8de21 diff --git a/apps/desktopgui/nbproject/project.properties b/apps/desktopgui/nbproject/project.properties index b7a05f8ed6df77b4543a58141526bd4976695be3..e9f5d1a2a159f3695a72d31d03a2e8aeb743ce61 100644 --- a/apps/desktopgui/nbproject/project.properties +++ b/apps/desktopgui/nbproject/project.properties @@ -58,7 +58,7 @@ jnlp.codebase.url=file:/home/mathias/Documenten/Programmeren/i2p_monotone/repo/i jnlp.enabled=false jnlp.offline-allowed=false jnlp.signed=false -main.class=desktopgui.Main +main.class=net.i2p.desktopgui.desktopgui.Main manifest.file=manifest.mf meta.inf.dir=${src.dir}/META-INF platform.active=default_platform diff --git a/apps/desktopgui/nbproject/project.xml b/apps/desktopgui/nbproject/project.xml index 09409a64cda6d6b494561a5fccf74c9d90b73245..9dba9493c19d106655401d5e0fabc02381858ef8 100644 --- a/apps/desktopgui/nbproject/project.xml +++ b/apps/desktopgui/nbproject/project.xml @@ -13,7 +13,7 @@ </test-roots> </data> <swingapp xmlns="http://www.netbeans.org/ns/form-swingapp/1"> - <application-class name="desktopgui.Main"/> + <application-class name="net.i2p.desktopgui.desktopgui.Main"/> </swingapp> </configuration> </project> diff --git a/apps/desktopgui/src/gui/GeneralConfiguration.java b/apps/desktopgui/src/gui/GeneralConfiguration.java deleted file mode 100644 index 912026bf12d218bb5703a1b850180df7772355f3..0000000000000000000000000000000000000000 --- a/apps/desktopgui/src/gui/GeneralConfiguration.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * GeneralConfiguration.java - * - * Created on 10 april 2009, 19:04 - */ - -package gui; - -/** - * - * @author mathias - */ -public class GeneralConfiguration extends javax.swing.JFrame { - - /** Creates new form GeneralConfiguration */ - public GeneralConfiguration() { - initComponents(); - this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); - this.setVisible(true); - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents - private void initComponents() { - - jPanel1 = new javax.swing.JPanel(); - cancel = new javax.swing.JToggleButton(); - ok = new javax.swing.JToggleButton(); - jTabbedPane1 = new javax.swing.JTabbedPane(); - jPanel2 = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - jTextField1 = new javax.swing.JTextField(); - jTextField2 = new javax.swing.JTextField(); - jComboBox1 = new javax.swing.JComboBox(); - jComboBox2 = new javax.swing.JComboBox(); - jLabel3 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); - jTextField3 = new javax.swing.JTextField(); - jTextField4 = new javax.swing.JTextField(); - jLabel5 = new javax.swing.JLabel(); - jLabel6 = new javax.swing.JLabel(); - jLabel7 = new javax.swing.JLabel(); - jPanel3 = new javax.swing.JPanel(); - jLabel8 = new javax.swing.JLabel(); - jRadioButton1 = new javax.swing.JRadioButton(); - jRadioButton2 = new javax.swing.JRadioButton(); - jRadioButton3 = new javax.swing.JRadioButton(); - jToggleButton1 = new javax.swing.JToggleButton(); - jToggleButton2 = new javax.swing.JToggleButton(); - jToggleButton3 = new javax.swing.JToggleButton(); - jPanel4 = new javax.swing.JPanel(); - jScrollPane1 = new javax.swing.JScrollPane(); - jScrollPane2 = new javax.swing.JScrollPane(); - jLabel9 = new javax.swing.JLabel(); - jLabel10 = new javax.swing.JLabel(); - jLabel11 = new javax.swing.JLabel(); - jPanel5 = new javax.swing.JPanel(); - jPanel6 = new javax.swing.JPanel(); - - setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - setName("Form"); // NOI18N - - jPanel1.setName("jPanel1"); // NOI18N - - org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(GeneralConfiguration.class); - cancel.setText(resourceMap.getString("cancel.text")); // NOI18N - cancel.setName("cancel"); // NOI18N - - ok.setText(resourceMap.getString("ok.text")); // NOI18N - ok.setName("ok"); // NOI18N - - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addContainerGap(475, Short.MAX_VALUE) - .addComponent(ok) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancel) - .addContainerGap()) - ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cancel) - .addComponent(ok)) - .addContainerGap(14, Short.MAX_VALUE)) - ); - - jTabbedPane1.setName("jTabbedPane1"); // NOI18N - - jPanel2.setName("jPanel2"); // NOI18N - jPanel2.setLayout(null); - - jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N - jLabel1.setName("jLabel1"); // NOI18N - jPanel2.add(jLabel1); - jLabel1.setBounds(20, 20, 140, 30); - - jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N - jLabel2.setName("jLabel2"); // NOI18N - jPanel2.add(jLabel2); - jLabel2.setBounds(20, 60, 140, 30); - - jTextField1.setText(resourceMap.getString("jTextField1.text")); // NOI18N - jTextField1.setName("jTextField1"); // NOI18N - jPanel2.add(jTextField1); - jTextField1.setBounds(160, 20, 77, 27); - - jTextField2.setText(resourceMap.getString("jTextField2.text")); // NOI18N - jTextField2.setName("jTextField2"); // NOI18N - jPanel2.add(jTextField2); - jTextField2.setBounds(160, 60, 77, 27); - - jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); - jComboBox1.setName("jComboBox1"); // NOI18N - jPanel2.add(jComboBox1); - jComboBox1.setBounds(240, 20, 78, 27); - - jComboBox2.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); - jComboBox2.setName("jComboBox2"); // NOI18N - jPanel2.add(jComboBox2); - jComboBox2.setBounds(240, 60, 78, 27); - - jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N - jLabel3.setName("jLabel3"); // NOI18N - jPanel2.add(jLabel3); - jLabel3.setBounds(330, 20, 97, 30); - - jLabel4.setText(resourceMap.getString("jLabel4.text")); // NOI18N - jLabel4.setName("jLabel4"); // NOI18N - jPanel2.add(jLabel4); - jLabel4.setBounds(330, 60, 97, 30); - - jTextField3.setText(resourceMap.getString("jTextField3.text")); // NOI18N - jTextField3.setName("jTextField3"); // NOI18N - jPanel2.add(jTextField3); - jTextField3.setBounds(440, 20, 60, 27); - - jTextField4.setText(resourceMap.getString("jTextField4.text")); // NOI18N - jTextField4.setName("jTextField4"); // NOI18N - jPanel2.add(jTextField4); - jTextField4.setBounds(440, 60, 60, 27); - - jLabel5.setText(resourceMap.getString("jLabel5.text")); // NOI18N - jLabel5.setName("jLabel5"); // NOI18N - jPanel2.add(jLabel5); - jLabel5.setBounds(510, 20, 19, 30); - - jLabel6.setText(resourceMap.getString("jLabel6.text")); // NOI18N - jLabel6.setName("jLabel6"); // NOI18N - jPanel2.add(jLabel6); - jLabel6.setBounds(510, 60, 19, 30); - - jLabel7.setText(resourceMap.getString("jLabel7.text")); // NOI18N - jLabel7.setName("jLabel7"); // NOI18N - jPanel2.add(jLabel7); - jLabel7.setBounds(20, 100, 520, 70); - - jTabbedPane1.addTab(resourceMap.getString("jPanel2.TabConstraints.tabTitle"), jPanel2); // NOI18N - - jPanel3.setName("jPanel3"); // NOI18N - - jLabel8.setText(resourceMap.getString("jLabel8.text")); // NOI18N - jLabel8.setName("jLabel8"); // NOI18N - - jRadioButton1.setText(resourceMap.getString("jRadioButton1.text")); // NOI18N - jRadioButton1.setName("jRadioButton1"); // NOI18N - - jRadioButton2.setText(resourceMap.getString("jRadioButton2.text")); // NOI18N - jRadioButton2.setName("jRadioButton2"); // NOI18N - - jRadioButton3.setText(resourceMap.getString("jRadioButton3.text")); // NOI18N - jRadioButton3.setName("jRadioButton3"); // NOI18N - - jToggleButton1.setText(resourceMap.getString("jToggleButton1.text")); // NOI18N - jToggleButton1.setName("jToggleButton1"); // NOI18N - - jToggleButton2.setText(resourceMap.getString("jToggleButton2.text")); // NOI18N - jToggleButton2.setName("jToggleButton2"); // NOI18N - - jToggleButton3.setText(resourceMap.getString("jToggleButton3.text")); // NOI18N - jToggleButton3.setName("jToggleButton3"); // NOI18N - - javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); - jPanel3.setLayout(jPanel3Layout); - jPanel3Layout.setHorizontalGroup( - jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel3Layout.createSequentialGroup() - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel3Layout.createSequentialGroup() - .addGap(20, 20, 20) - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel8) - .addGroup(jPanel3Layout.createSequentialGroup() - .addComponent(jToggleButton1) - .addGap(18, 18, 18) - .addComponent(jToggleButton2)))) - .addGroup(jPanel3Layout.createSequentialGroup() - .addGap(40, 40, 40) - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jRadioButton2) - .addComponent(jRadioButton1) - .addComponent(jRadioButton3)))) - .addGap(9, 9, 9)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() - .addContainerGap(339, Short.MAX_VALUE) - .addComponent(jToggleButton3) - .addContainerGap()) - ); - jPanel3Layout.setVerticalGroup( - jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel3Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel8) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jRadioButton1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jRadioButton2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jRadioButton3) - .addGap(18, 18, 18) - .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jToggleButton1) - .addComponent(jToggleButton2)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 181, Short.MAX_VALUE) - .addComponent(jToggleButton3) - .addContainerGap()) - ); - - jTabbedPane1.addTab(resourceMap.getString("jPanel3.TabConstraints.tabTitle"), jPanel3); // NOI18N - - jPanel4.setName("jPanel4"); // NOI18N - - jScrollPane1.setName("jScrollPane1"); // NOI18N - - jScrollPane2.setName("jScrollPane2"); // NOI18N - - jLabel9.setText(resourceMap.getString("jLabel9.text")); // NOI18N - jLabel9.setName("jLabel9"); // NOI18N - - jLabel10.setText(resourceMap.getString("jLabel10.text")); // NOI18N - jLabel10.setName("jLabel10"); // NOI18N - - jLabel11.setText(resourceMap.getString("jLabel11.text")); // NOI18N - jLabel11.setName("jLabel11"); // NOI18N - - javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); - jPanel4.setLayout(jPanel4Layout); - jPanel4Layout.setHorizontalGroup( - jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE) - .addComponent(jLabel9, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE) - .addComponent(jLabel10) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE) - .addComponent(jLabel11)) - .addContainerGap()) - ); - jPanel4Layout.setVerticalGroup( - jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel10) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel11) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap()) - ); - - jTabbedPane1.addTab(resourceMap.getString("jPanel4.TabConstraints.tabTitle"), jPanel4); // NOI18N - - jPanel5.setName("jPanel5"); // NOI18N - - javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); - jPanel5.setLayout(jPanel5Layout); - jPanel5Layout.setHorizontalGroup( - jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 562, Short.MAX_VALUE) - ); - jPanel5Layout.setVerticalGroup( - jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 388, Short.MAX_VALUE) - ); - - jTabbedPane1.addTab(resourceMap.getString("jPanel5.TabConstraints.tabTitle"), jPanel5); // NOI18N - - jPanel6.setName("jPanel6"); // NOI18N - - javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); - jPanel6.setLayout(jPanel6Layout); - jPanel6Layout.setHorizontalGroup( - jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 562, Short.MAX_VALUE) - ); - jPanel6Layout.setVerticalGroup( - jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 388, Short.MAX_VALUE) - ); - - jTabbedPane1.addTab(resourceMap.getString("jPanel6.TabConstraints.tabTitle"), jPanel6); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addGap(12, 12, 12) - .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 566, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jTabbedPane1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); - - pack(); - }// </editor-fold>//GEN-END:initComponents - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JToggleButton cancel; - private javax.swing.JComboBox jComboBox1; - private javax.swing.JComboBox jComboBox2; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel10; - private javax.swing.JLabel jLabel11; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JLabel jLabel6; - private javax.swing.JLabel jLabel7; - private javax.swing.JLabel jLabel8; - private javax.swing.JLabel jLabel9; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel2; - private javax.swing.JPanel jPanel3; - private javax.swing.JPanel jPanel4; - private javax.swing.JPanel jPanel5; - private javax.swing.JPanel jPanel6; - private javax.swing.JRadioButton jRadioButton1; - private javax.swing.JRadioButton jRadioButton2; - private javax.swing.JRadioButton jRadioButton3; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JTabbedPane jTabbedPane1; - private javax.swing.JTextField jTextField1; - private javax.swing.JTextField jTextField2; - private javax.swing.JTextField jTextField3; - private javax.swing.JTextField jTextField4; - private javax.swing.JToggleButton jToggleButton1; - private javax.swing.JToggleButton jToggleButton2; - private javax.swing.JToggleButton jToggleButton3; - private javax.swing.JToggleButton ok; - // End of variables declaration//GEN-END:variables - -} diff --git a/apps/desktopgui/src/gui/resources/GeneralConfiguration.properties b/apps/desktopgui/src/gui/resources/GeneralConfiguration.properties deleted file mode 100644 index 3dc629a9715ac76d59515d7e02df719a4cb41375..0000000000000000000000000000000000000000 --- a/apps/desktopgui/src/gui/resources/GeneralConfiguration.properties +++ /dev/null @@ -1,29 +0,0 @@ - -jPanel2.TabConstraints.tabTitle=Speed -jPanel3.TabConstraints.tabTitle=Updates -jPanel4.TabConstraints.tabTitle=Tunnels/Services -jPanel5.TabConstraints.tabTitle=Network -jPanel6.TabConstraints.tabTitle=Advanced -cancel.text=Cancel -ok.text=OK -jLabel1.text=Upload speed: -jLabel2.text=Download speed: -jTextField1.text=jTextField1 -jTextField2.text=jTextField2 -jLabel3.text=Monthly usage: -jLabel4.text=Monthly usage: -jTextField3.text=jTextField3 -jTextField4.text=jTextField4 -jLabel5.text=GB -jLabel6.text=GB -jLabel7.text=Explanation ... -jLabel8.text=What is your preferred automatic update setting? -jRadioButton1.text=Only inform about updates -jRadioButton2.text=Download and verify update file, do not restart -jRadioButton3.text=Download, verify and restart -jToggleButton1.text=Check for updates now -jToggleButton2.text=Update available: update now -jToggleButton3.text=Advanced update configuration -jLabel9.text=Tunnel explanation -jLabel10.text=Client tunnels: -jLabel11.text=Server tunnels: diff --git a/apps/desktopgui/src/desktopgui/GUIVersion.java b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java similarity index 63% rename from apps/desktopgui/src/desktopgui/GUIVersion.java rename to apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java index 7bde544de8d05d1b0dbaecbf613f2d3667ce97c5..f4e948e52c05df8d2c848d9cb5221d77609120c7 100644 --- a/apps/desktopgui/src/desktopgui/GUIVersion.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java @@ -3,12 +3,12 @@ * and open the template in the editor. */ -package desktopgui; +package net.i2p.desktopgui.desktopgui; /** * * @author mathias */ public class GUIVersion { - public static final String VERSION = "0.0.1.1"; + public static final String VERSION = "0.0.1.2"; } diff --git a/apps/desktopgui/src/desktopgui/Main.java b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/Main.java similarity index 95% rename from apps/desktopgui/src/desktopgui/Main.java rename to apps/desktopgui/src/net/i2p/desktopgui/desktopgui/Main.java index 9d9708c8dd61b9a32ee9317e2aef273a6ae1a019..c3078163d4c64ff29d6c58927c3c3e71ddf3efd3 100644 --- a/apps/desktopgui/src/desktopgui/Main.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/Main.java @@ -1,4 +1,4 @@ -package desktopgui; +package net.i2p.desktopgui.desktopgui; /* * Main.java @@ -6,8 +6,8 @@ package desktopgui; -import gui.Tray; -import gui.SpeedSelector; +import net.i2p.desktopgui.gui.Tray; +import net.i2p.desktopgui.gui.SpeedSelector; import java.awt.SystemTray; import java.util.Properties; import java.util.logging.Level; @@ -16,7 +16,7 @@ import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import org.jdesktop.application.Application; import org.jdesktop.application.SingleFrameApplication; -import persistence.PropertyManager; +import net.i2p.desktopgui.persistence.PropertyManager; /** * The main class of the application. diff --git a/apps/desktopgui/src/desktopgui/resources/Main.properties b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/resources/Main.properties similarity index 100% rename from apps/desktopgui/src/desktopgui/resources/Main.properties rename to apps/desktopgui/src/net/i2p/desktopgui/desktopgui/resources/Main.properties diff --git a/apps/desktopgui/src/desktopgui/resources/Main_nl_BE.properties b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/resources/Main_nl_BE.properties similarity index 100% rename from apps/desktopgui/src/desktopgui/resources/Main_nl_BE.properties rename to apps/desktopgui/src/net/i2p/desktopgui/desktopgui/resources/Main_nl_BE.properties diff --git a/apps/desktopgui/src/gui/GeneralConfiguration.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form similarity index 71% rename from apps/desktopgui/src/gui/GeneralConfiguration.form rename to apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form index df02e3d967a24a23edea625e7fb33f3f4bc76984..7c0fc8edcdf41c794e426e3b8937ded3d2782e88 100644 --- a/apps/desktopgui/src/gui/GeneralConfiguration.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form @@ -1,8 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> <Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> + <NonVisualComponents> + <Component class="javax.swing.ButtonGroup" name="buttonGroup1"> + </Component> + </NonVisualComponents> <Properties> <Property name="defaultCloseOperation" type="int" value="3"/> + <Property name="title" type="java.lang.String" resourceKey="Form.title"/> <Property name="name" type="java.lang.String" value="Form" noResource="true"/> </Properties> <SyntheticProperties> @@ -11,6 +16,7 @@ <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> @@ -22,27 +28,27 @@ <Layout> <DimensionLayout dim="0"> <Group type="103" groupAlignment="0" attributes="0"> - <Component id="jPanel1" alignment="0" max="32767" attributes="0"/> + <Component id="applyPanel" alignment="0" max="32767" attributes="0"/> <Group type="102" attributes="0"> <EmptySpace min="12" pref="12" max="12" attributes="0"/> - <Component id="jTabbedPane1" pref="566" max="32767" attributes="0"/> + <Component id="settingsPanel" pref="566" max="32767" attributes="0"/> </Group> </Group> </DimensionLayout> <DimensionLayout dim="1"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="1" attributes="0"> - <Component id="jTabbedPane1" max="32767" attributes="0"/> + <Component id="settingsPanel" max="32767" attributes="0"/> <EmptySpace max="-2" attributes="0"/> - <Component id="jPanel1" min="-2" max="-2" attributes="0"/> + <Component id="applyPanel" min="-2" max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> </Layout> <SubComponents> - <Container class="javax.swing.JPanel" name="jPanel1"> + <Container class="javax.swing.JPanel" name="applyPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jPanel1" noResource="true"/> + <Property name="name" type="java.lang.String" value="applyPanel" noResource="true"/> </Properties> <Layout> @@ -84,21 +90,21 @@ </Component> </SubComponents> </Container> - <Container class="javax.swing.JTabbedPane" name="jTabbedPane1"> + <Container class="javax.swing.JTabbedPane" name="settingsPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jTabbedPane1" noResource="true"/> + <Property name="name" type="java.lang.String" value="settingsPanel" noResource="true"/> </Properties> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/> <SubComponents> - <Container class="javax.swing.JPanel" name="jPanel2"> + <Container class="javax.swing.JPanel" name="speedPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jPanel2" noResource="true"/> + <Property name="name" type="java.lang.String" value="speedPanel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> <JTabbedPaneConstraints tabName="Speed"> - <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel2.TabConstraints.tabTitle"/> + <Property name="tabTitle" type="java.lang.String" resourceKey="speedPanel.TabConstraints.tabTitle"/> </JTabbedPaneConstraints> </Constraint> </Constraints> @@ -107,10 +113,10 @@ <Property name="useNullLayout" type="boolean" value="true"/> </Layout> <SubComponents> - <Component class="javax.swing.JLabel" name="jLabel1"> + <Component class="javax.swing.JLabel" name="uploadSpeedLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel1.text"/> - <Property name="name" type="java.lang.String" value="jLabel1" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="uploadSpeedLabel.text"/> + <Property name="name" type="java.lang.String" value="uploadSpeedLabel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -118,10 +124,10 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JLabel" name="jLabel2"> + <Component class="javax.swing.JLabel" name="downloadSpeedLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel2.text"/> - <Property name="name" type="java.lang.String" value="jLabel2" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="downloadSpeedLabel.text"/> + <Property name="name" type="java.lang.String" value="downloadSpeedLabel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -129,58 +135,66 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JTextField" name="jTextField1"> + <Component class="javax.swing.JTextField" name="uploadspeed"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jTextField1.text"/> - <Property name="name" type="java.lang.String" value="jTextField1" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="uploadspeed.text"/> + <Property name="name" type="java.lang.String" value="uploadspeed" noResource="true"/> </Properties> + <Events> + <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="speedKeyTyped"/> + </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> <AbsoluteConstraints x="160" y="20" width="-1" height="-1"/> </Constraint> </Constraints> </Component> - <Component class="javax.swing.JTextField" name="jTextField2"> + <Component class="javax.swing.JTextField" name="downloadspeed"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jTextField2.text"/> - <Property name="name" type="java.lang.String" value="jTextField2" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="downloadspeed.text"/> + <Property name="name" type="java.lang.String" value="downloadspeed" noResource="true"/> </Properties> + <Events> + <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="speedKeyTyped"/> + </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> <AbsoluteConstraints x="160" y="60" width="-1" height="-1"/> </Constraint> </Constraints> </Component> - <Component class="javax.swing.JComboBox" name="jComboBox1"> + <Component class="javax.swing.JComboBox" name="uploadkbps"> <Properties> <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> - <StringArray count="4"> - <StringItem index="0" value="Item 1"/> - <StringItem index="1" value="Item 2"/> - <StringItem index="2" value="Item 3"/> - <StringItem index="3" value="Item 4"/> + <StringArray count="2"> + <StringItem index="0" value="kbps"/> + <StringItem index="1" value="kBps"/> </StringArray> </Property> - <Property name="name" type="java.lang.String" value="jComboBox1" noResource="true"/> + <Property name="name" type="java.lang.String" value="uploadkbps" noResource="true"/> </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="uploadkbpsActionPerformed"/> + </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> <AbsoluteConstraints x="240" y="20" width="-1" height="-1"/> </Constraint> </Constraints> </Component> - <Component class="javax.swing.JComboBox" name="jComboBox2"> + <Component class="javax.swing.JComboBox" name="downloadkbps"> <Properties> <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> - <StringArray count="4"> - <StringItem index="0" value="Item 1"/> - <StringItem index="1" value="Item 2"/> - <StringItem index="2" value="Item 3"/> - <StringItem index="3" value="Item 4"/> + <StringArray count="2"> + <StringItem index="0" value="kbps"/> + <StringItem index="1" value="kBps"/> </StringArray> </Property> - <Property name="name" type="java.lang.String" value="jComboBox2" noResource="true"/> + <Property name="name" type="java.lang.String" value="downloadkbps" noResource="true"/> </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="downloadkbpsActionPerformed"/> + </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> <AbsoluteConstraints x="240" y="60" width="-1" height="-1"/> @@ -209,22 +223,28 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JTextField" name="jTextField3"> + <Component class="javax.swing.JTextField" name="uploadgb"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jTextField3.text"/> - <Property name="name" type="java.lang.String" value="jTextField3" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="uploadgb.text"/> + <Property name="name" type="java.lang.String" value="uploadgb" noResource="true"/> </Properties> + <Events> + <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="uploadgbKeyTyped"/> + </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> <AbsoluteConstraints x="440" y="20" width="60" height="-1"/> </Constraint> </Constraints> </Component> - <Component class="javax.swing.JTextField" name="jTextField4"> + <Component class="javax.swing.JTextField" name="downloadgb"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jTextField4.text"/> - <Property name="name" type="java.lang.String" value="jTextField4" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="downloadgb.text"/> + <Property name="name" type="java.lang.String" value="downloadgb" noResource="true"/> </Properties> + <Events> + <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="downloadgbKeyTyped"/> + </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> <AbsoluteConstraints x="440" y="60" width="60" height="-1"/> @@ -266,14 +286,14 @@ </Component> </SubComponents> </Container> - <Container class="javax.swing.JPanel" name="jPanel3"> + <Container class="javax.swing.JPanel" name="updatesPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jPanel3" noResource="true"/> + <Property name="name" type="java.lang.String" value="updatesPanel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> <JTabbedPaneConstraints tabName="Updates"> - <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel3.TabConstraints.tabTitle"/> + <Property name="tabTitle" type="java.lang.String" resourceKey="updatesPanel.TabConstraints.tabTitle"/> </JTabbedPaneConstraints> </Constraint> </Constraints> @@ -286,20 +306,20 @@ <Group type="102" alignment="0" attributes="0"> <EmptySpace min="-2" pref="20" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> - <Component id="jLabel8" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="updateMethod" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0"> - <Component id="jToggleButton1" min="-2" max="-2" attributes="0"/> + <Component id="checkUpdates" min="-2" max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/> - <Component id="jToggleButton2" min="-2" max="-2" attributes="0"/> + <Component id="updateNow" min="-2" max="-2" attributes="0"/> </Group> </Group> </Group> <Group type="102" alignment="0" attributes="0"> <EmptySpace min="40" pref="40" max="40" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> - <Component id="jRadioButton2" alignment="0" min="-2" max="-2" attributes="0"/> - <Component id="jRadioButton1" alignment="0" min="-2" max="-2" attributes="0"/> - <Component id="jRadioButton3" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="updateDownload" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="updateInform" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="updateDownloadRestart" alignment="0" min="-2" max="-2" attributes="0"/> </Group> </Group> </Group> @@ -307,7 +327,7 @@ </Group> <Group type="102" alignment="1" attributes="0"> <EmptySpace pref="339" max="32767" attributes="0"/> - <Component id="jToggleButton3" min="-2" max="-2" attributes="0"/> + <Component id="advancedUpdateConfig" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> </Group> </Group> @@ -316,78 +336,87 @@ <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" attributes="0"> <EmptySpace max="-2" attributes="0"/> - <Component id="jLabel8" min="-2" max="-2" attributes="0"/> + <Component id="updateMethod" min="-2" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/> - <Component id="jRadioButton1" min="-2" max="-2" attributes="0"/> + <Component id="updateInform" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> - <Component id="jRadioButton2" min="-2" max="-2" attributes="0"/> + <Component id="updateDownload" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> - <Component id="jRadioButton3" min="-2" max="-2" attributes="0"/> + <Component id="updateDownloadRestart" min="-2" max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="3" attributes="0"> - <Component id="jToggleButton1" alignment="3" min="-2" max="-2" attributes="0"/> - <Component id="jToggleButton2" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="checkUpdates" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="updateNow" alignment="3" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace pref="181" max="32767" attributes="0"/> - <Component id="jToggleButton3" min="-2" max="-2" attributes="0"/> + <Component id="advancedUpdateConfig" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> </Layout> <SubComponents> - <Component class="javax.swing.JLabel" name="jLabel8"> + <Component class="javax.swing.JLabel" name="updateMethod"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel8.text"/> - <Property name="name" type="java.lang.String" value="jLabel8" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="updateMethod.text"/> + <Property name="name" type="java.lang.String" value="updateMethod" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JRadioButton" name="jRadioButton1"> + <Component class="javax.swing.JRadioButton" name="updateInform"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jRadioButton1.text"/> - <Property name="name" type="java.lang.String" value="jRadioButton1" noResource="true"/> + <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> + <ComponentRef name="buttonGroup1"/> + </Property> + <Property name="text" type="java.lang.String" resourceKey="updateInform.text"/> + <Property name="name" type="java.lang.String" value="updateInform" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JRadioButton" name="jRadioButton2"> + <Component class="javax.swing.JRadioButton" name="updateDownload"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jRadioButton2.text"/> - <Property name="name" type="java.lang.String" value="jRadioButton2" noResource="true"/> + <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> + <ComponentRef name="buttonGroup1"/> + </Property> + <Property name="text" type="java.lang.String" resourceKey="updateDownload.text"/> + <Property name="name" type="java.lang.String" value="updateDownload" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JRadioButton" name="jRadioButton3"> + <Component class="javax.swing.JRadioButton" name="updateDownloadRestart"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jRadioButton3.text"/> - <Property name="name" type="java.lang.String" value="jRadioButton3" noResource="true"/> + <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> + <ComponentRef name="buttonGroup1"/> + </Property> + <Property name="text" type="java.lang.String" resourceKey="updateDownloadRestart.text"/> + <Property name="name" type="java.lang.String" value="updateDownloadRestart" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JToggleButton" name="jToggleButton1"> + <Component class="javax.swing.JToggleButton" name="checkUpdates"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jToggleButton1.text"/> - <Property name="name" type="java.lang.String" value="jToggleButton1" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="checkUpdates.text"/> + <Property name="name" type="java.lang.String" value="checkUpdates" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JToggleButton" name="jToggleButton2"> + <Component class="javax.swing.JToggleButton" name="updateNow"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jToggleButton2.text"/> - <Property name="name" type="java.lang.String" value="jToggleButton2" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="updateNow.text"/> + <Property name="name" type="java.lang.String" value="updateNow" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JToggleButton" name="jToggleButton3"> + <Component class="javax.swing.JToggleButton" name="advancedUpdateConfig"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jToggleButton3.text"/> - <Property name="name" type="java.lang.String" value="jToggleButton3" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="advancedUpdateConfig.text"/> + <Property name="name" type="java.lang.String" value="advancedUpdateConfig" noResource="true"/> </Properties> </Component> </SubComponents> </Container> - <Container class="javax.swing.JPanel" name="jPanel4"> + <Container class="javax.swing.JPanel" name="tunnelPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jPanel4" noResource="true"/> + <Property name="name" type="java.lang.String" value="tunnelPanel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> <JTabbedPaneConstraints tabName="Tunnels/Services"> - <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel4.TabConstraints.tabTitle"/> + <Property name="tabTitle" type="java.lang.String" resourceKey="tunnelPanel.TabConstraints.tabTitle"/> </JTabbedPaneConstraints> </Constraint> </Constraints> @@ -398,11 +427,11 @@ <Group type="102" alignment="0" attributes="0"> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> - <Component id="jScrollPane2" alignment="1" pref="538" max="32767" attributes="0"/> - <Component id="jLabel9" alignment="0" pref="538" max="32767" attributes="0"/> - <Component id="jLabel10" alignment="0" min="-2" max="-2" attributes="0"/> - <Component id="jScrollPane1" alignment="0" pref="538" max="32767" attributes="0"/> - <Component id="jLabel11" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="serverFrame" alignment="1" pref="538" max="32767" attributes="0"/> + <Component id="tunnelsExplanation" alignment="0" pref="538" max="32767" attributes="0"/> + <Component id="clientTunnelLabel" alignment="0" min="-2" max="-2" attributes="0"/> + <Component id="clientFrame" alignment="0" pref="538" max="32767" attributes="0"/> + <Component id="serverTunnelLabel" alignment="0" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> </Group> @@ -412,63 +441,63 @@ <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0"> <EmptySpace min="-2" max="-2" attributes="0"/> - <Component id="jLabel10" min="-2" max="-2" attributes="0"/> + <Component id="clientTunnelLabel" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/> - <Component id="jScrollPane1" pref="119" max="32767" attributes="0"/> + <Component id="clientFrame" pref="119" max="32767" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/> - <Component id="jLabel11" min="-2" max="-2" attributes="0"/> + <Component id="serverTunnelLabel" min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/> - <Component id="jScrollPane2" pref="122" max="32767" attributes="0"/> + <Component id="serverFrame" pref="122" max="32767" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/> - <Component id="jLabel9" min="-2" pref="65" max="-2" attributes="0"/> + <Component id="tunnelsExplanation" min="-2" pref="65" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> </Layout> <SubComponents> - <Container class="javax.swing.JScrollPane" name="jScrollPane1"> + <Container class="javax.swing.JScrollPane" name="clientFrame"> <Properties> - <Property name="name" type="java.lang.String" value="jScrollPane1" noResource="true"/> + <Property name="name" type="java.lang.String" value="clientFrame" noResource="true"/> </Properties> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> </Container> - <Container class="javax.swing.JScrollPane" name="jScrollPane2"> + <Container class="javax.swing.JScrollPane" name="serverFrame"> <Properties> - <Property name="name" type="java.lang.String" value="jScrollPane2" noResource="true"/> + <Property name="name" type="java.lang.String" value="serverFrame" noResource="true"/> </Properties> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> </Container> - <Component class="javax.swing.JLabel" name="jLabel9"> + <Component class="javax.swing.JLabel" name="tunnelsExplanation"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel9.text"/> - <Property name="name" type="java.lang.String" value="jLabel9" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="tunnelsExplanation.text"/> + <Property name="name" type="java.lang.String" value="tunnelsExplanation" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JLabel" name="jLabel10"> + <Component class="javax.swing.JLabel" name="clientTunnelLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel10.text"/> - <Property name="name" type="java.lang.String" value="jLabel10" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="clientTunnelLabel.text"/> + <Property name="name" type="java.lang.String" value="clientTunnelLabel" noResource="true"/> </Properties> </Component> - <Component class="javax.swing.JLabel" name="jLabel11"> + <Component class="javax.swing.JLabel" name="serverTunnelLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel11.text"/> - <Property name="name" type="java.lang.String" value="jLabel11" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="serverTunnelLabel.text"/> + <Property name="name" type="java.lang.String" value="serverTunnelLabel" noResource="true"/> </Properties> </Component> </SubComponents> </Container> - <Container class="javax.swing.JPanel" name="jPanel5"> + <Container class="javax.swing.JPanel" name="networkPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jPanel5" noResource="true"/> + <Property name="name" type="java.lang.String" value="networkPanel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> <JTabbedPaneConstraints tabName="Network"> - <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel5.TabConstraints.tabTitle"/> + <Property name="tabTitle" type="java.lang.String" resourceKey="networkPanel.TabConstraints.tabTitle"/> </JTabbedPaneConstraints> </Constraint> </Constraints> @@ -486,14 +515,14 @@ </DimensionLayout> </Layout> </Container> - <Container class="javax.swing.JPanel" name="jPanel6"> + <Container class="javax.swing.JPanel" name="advancedPanel"> <Properties> - <Property name="name" type="java.lang.String" value="jPanel6" noResource="true"/> + <Property name="name" type="java.lang.String" value="advancedPanel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription"> <JTabbedPaneConstraints tabName="Advanced"> - <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel6.TabConstraints.tabTitle"/> + <Property name="tabTitle" type="java.lang.String" resourceKey="advancedPanel.TabConstraints.tabTitle"/> </JTabbedPaneConstraints> </Constraint> </Constraints> diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..910ca21fb5eeee8fec14984eaa501704f7c2f9e6 --- /dev/null +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java @@ -0,0 +1,461 @@ +/* + * GeneralConfiguration.java + * + * Created on 10 april 2009, 19:04 + */ + +package net.i2p.desktopgui.gui; + +import net.i2p.desktopgui.router.configuration.SpeedHelper; + +/** + * + * @author mathias + */ +public class GeneralConfiguration extends javax.swing.JFrame { + + /** Creates new form GeneralConfiguration */ + public GeneralConfiguration() { + initComponents(); + extraInitComponents(); + this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); + this.setVisible(true); + } + + private void extraInitComponents() { + downloadspeed.setText(SpeedHelper.getInboundBandwidth()); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + buttonGroup1 = new javax.swing.ButtonGroup(); + applyPanel = new javax.swing.JPanel(); + cancel = new javax.swing.JToggleButton(); + ok = new javax.swing.JToggleButton(); + settingsPanel = new javax.swing.JTabbedPane(); + speedPanel = new javax.swing.JPanel(); + uploadSpeedLabel = new javax.swing.JLabel(); + downloadSpeedLabel = new javax.swing.JLabel(); + uploadspeed = new javax.swing.JTextField(); + downloadspeed = new javax.swing.JTextField(); + uploadkbps = new javax.swing.JComboBox(); + downloadkbps = new javax.swing.JComboBox(); + jLabel3 = new javax.swing.JLabel(); + jLabel4 = new javax.swing.JLabel(); + uploadgb = new javax.swing.JTextField(); + downloadgb = new javax.swing.JTextField(); + jLabel5 = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jLabel7 = new javax.swing.JLabel(); + updatesPanel = new javax.swing.JPanel(); + updateMethod = new javax.swing.JLabel(); + updateInform = new javax.swing.JRadioButton(); + updateDownload = new javax.swing.JRadioButton(); + updateDownloadRestart = new javax.swing.JRadioButton(); + checkUpdates = new javax.swing.JToggleButton(); + updateNow = new javax.swing.JToggleButton(); + advancedUpdateConfig = new javax.swing.JToggleButton(); + tunnelPanel = new javax.swing.JPanel(); + clientFrame = new javax.swing.JScrollPane(); + serverFrame = new javax.swing.JScrollPane(); + tunnelsExplanation = new javax.swing.JLabel(); + clientTunnelLabel = new javax.swing.JLabel(); + serverTunnelLabel = new javax.swing.JLabel(); + networkPanel = new javax.swing.JPanel(); + advancedPanel = new javax.swing.JPanel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(GeneralConfiguration.class); + setTitle(resourceMap.getString("Form.title")); // NOI18N + setName("Form"); // NOI18N + + applyPanel.setName("applyPanel"); // NOI18N + + cancel.setText(resourceMap.getString("cancel.text")); // NOI18N + cancel.setName("cancel"); // NOI18N + + ok.setText(resourceMap.getString("ok.text")); // NOI18N + ok.setName("ok"); // NOI18N + + javax.swing.GroupLayout applyPanelLayout = new javax.swing.GroupLayout(applyPanel); + applyPanel.setLayout(applyPanelLayout); + applyPanelLayout.setHorizontalGroup( + applyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, applyPanelLayout.createSequentialGroup() + .addContainerGap(475, Short.MAX_VALUE) + .addComponent(ok) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancel) + .addContainerGap()) + ); + applyPanelLayout.setVerticalGroup( + applyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(applyPanelLayout.createSequentialGroup() + .addGroup(applyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cancel) + .addComponent(ok)) + .addContainerGap(14, Short.MAX_VALUE)) + ); + + settingsPanel.setName("settingsPanel"); // NOI18N + + speedPanel.setName("speedPanel"); // NOI18N + speedPanel.setLayout(null); + + uploadSpeedLabel.setText(resourceMap.getString("uploadSpeedLabel.text")); // NOI18N + uploadSpeedLabel.setName("uploadSpeedLabel"); // NOI18N + speedPanel.add(uploadSpeedLabel); + uploadSpeedLabel.setBounds(20, 20, 140, 30); + + downloadSpeedLabel.setText(resourceMap.getString("downloadSpeedLabel.text")); // NOI18N + downloadSpeedLabel.setName("downloadSpeedLabel"); // NOI18N + speedPanel.add(downloadSpeedLabel); + downloadSpeedLabel.setBounds(20, 60, 140, 30); + + uploadspeed.setText(resourceMap.getString("uploadspeed.text")); // NOI18N + uploadspeed.setName("uploadspeed"); // NOI18N + uploadspeed.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + speedKeyTyped(evt); + } + }); + speedPanel.add(uploadspeed); + uploadspeed.setBounds(160, 20, 77, 27); + + downloadspeed.setText(resourceMap.getString("downloadspeed.text")); // NOI18N + downloadspeed.setName("downloadspeed"); // NOI18N + downloadspeed.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + speedKeyTyped(evt); + } + }); + speedPanel.add(downloadspeed); + downloadspeed.setBounds(160, 60, 77, 27); + + uploadkbps.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "kbps", "kBps" })); + uploadkbps.setName("uploadkbps"); // NOI18N + uploadkbps.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + uploadkbpsActionPerformed(evt); + } + }); + speedPanel.add(uploadkbps); + uploadkbps.setBounds(240, 20, 68, 27); + + downloadkbps.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "kbps", "kBps" })); + downloadkbps.setName("downloadkbps"); // NOI18N + downloadkbps.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + downloadkbpsActionPerformed(evt); + } + }); + speedPanel.add(downloadkbps); + downloadkbps.setBounds(240, 60, 68, 27); + + jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N + jLabel3.setName("jLabel3"); // NOI18N + speedPanel.add(jLabel3); + jLabel3.setBounds(330, 20, 97, 30); + + jLabel4.setText(resourceMap.getString("jLabel4.text")); // NOI18N + jLabel4.setName("jLabel4"); // NOI18N + speedPanel.add(jLabel4); + jLabel4.setBounds(330, 60, 97, 30); + + uploadgb.setText(resourceMap.getString("uploadgb.text")); // NOI18N + uploadgb.setName("uploadgb"); // NOI18N + uploadgb.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + uploadgbKeyTyped(evt); + } + }); + speedPanel.add(uploadgb); + uploadgb.setBounds(440, 20, 60, 27); + + downloadgb.setText(resourceMap.getString("downloadgb.text")); // NOI18N + downloadgb.setName("downloadgb"); // NOI18N + downloadgb.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + downloadgbKeyTyped(evt); + } + }); + speedPanel.add(downloadgb); + downloadgb.setBounds(440, 60, 60, 27); + + jLabel5.setText(resourceMap.getString("jLabel5.text")); // NOI18N + jLabel5.setName("jLabel5"); // NOI18N + speedPanel.add(jLabel5); + jLabel5.setBounds(510, 20, 19, 30); + + jLabel6.setText(resourceMap.getString("jLabel6.text")); // NOI18N + jLabel6.setName("jLabel6"); // NOI18N + speedPanel.add(jLabel6); + jLabel6.setBounds(510, 60, 19, 30); + + jLabel7.setText(resourceMap.getString("jLabel7.text")); // NOI18N + jLabel7.setName("jLabel7"); // NOI18N + speedPanel.add(jLabel7); + jLabel7.setBounds(20, 100, 520, 70); + + settingsPanel.addTab(resourceMap.getString("speedPanel.TabConstraints.tabTitle"), speedPanel); // NOI18N + + updatesPanel.setName("updatesPanel"); // NOI18N + + updateMethod.setText(resourceMap.getString("updateMethod.text")); // NOI18N + updateMethod.setName("updateMethod"); // NOI18N + + buttonGroup1.add(updateInform); + updateInform.setText(resourceMap.getString("updateInform.text")); // NOI18N + updateInform.setName("updateInform"); // NOI18N + + buttonGroup1.add(updateDownload); + updateDownload.setText(resourceMap.getString("updateDownload.text")); // NOI18N + updateDownload.setName("updateDownload"); // NOI18N + + buttonGroup1.add(updateDownloadRestart); + updateDownloadRestart.setText(resourceMap.getString("updateDownloadRestart.text")); // NOI18N + updateDownloadRestart.setName("updateDownloadRestart"); // NOI18N + + checkUpdates.setText(resourceMap.getString("checkUpdates.text")); // NOI18N + checkUpdates.setName("checkUpdates"); // NOI18N + + updateNow.setText(resourceMap.getString("updateNow.text")); // NOI18N + updateNow.setName("updateNow"); // NOI18N + + advancedUpdateConfig.setText(resourceMap.getString("advancedUpdateConfig.text")); // NOI18N + advancedUpdateConfig.setName("advancedUpdateConfig"); // NOI18N + + javax.swing.GroupLayout updatesPanelLayout = new javax.swing.GroupLayout(updatesPanel); + updatesPanel.setLayout(updatesPanelLayout); + updatesPanelLayout.setHorizontalGroup( + updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(updatesPanelLayout.createSequentialGroup() + .addGroup(updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(updatesPanelLayout.createSequentialGroup() + .addGap(20, 20, 20) + .addGroup(updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(updateMethod) + .addGroup(updatesPanelLayout.createSequentialGroup() + .addComponent(checkUpdates) + .addGap(18, 18, 18) + .addComponent(updateNow)))) + .addGroup(updatesPanelLayout.createSequentialGroup() + .addGap(40, 40, 40) + .addGroup(updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(updateDownload) + .addComponent(updateInform) + .addComponent(updateDownloadRestart)))) + .addGap(9, 9, 9)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, updatesPanelLayout.createSequentialGroup() + .addContainerGap(339, Short.MAX_VALUE) + .addComponent(advancedUpdateConfig) + .addContainerGap()) + ); + updatesPanelLayout.setVerticalGroup( + updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(updatesPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(updateMethod) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(updateInform) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(updateDownload) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(updateDownloadRestart) + .addGap(18, 18, 18) + .addGroup(updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(checkUpdates) + .addComponent(updateNow)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 181, Short.MAX_VALUE) + .addComponent(advancedUpdateConfig) + .addContainerGap()) + ); + + settingsPanel.addTab(resourceMap.getString("updatesPanel.TabConstraints.tabTitle"), updatesPanel); // NOI18N + + tunnelPanel.setName("tunnelPanel"); // NOI18N + + clientFrame.setName("clientFrame"); // NOI18N + + serverFrame.setName("serverFrame"); // NOI18N + + tunnelsExplanation.setText(resourceMap.getString("tunnelsExplanation.text")); // NOI18N + tunnelsExplanation.setName("tunnelsExplanation"); // NOI18N + + clientTunnelLabel.setText(resourceMap.getString("clientTunnelLabel.text")); // NOI18N + clientTunnelLabel.setName("clientTunnelLabel"); // NOI18N + + serverTunnelLabel.setText(resourceMap.getString("serverTunnelLabel.text")); // NOI18N + serverTunnelLabel.setName("serverTunnelLabel"); // NOI18N + + javax.swing.GroupLayout tunnelPanelLayout = new javax.swing.GroupLayout(tunnelPanel); + tunnelPanel.setLayout(tunnelPanelLayout); + tunnelPanelLayout.setHorizontalGroup( + tunnelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tunnelPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(tunnelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(serverFrame, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE) + .addComponent(tunnelsExplanation, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE) + .addComponent(clientTunnelLabel) + .addComponent(clientFrame, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE) + .addComponent(serverTunnelLabel)) + .addContainerGap()) + ); + tunnelPanelLayout.setVerticalGroup( + tunnelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tunnelPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(clientTunnelLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(clientFrame, javax.swing.GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(serverTunnelLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(serverFrame, javax.swing.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tunnelsExplanation, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + settingsPanel.addTab(resourceMap.getString("tunnelPanel.TabConstraints.tabTitle"), tunnelPanel); // NOI18N + + networkPanel.setName("networkPanel"); // NOI18N + + javax.swing.GroupLayout networkPanelLayout = new javax.swing.GroupLayout(networkPanel); + networkPanel.setLayout(networkPanelLayout); + networkPanelLayout.setHorizontalGroup( + networkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 562, Short.MAX_VALUE) + ); + networkPanelLayout.setVerticalGroup( + networkPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 388, Short.MAX_VALUE) + ); + + settingsPanel.addTab(resourceMap.getString("networkPanel.TabConstraints.tabTitle"), networkPanel); // NOI18N + + advancedPanel.setName("advancedPanel"); // NOI18N + + javax.swing.GroupLayout advancedPanelLayout = new javax.swing.GroupLayout(advancedPanel); + advancedPanel.setLayout(advancedPanelLayout); + advancedPanelLayout.setHorizontalGroup( + advancedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 562, Short.MAX_VALUE) + ); + advancedPanelLayout.setVerticalGroup( + advancedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 388, Short.MAX_VALUE) + ); + + settingsPanel.addTab(resourceMap.getString("advancedPanel.TabConstraints.tabTitle"), advancedPanel); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(applyPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGap(12, 12, 12) + .addComponent(settingsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 566, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(settingsPanel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(applyPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + pack(); + }// </editor-fold>//GEN-END:initComponents + +private void speedKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_speedKeyTyped + try { + String upload = ""; + if(uploadkbps.getSelectedIndex() == KILOBIT) + upload = "" + Integer.parseInt(uploadspeed.getText())/8; + else + upload = uploadspeed.getText(); + String download = ""; + if(downloadkbps.getSelectedIndex() == KILOBIT) + download = "" + Integer.parseInt(downloadspeed.getText())/8; + else + download = downloadspeed.getText(); + initUsage(upload, download); + } + catch(NumberFormatException e) { + e.printStackTrace(); + return; + } +}//GEN-LAST:event_speedKeyTyped + +private void uploadkbpsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uploadkbpsActionPerformed + // TODO add your handling code here: +}//GEN-LAST:event_uploadkbpsActionPerformed + +private void downloadkbpsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadkbpsActionPerformed + // TODO add your handling code here: +}//GEN-LAST:event_downloadkbpsActionPerformed + +private void uploadgbKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_uploadgbKeyTyped + // TODO add your handling code here: +}//GEN-LAST:event_uploadgbKeyTyped + +private void downloadgbKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_downloadgbKeyTyped + // TODO add your handling code here: +}//GEN-LAST:event_downloadgbKeyTyped + + protected void initUsage(String upload, String download) { + uploadgb.setText("" + SpeedHelper.calculateMonthlyUsage(Integer.parseInt(upload))); + downloadgb.setText("" + SpeedHelper.calculateMonthlyUsage(Integer.parseInt(download))); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel advancedPanel; + private javax.swing.JToggleButton advancedUpdateConfig; + private javax.swing.JPanel applyPanel; + private javax.swing.ButtonGroup buttonGroup1; + private javax.swing.JToggleButton cancel; + private javax.swing.JToggleButton checkUpdates; + private javax.swing.JScrollPane clientFrame; + private javax.swing.JLabel clientTunnelLabel; + private javax.swing.JLabel downloadSpeedLabel; + private javax.swing.JTextField downloadgb; + private javax.swing.JComboBox downloadkbps; + private javax.swing.JTextField downloadspeed; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JPanel networkPanel; + private javax.swing.JToggleButton ok; + private javax.swing.JScrollPane serverFrame; + private javax.swing.JLabel serverTunnelLabel; + private javax.swing.JTabbedPane settingsPanel; + private javax.swing.JPanel speedPanel; + private javax.swing.JPanel tunnelPanel; + private javax.swing.JLabel tunnelsExplanation; + private javax.swing.JRadioButton updateDownload; + private javax.swing.JRadioButton updateDownloadRestart; + private javax.swing.JRadioButton updateInform; + private javax.swing.JLabel updateMethod; + private javax.swing.JToggleButton updateNow; + private javax.swing.JPanel updatesPanel; + private javax.swing.JLabel uploadSpeedLabel; + private javax.swing.JTextField uploadgb; + private javax.swing.JComboBox uploadkbps; + private javax.swing.JTextField uploadspeed; + // End of variables declaration//GEN-END:variables + + public static final int KILOBIT = 0; + public static final int KILOBYTE = 1; +} diff --git a/apps/desktopgui/src/gui/JPopupTrayIcon.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/JPopupTrayIcon.java similarity index 83% rename from apps/desktopgui/src/gui/JPopupTrayIcon.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/JPopupTrayIcon.java index 83872e4a51958c1b9b5ca094800ec731392574a3..1f62df2c27099c0863608ec181204dbe1d3473d2 100644 --- a/apps/desktopgui/src/gui/JPopupTrayIcon.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/JPopupTrayIcon.java @@ -24,7 +24,7 @@ * */ -package gui; +package net.i2p.desktopgui.gui; import java.awt.Dimension; import java.awt.Frame; @@ -37,13 +37,12 @@ import java.awt.Window; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JWindow; import javax.swing.RootPaneContainer; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; +import java.util.Date; @@ -63,6 +62,10 @@ public class JPopupTrayIcon extends TrayIcon { private final static boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows"); + private static MouseEvent previous = null; + private static Date previousTime = new Date(); + private static Date time = new Date(); + public JPopupTrayIcon(Image image) { super(image); init(); @@ -92,12 +95,12 @@ public class JPopupTrayIcon extends TrayIcon { @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { -// System.out.println("popupMenuWillBecomeVisible"); + //System.out.println("popupMenuWillBecomeVisible"); } @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { -// System.out.println("popupMenuWillBecomeInvisible"); + //System.out.println("popupMenuWillBecomeInvisible"); if(window != null) { window.dispose(); window = null; @@ -117,21 +120,27 @@ public class JPopupTrayIcon extends TrayIcon { addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { -// System.out.println(e.getPoint()); - showJPopupMenu(e); + //System.out.println("Pressed " + e.getPoint()); + showJPopupMenu(e, previous); + previous = e; + previousTime = time; + time = new Date(); } @Override public void mouseReleased(MouseEvent e) { -// System.out.println(e.getPoint()); - showJPopupMenu(e); + //System.out.println("Released " + e.getPoint()); + showJPopupMenu(e, previous); + previous = e; + previousTime = time; + time = new Date(); } }); } - private final void showJPopupMenu(MouseEvent e) { - if(e.isPopupTrigger() && menu != null) { + private final void showJPopupMenu(MouseEvent e, MouseEvent previous) { + if((e.isPopupTrigger() || previous.isPopupTrigger()) && (time.getTime() - previousTime.getTime() < 1000) && menu != null) { if (window == null) { if(IS_WINDOWS) { diff --git a/apps/desktopgui/src/gui/LogViewer.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/LogViewer.form similarity index 96% rename from apps/desktopgui/src/gui/LogViewer.form rename to apps/desktopgui/src/net/i2p/desktopgui/gui/LogViewer.form index b53b410bac2305d27ef38ff74014877dace14fdc..ed2441319e9e731b289d75c220c71dbf87c906db 100644 --- a/apps/desktopgui/src/gui/LogViewer.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/LogViewer.form @@ -3,6 +3,7 @@ <Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> <Properties> <Property name="defaultCloseOperation" type="int" value="3"/> + <Property name="title" type="java.lang.String" resourceKey="Form.title"/> <Property name="name" type="java.lang.String" value="Form" noResource="true"/> </Properties> <SyntheticProperties> @@ -11,6 +12,7 @@ <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> diff --git a/apps/desktopgui/src/gui/LogViewer.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/LogViewer.java similarity index 96% rename from apps/desktopgui/src/gui/LogViewer.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/LogViewer.java index 2dad70c1fc242ecabc02401c3ac10c83908dbddf..1edf85b3bf0d169647fceacd52a33e671f90d025 100644 --- a/apps/desktopgui/src/gui/LogViewer.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/LogViewer.java @@ -4,7 +4,7 @@ * Created on 10 april 2009, 19:17 */ -package gui; +package net.i2p.desktopgui.gui; import java.io.BufferedReader; import java.io.File; @@ -73,6 +73,8 @@ public class LogViewer extends javax.swing.JFrame { clearButton = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(LogViewer.class); + setTitle(resourceMap.getString("Form.title")); // NOI18N setName("Form"); // NOI18N textScroll.setName("textScroll"); // NOI18N @@ -82,7 +84,6 @@ public class LogViewer extends javax.swing.JFrame { logText.setName("logText"); // NOI18N textScroll.setViewportView(logText); - org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(LogViewer.class); explanationText.setText(resourceMap.getString("explanationText.text")); // NOI18N explanationText.setName("explanationText"); // NOI18N diff --git a/apps/desktopgui/src/gui/SpeedSelector.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector.form similarity index 99% rename from apps/desktopgui/src/gui/SpeedSelector.form rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector.form index 79d25ae9650187e565486e5823d843a5a52a4727..5ee7b94ac85c39d02589ebb8741493ec98026232 100644 --- a/apps/desktopgui/src/gui/SpeedSelector.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector.form @@ -16,6 +16,7 @@ <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> diff --git a/apps/desktopgui/src/gui/SpeedSelector.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector.java similarity index 96% rename from apps/desktopgui/src/gui/SpeedSelector.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector.java index bce18621f2919beeb77c9d8e9702ca903a63e980..335812e2a99a1ce4dcdd5dd7f58eb3d1e3d25b02 100644 --- a/apps/desktopgui/src/gui/SpeedSelector.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector.java @@ -4,15 +4,14 @@ * Created on 3 april 2009, 13:57 */ -package gui; +package net.i2p.desktopgui.gui; -import java.awt.Dimension; import java.awt.Point; import java.util.Properties; import javax.swing.JComboBox; import javax.swing.JTextField; -import persistence.PropertyManager; -import util.IntegerVerifier; +import net.i2p.desktopgui.persistence.PropertyManager; +import net.i2p.desktopgui.util.IntegerVerifier; /** * @@ -60,7 +59,7 @@ public class SpeedSelector extends javax.swing.JFrame { downloadkbps = new javax.swing.JComboBox(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(SpeedSelector.class); + org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(SpeedSelector.class); setTitle(resourceMap.getString("Form.title")); // NOI18N setMinimumSize(new java.awt.Dimension(610, 330)); setName("Form"); // NOI18N diff --git a/apps/desktopgui/src/gui/SpeedSelector2.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector2.form similarity index 98% rename from apps/desktopgui/src/gui/SpeedSelector2.form rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector2.form index 5c305de19b450dfc4a0d812173e600d01612449d..54f5fa7262dc3a23f793f4180dc0d1acb83f6cb4 100644 --- a/apps/desktopgui/src/gui/SpeedSelector2.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector2.form @@ -20,6 +20,7 @@ <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> diff --git a/apps/desktopgui/src/gui/SpeedSelector2.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector2.java similarity index 96% rename from apps/desktopgui/src/gui/SpeedSelector2.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector2.java index 1177b5725817f5aead7062dc8dae196af3fc67e7..772d16918a58a6edf6d65601f708dc8768c35c01 100644 --- a/apps/desktopgui/src/gui/SpeedSelector2.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector2.java @@ -4,14 +4,13 @@ * Created on 3 april 2009, 14:36 */ -package gui; +package net.i2p.desktopgui.gui; -import java.awt.Dimension; import java.awt.Point; import java.util.Enumeration; import java.util.Properties; import javax.swing.AbstractButton; -import persistence.PropertyManager; +import net.i2p.desktopgui.persistence.PropertyManager; /** * @@ -48,7 +47,7 @@ public class SpeedSelector2 extends javax.swing.JFrame { jLabel1 = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(SpeedSelector2.class); + org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(SpeedSelector2.class); setTitle(resourceMap.getString("Form.title")); // NOI18N setMinimumSize(new java.awt.Dimension(610, 330)); setName("Form"); // NOI18N diff --git a/apps/desktopgui/src/gui/SpeedSelector3.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector3.form similarity index 99% rename from apps/desktopgui/src/gui/SpeedSelector3.form rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector3.form index b295c45938c70d6d1a1a54dba4a00d3e55e3f747..8e4aa5b4e8d19b460b4eb3a21575ac3a309fa496 100644 --- a/apps/desktopgui/src/gui/SpeedSelector3.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector3.form @@ -16,6 +16,7 @@ <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> @@ -318,7 +319,7 @@ </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> - <AbsoluteConstraints x="580" y="150" width="-1" height="30"/> + <AbsoluteConstraints x="580" y="150" width="40" height="30"/> </Constraint> </Constraints> </Component> diff --git a/apps/desktopgui/src/gui/SpeedSelector3.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector3.java similarity index 98% rename from apps/desktopgui/src/gui/SpeedSelector3.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector3.java index 8c6407f629d55dea655d5e63961420f40b39ab8c..933ad3ff2f9489714d1db00c73be96c466d86580 100644 --- a/apps/desktopgui/src/gui/SpeedSelector3.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelector3.java @@ -4,16 +4,16 @@ * Created on 3 april 2009, 15:17 */ -package gui; +package net.i2p.desktopgui.gui; import java.awt.Dimension; import java.awt.Point; import java.util.Properties; import javax.swing.JComboBox; import javax.swing.JTextField; -import persistence.PropertyManager; -import router.configuration.SpeedHandler; -import router.configuration.SpeedHelper; +import net.i2p.desktopgui.persistence.PropertyManager; +import net.i2p.desktopgui.router.configuration.SpeedHandler; +import net.i2p.desktopgui.router.configuration.SpeedHelper; /** * @@ -67,7 +67,7 @@ public class SpeedSelector3 extends javax.swing.JFrame { explanation = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(SpeedSelector3.class); + org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(SpeedSelector3.class); setTitle(resourceMap.getString("Form.title")); // NOI18N setMinimumSize(new java.awt.Dimension(670, 330)); setName("Form"); // NOI18N @@ -231,7 +231,7 @@ public class SpeedSelector3 extends javax.swing.JFrame { downloadGB.setText(resourceMap.getString("downloadUsageLabel.text")); // NOI18N downloadGB.setName("downloadUsageLabel"); // NOI18N getContentPane().add(downloadGB); - downloadGB.setBounds(580, 150, 19, 30); + downloadGB.setBounds(580, 150, 40, 30); explanation.setText(resourceMap.getString("explanation.text")); // NOI18N explanation.setName("explanation"); // NOI18N diff --git a/apps/desktopgui/src/gui/SpeedSelectorConstants.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelectorConstants.java similarity index 96% rename from apps/desktopgui/src/gui/SpeedSelectorConstants.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelectorConstants.java index ea5e32427b56eb9d86e5cc263787de07fe1648bc..1088f6957f27bdba770c02a26ecb3f0fee19c1a1 100644 --- a/apps/desktopgui/src/gui/SpeedSelectorConstants.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/SpeedSelectorConstants.java @@ -1,4 +1,4 @@ -package gui; +package net.i2p.desktopgui.gui; /** * diff --git a/apps/desktopgui/src/gui/Tray.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java similarity index 97% rename from apps/desktopgui/src/gui/Tray.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java index 7c95cd6eb3ef740bf518141d130b6d7d5079129a..b20a850f6d744075da74d2e9cd51ae82deb37799 100644 --- a/apps/desktopgui/src/gui/Tray.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java @@ -3,9 +3,9 @@ * and open the template in the editor. */ -package gui; +package net.i2p.desktopgui.gui; -import desktopgui.*; +import net.i2p.desktopgui.desktopgui.*; import java.awt.AWTException; import java.awt.Desktop; import java.awt.Image; @@ -23,9 +23,9 @@ import java.util.logging.Logger; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; -import router.RouterHandler; -import router.RouterHelper; -import router.configuration.PeerHelper; +import net.i2p.desktopgui.router.RouterHandler; +import net.i2p.desktopgui.router.RouterHelper; +import net.i2p.desktopgui.router.configuration.PeerHelper; /** * diff --git a/apps/desktopgui/src/gui/Version.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/Version.form similarity index 79% rename from apps/desktopgui/src/gui/Version.form rename to apps/desktopgui/src/net/i2p/desktopgui/gui/Version.form index 20df8621a0c244ba59e834ca5543fcf3731bf219..32ab90b311d119e3fa4034aa8480e47ccbc3cdec 100644 --- a/apps/desktopgui/src/gui/Version.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/Version.form @@ -3,6 +3,7 @@ <Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JDialogFormInfo"> <Properties> <Property name="defaultCloseOperation" type="int" value="2"/> + <Property name="title" type="java.lang.String" resourceKey="Form.title"/> <Property name="name" type="java.lang.String" value="Form" noResource="true"/> </Properties> <SyntheticProperties> @@ -11,6 +12,7 @@ <AuxValues> <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> @@ -22,24 +24,24 @@ <Layout> <DimensionLayout dim="0"> <Group type="103" groupAlignment="0" attributes="0"> - <Group type="102" alignment="0" attributes="0"> + <Group type="102" attributes="0"> <EmptySpace max="-2" attributes="0"/> - <Group type="103" groupAlignment="1" max="-2" attributes="0"> - <Component id="I2Plabel" alignment="0" max="32767" attributes="0"/> - <Component id="GUILabel" alignment="0" max="32767" attributes="1"/> - </Group> - <EmptySpace type="separate" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> - <Component id="I2PVersion" pref="126" max="32767" attributes="0"/> - <Component id="GUIVersion" pref="126" max="32767" attributes="0"/> + <Group type="102" alignment="0" attributes="0"> + <Group type="103" groupAlignment="1" max="-2" attributes="0"> + <Component id="I2Plabel" alignment="0" max="32767" attributes="0"/> + <Component id="GUILabel" alignment="0" max="32767" attributes="1"/> + </Group> + <EmptySpace type="separate" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="I2PVersion" pref="126" max="32767" attributes="0"/> + <Component id="GUIVersion" pref="126" max="32767" attributes="0"/> + </Group> + </Group> + <Component id="okButton" alignment="1" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> </Group> - <Group type="102" alignment="1" attributes="0"> - <EmptySpace pref="294" max="32767" attributes="0"/> - <Component id="okButton" min="-2" max="-2" attributes="0"/> - <EmptySpace max="-2" attributes="0"/> - </Group> </Group> </DimensionLayout> <DimensionLayout dim="1"> diff --git a/apps/desktopgui/src/gui/Version.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/Version.java similarity index 75% rename from apps/desktopgui/src/gui/Version.java rename to apps/desktopgui/src/net/i2p/desktopgui/gui/Version.java index 3e5a478c59a15f5c5ef6576e5f5261830f2a05f1..25a38d6b8ffa7785db79aee870680e9ed9fcd818 100644 --- a/apps/desktopgui/src/gui/Version.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/Version.java @@ -4,10 +4,10 @@ * Created on 13 april 2009, 13:48 */ -package gui; +package net.i2p.desktopgui.gui; import javax.swing.JFrame; -import router.RouterHelper; +import net.i2p.desktopgui.router.RouterHelper; /** * @@ -24,7 +24,7 @@ public class Version extends javax.swing.JDialog { super(parent, modal); initComponents(); String i2pVersion = RouterHelper.getVersion(); - String guiVersion = desktopgui.GUIVersion.VERSION; + String guiVersion = net.i2p.desktopgui.desktopgui.GUIVersion.VERSION; this.I2PVersion.setText("<html><h1>" + i2pVersion + "</h1></html>"); this.GUIVersion.setText("<html><h1>" + guiVersion + "</h1></html>"); this.setVisible(true); @@ -46,9 +46,10 @@ public class Version extends javax.swing.JDialog { GUIVersion = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(Version.class); + setTitle(resourceMap.getString("Form.title")); // NOI18N setName("Form"); // NOI18N - org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(Version.class); okButton.setText(resourceMap.getString("okButton.text")); // NOI18N okButton.setName("okButton"); // NOI18N okButton.addActionListener(new java.awt.event.ActionListener() { @@ -75,17 +76,16 @@ public class Version extends javax.swing.JDialog { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(I2Plabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(GUILabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(I2PVersion, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE) - .addComponent(GUIVersion, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE)) - .addContainerGap()) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap(294, Short.MAX_VALUE) - .addComponent(okButton) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(I2Plabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(GUILabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(I2PVersion, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE) + .addComponent(GUIVersion, javax.swing.GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE))) + .addComponent(okButton, javax.swing.GroupLayout.Alignment.TRAILING)) .addContainerGap()) ); layout.setVerticalGroup( diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties new file mode 100644 index 0000000000000000000000000000000000000000..e1c16a08cb12f393dacb7b3190ecbe899c11a529 --- /dev/null +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties @@ -0,0 +1,29 @@ +cancel.text=Cancel +ok.text=OK +jLabel3.text=Monthly usage: +jLabel4.text=Monthly usage: +jLabel5.text=GB +jLabel6.text=GB +jLabel7.text=Explanation ... +Form.title=General Configuration +speedPanel.TabConstraints.tabTitle=Speed +updatesPanel.TabConstraints.tabTitle=Updates +tunnelPanel.TabConstraints.tabTitle=Tunnels/Services +networkPanel.TabConstraints.tabTitle=Network +advancedPanel.TabConstraints.tabTitle=Advanced +uploadSpeedLabel.text=Upload speed: +downloadSpeedLabel.text=Download speed: +uploadspeed.text=jTextField1 +downloadspeed.text=jTextField2 +uploadgb.text=jTextField3 +downloadgb.text=jTextField4 +updateMethod.text=What is your preferred automatic update setting? +updateInform.text=Only inform about updates +updateDownload.text=Download and verify update file, do not restart +updateDownloadRestart.text=Download, verify and restart +checkUpdates.text=Check for updates now +updateNow.text=Update available: update now +advancedUpdateConfig.text=Advanced update configuration +clientTunnelLabel.text=Client tunnels: +serverTunnelLabel.text=Server tunnels: +tunnelsExplanation.text=Tunnel explanation diff --git a/apps/desktopgui/src/gui/resources/LogViewer.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/LogViewer.properties similarity index 80% rename from apps/desktopgui/src/gui/resources/LogViewer.properties rename to apps/desktopgui/src/net/i2p/desktopgui/gui/resources/LogViewer.properties index 8cb0e620913951f63269300844bf5f732f5f550f..d4ef5bf0e0c6c495848c2cd8f8988133c684121e 100644 --- a/apps/desktopgui/src/gui/resources/LogViewer.properties +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/LogViewer.properties @@ -1,3 +1,4 @@ refreshButton.text=Refresh clearButton.text=Clear explanationText.text=Explanation ... +Form.title=View Logs diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector.properties similarity index 100% rename from apps/desktopgui/src/gui/resources/SpeedSelector.properties rename to apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector.properties diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector2.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector2.properties similarity index 100% rename from apps/desktopgui/src/gui/resources/SpeedSelector2.properties rename to apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector2.properties diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector3.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector3.properties similarity index 92% rename from apps/desktopgui/src/gui/resources/SpeedSelector3.properties rename to apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector3.properties index 5b338348cf2e778a6a37fc3109aac5a169747a9e..6dca3ca51603dd9a6667aea2588bda0812aecd5f 100644 --- a/apps/desktopgui/src/gui/resources/SpeedSelector3.properties +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/SpeedSelector3.properties @@ -5,8 +5,8 @@ uploadLabel.text=Upload Speed: uploadBurstLabel.text=Burst Upload Speed: downloadLabel.text=Download Speed: downloadBurstLabel.text=Burst Download Speed: -uploadUsageLabel.text=Monthly usage: -downloadUsageLabel.text=Monthly usage: +uploadUsageLabel.text=GB +downloadUsageLabel.text=GB uploadField.text=jTextField1 uploadBurstField.text=jTextField2 downloadField.text=jTextField4 diff --git a/apps/desktopgui/src/gui/resources/Version.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/Version.properties similarity index 89% rename from apps/desktopgui/src/gui/resources/Version.properties rename to apps/desktopgui/src/net/i2p/desktopgui/gui/resources/Version.properties index 91ee786ad12716094d21e405f0619bf11676ea82..c2030bb2d838b6859ded31c3fee5ef30beeba8f0 100644 --- a/apps/desktopgui/src/gui/resources/Version.properties +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/Version.properties @@ -3,3 +3,4 @@ I2Plabel.text=<html><h1>I2P Version:</h1></html> GUILabel.text=<html><h1>GUI Version:</h1></html> I2PVersion.text=jLabel3 GUIVersion.text=jLabel4 +Form.title=Version diff --git a/apps/desktopgui/src/persistence/PropertyManager.java b/apps/desktopgui/src/net/i2p/desktopgui/persistence/PropertyManager.java similarity index 98% rename from apps/desktopgui/src/persistence/PropertyManager.java rename to apps/desktopgui/src/net/i2p/desktopgui/persistence/PropertyManager.java index bacbf348ac4b0d645ab2d7913f9c0b32dd7df989..770bd09570f16b90522e0042c183f792ccd58737 100644 --- a/apps/desktopgui/src/persistence/PropertyManager.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/persistence/PropertyManager.java @@ -1,4 +1,4 @@ -package persistence; +package net.i2p.desktopgui.persistence; import java.io.File; import java.io.FileInputStream; diff --git a/apps/desktopgui/src/router/RouterHandler.java b/apps/desktopgui/src/net/i2p/desktopgui/router/RouterHandler.java similarity index 97% rename from apps/desktopgui/src/router/RouterHandler.java rename to apps/desktopgui/src/net/i2p/desktopgui/router/RouterHandler.java index 0752f877b516cc618a72b71ab14e49be3c619157..022c5c8149659087f48433ee05b7ced2a9dfa7ef 100644 --- a/apps/desktopgui/src/router/RouterHandler.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/RouterHandler.java @@ -3,7 +3,7 @@ * and open the template in the editor. */ -package router; +package net.i2p.desktopgui.router; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/apps/desktopgui/src/router/RouterHelper.java b/apps/desktopgui/src/net/i2p/desktopgui/router/RouterHelper.java similarity index 93% rename from apps/desktopgui/src/router/RouterHelper.java rename to apps/desktopgui/src/net/i2p/desktopgui/router/RouterHelper.java index 49a7c8b29a2fe8632ba1dd4d935db9332f8497be..2da95f0c6a86d41f4e975532d689fc438922fa0a 100644 --- a/apps/desktopgui/src/router/RouterHelper.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/RouterHelper.java @@ -1,4 +1,4 @@ -package router; +package net.i2p.desktopgui.router; import net.i2p.router.RouterContext; import net.i2p.router.RouterVersion; diff --git a/apps/desktopgui/src/router/configuration/PeerHelper.java b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/PeerHelper.java similarity index 98% rename from apps/desktopgui/src/router/configuration/PeerHelper.java rename to apps/desktopgui/src/net/i2p/desktopgui/router/configuration/PeerHelper.java index 76ffeef8777077fcf1b131d8943da125d29521f6..74df2b3d99ec0186ebda188743feb25bdbafa195 100644 --- a/apps/desktopgui/src/router/configuration/PeerHelper.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/PeerHelper.java @@ -1,4 +1,4 @@ -package router.configuration; +package net.i2p.desktopgui.router.configuration; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -11,7 +11,7 @@ import net.i2p.router.CommSystemFacade; import net.i2p.router.RouterContext; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.transport.ntcp.NTCPAddress; -import router.RouterHelper; +import net.i2p.desktopgui.router.RouterHelper; /** * Part of the code imported and adapted from the I2P Router Console (which is licensed as public domain) diff --git a/apps/desktopgui/src/router/configuration/SpeedHandler.java b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHandler.java similarity index 91% rename from apps/desktopgui/src/router/configuration/SpeedHandler.java rename to apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHandler.java index 235790792ac539e7e6120efa2220026b1b34548a..8fd67565787d35322c96c2eb82207ff0e1769118 100644 --- a/apps/desktopgui/src/router/configuration/SpeedHandler.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHandler.java @@ -1,8 +1,8 @@ -package router.configuration; +package net.i2p.desktopgui.router.configuration; import net.i2p.router.RouterContext; import net.i2p.router.transport.FIFOBandwidthRefiller; -import router.RouterHelper; +import net.i2p.desktopgui.router.RouterHelper; /** * diff --git a/apps/desktopgui/src/router/configuration/SpeedHelper.java b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java similarity index 77% rename from apps/desktopgui/src/router/configuration/SpeedHelper.java rename to apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java index acad2adb146d65403c3c497b9b7364c139f3dc09..5d2074de2c76b3ce893caee53947a32646787d84 100644 --- a/apps/desktopgui/src/router/configuration/SpeedHelper.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java @@ -1,4 +1,7 @@ -package router.configuration; +package net.i2p.desktopgui.router.configuration; + +import net.i2p.router.transport.FIFOBandwidthRefiller; +import net.i2p.desktopgui.router.RouterHelper; /** * @@ -29,4 +32,8 @@ public class SpeedHelper { public static int calculateSpeed(int gigabytes) { return (int) (((long)gigabytes)*1000000/31/24/3600); } + + public static String getInboundBandwidth() { + return RouterHelper.getContext().router().getConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH); + } } diff --git a/apps/desktopgui/src/util/IntegerVerifier.java b/apps/desktopgui/src/net/i2p/desktopgui/util/IntegerVerifier.java similarity index 95% rename from apps/desktopgui/src/util/IntegerVerifier.java rename to apps/desktopgui/src/net/i2p/desktopgui/util/IntegerVerifier.java index 74f87961daa02897cff605f36aadcba95314f9a0..7cc0fb46ae5ccd8b676a5f33137909e3d5c36dd9 100644 --- a/apps/desktopgui/src/util/IntegerVerifier.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/util/IntegerVerifier.java @@ -1,4 +1,4 @@ -package util; +package net.i2p.desktopgui.util; import javax.swing.InputVerifier; import javax.swing.JComponent; diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index 515594219e378dcd246b52d4415c76b254d5e5ba..3923484a80901882de9735eff80905314df77516 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -587,6 +587,8 @@ public class I2PSnarkServlet extends HttpServlet { client = "I2PSnarkXL"; else if ("ZV".equals(ch.substring(2,4))) client = "Robert"; + else if ("VUZP".equals(ch)) + client = "Robert"; else client = "Unknown (" + ch + ')'; out.write("<font size=-1>" + client + "</font> <tt>" + peer.toString().substring(5, 9) + "</tt>"); diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java index 015f5c9c5811571cb320cc981dcef5b1727de7ab..8e76273098154ca34df4fd706588654cc23c5847 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java @@ -92,7 +92,7 @@ public class I2PTunnel implements Logging, EventDispatcher { private final List tasks = new ArrayList(); private int next_task_id = 1; - private Set listeners = new HashSet(); + private final Set listeners = new HashSet(); public static void main(String[] args) throws IOException { new I2PTunnel(args); @@ -668,9 +668,9 @@ public class I2PTunnel implements Logging, EventDispatcher { */ public void runConnectClient(String args[], Logging l) { if (args.length >= 1 && args.length <= 3) { - int port = -1; + int _port = -1; try { - port = Integer.parseInt(args[0]); + _port = Integer.parseInt(args[0]); } catch (NumberFormatException nfe) { _log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe); return; @@ -702,10 +702,10 @@ public class I2PTunnel implements Logging, EventDispatcher { I2PTunnelTask task; ownDest = !isShared; try { - task = new I2PTunnelConnectClient(port, l, ownDest, proxy, (EventDispatcher) this, this); + task = new I2PTunnelConnectClient(_port, l, ownDest, proxy, (EventDispatcher) this, this); addtask(task); } catch (IllegalArgumentException iae) { - _log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ port + "]", iae); + _log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ _port + "]", iae); } } else { l.log("connectclient <port> [<sharedClient>] [<proxy>]"); @@ -728,9 +728,9 @@ public class I2PTunnel implements Logging, EventDispatcher { */ public void runIrcClient(String args[], Logging l) { if (args.length >= 2) { - int port = -1; + int _port = -1; try { - port = Integer.parseInt(args[0]); + _port = Integer.parseInt(args[0]); } catch (NumberFormatException nfe) { l.log("invalid port"); _log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe); @@ -757,12 +757,12 @@ public class I2PTunnel implements Logging, EventDispatcher { String privateKeyFile = null; if (args.length >= 4) privateKeyFile = args[3]; - task = new I2PTunnelIRCClient(port, args[1], l, ownDest, (EventDispatcher) this, this, privateKeyFile); + task = new I2PTunnelIRCClient(_port, args[1], l, ownDest, (EventDispatcher) this, this, privateKeyFile); addtask(task); notifyEvent("ircclientTaskId", Integer.valueOf(task.getId())); } catch (IllegalArgumentException iae) { - _log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ port + "]", iae); - l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]"); + _log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ _port + "]", iae); + l.log("Invalid I2PTunnel configuration [" + host + ":" + _port + "]"); notifyEvent("ircclientTaskId", Integer.valueOf(-1)); } } else { @@ -786,9 +786,9 @@ public class I2PTunnel implements Logging, EventDispatcher { */ public void runSOCKSTunnel(String args[], Logging l) { if (args.length >= 1 && args.length <= 2) { - int port = -1; + int _port = -1; try { - port = Integer.parseInt(args[0]); + _port = Integer.parseInt(args[0]); } catch (NumberFormatException nfe) { l.log("invalid port"); _log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe); @@ -802,7 +802,7 @@ public class I2PTunnel implements Logging, EventDispatcher { ownDest = !isShared; I2PTunnelTask task; - task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this); + task = new I2PSOCKSTunnel(_port, l, ownDest, (EventDispatcher) this, this); addtask(task); notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId())); } else { @@ -820,9 +820,9 @@ public class I2PTunnel implements Logging, EventDispatcher { */ public void runStreamrClient(String args[], Logging l) { if (args.length == 3) { - InetAddress host; + InetAddress _host; try { - host = InetAddress.getByName(args[0]); + _host = InetAddress.getByName(args[0]); } catch (UnknownHostException uhe) { l.log("unknown host"); _log.error(getPrefix() + "Error resolving " + args[0], uhe); @@ -830,9 +830,9 @@ public class I2PTunnel implements Logging, EventDispatcher { return; } - int port = -1; + int _port = -1; try { - port = Integer.parseInt(args[1]); + _port = Integer.parseInt(args[1]); } catch (NumberFormatException nfe) { l.log("invalid port"); _log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe); @@ -840,7 +840,7 @@ public class I2PTunnel implements Logging, EventDispatcher { return; } - StreamrConsumer task = new StreamrConsumer(host, port, args[2], l, (EventDispatcher) this, this); + StreamrConsumer task = new StreamrConsumer(_host, _port, args[2], l, (EventDispatcher) this, this); task.startRunning(); addtask(task); notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId())); @@ -859,9 +859,9 @@ public class I2PTunnel implements Logging, EventDispatcher { */ public void runStreamrServer(String args[], Logging l) { if (args.length == 2) { - int port = -1; + int _port = -1; try { - port = Integer.parseInt(args[0]); + _port = Integer.parseInt(args[0]); } catch (NumberFormatException nfe) { l.log("invalid port"); _log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe); @@ -877,7 +877,7 @@ public class I2PTunnel implements Logging, EventDispatcher { return; } - StreamrProducer task = new StreamrProducer(port, privKeyFile, args[1], l, (EventDispatcher) this, this); + StreamrProducer task = new StreamrProducer(_port, privKeyFile, args[1], l, (EventDispatcher) this, this); task.startRunning(); addtask(task); notifyEvent("streamrtunnelTaskId", Integer.valueOf(task.getId())); diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java index 93db8595b7024d2fbbccdffa58dfb83de52ee1d9..662fd9e5721eb40de7446f84a59006ab473711af 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PServerSocketImpl.java @@ -20,7 +20,7 @@ class I2PServerSocketImpl implements I2PServerSocket { private final static Log _log = new Log(I2PServerSocketImpl.class); private I2PSocketManager mgr; /** list of sockets waiting for the client to accept them */ - private List pendingSockets = Collections.synchronizedList(new ArrayList(4)); + private List<I2PSocket> pendingSockets = Collections.synchronizedList(new ArrayList<I2PSocket>(4)); /** have we been closed */ private volatile boolean closing = false; diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java index 406f718474e934677b583b869873e9a5b16365f6..b40b9091f79e79caa8dae5faa44b713742b63b91 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java @@ -43,12 +43,12 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener { private I2PSession _session; private I2PServerSocketImpl _serverSocket = null; private Object lock = new Object(); // for locking socket lists - private HashMap _outSockets; - private HashMap _inSockets; + private HashMap<String,I2PSocket> _outSockets; + private HashMap<String,I2PSocket> _inSockets; private I2PSocketOptions _defaultOptions; private long _acceptTimeout; private String _name; - private List _listeners; + private List<DisconnectListener> _listeners; private static int __managerId = 0; public static final short ACK = 0x51; @@ -76,10 +76,10 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener { _name = name; _context = context; _log = _context.logManager().getLog(I2PSocketManager.class); - _inSockets = new HashMap(16); - _outSockets = new HashMap(16); + _inSockets = new HashMap<String,I2PSocket>(16); + _outSockets = new HashMap<String,I2PSocket>(16); _acceptTimeout = ACCEPT_TIMEOUT_DEFAULT; - _listeners = new ArrayList(1); + _listeners = new ArrayList<DisconnectListener>(1); setSession(session); setDefaultOptions(buildOptions(opts)); _context.statManager().createRateStat("streaming.lifetime", "How long before the socket is closed?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 }); @@ -113,9 +113,9 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener { public void disconnected(I2PSession session) { _log.info(getName() + ": Disconnected from the session"); destroySocketManager(); - List listeners = null; + List<DisconnectListener> listeners = null; synchronized (_listeners) { - listeners = new ArrayList(_listeners); + listeners = new ArrayList<DisconnectListener>(_listeners); _listeners.clear(); } for (int i = 0; i < listeners.size(); i++) { @@ -660,7 +660,7 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener { * */ public Set listSockets() { - Set sockets = new HashSet(8); + Set<I2PSocket> sockets = new HashSet<I2PSocket>(8); synchronized (lock) { sockets.addAll(_inSockets.values()); sockets.addAll(_outSockets.values()); diff --git a/apps/sam/Demos/datagramTests/README.txt b/apps/sam/Demos/datagramTests/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e79434f9541f302533b6e343c5bcd3cf2139fa4 --- /dev/null +++ b/apps/sam/Demos/datagramTests/README.txt @@ -0,0 +1,15 @@ +# test example + +#in a first terminal, launch : + ./samIn.py inTest + +#in a second terminal, launch : + ./samForward.py 25000 forward + +#in a third terminal, launch : +l=0 +while [ $l -lt 1000 ] +do + l=$((l+1)) + ./samOut.py forward this is message n. $l +done diff --git a/apps/sam/Demos/datagramTests/samForward.py b/apps/sam/Demos/datagramTests/samForward.py new file mode 100755 index 0000000000000000000000000000000000000000..a1fd5b3e3bc16adb6c6d3c64993d75829a50330a --- /dev/null +++ b/apps/sam/Demos/datagramTests/samForward.py @@ -0,0 +1,35 @@ +#!/usr/bin/python + +import socket +import sys + +# create a forward style SAM datagram session +# that forwards messages on specified port (default port : 25000) +# creates a standard datagram server that listens on this port forever +# usage : ./samForward.py [port [SAM session name]] + +if len(sys.argv)>=2 : + port = eval(sys.argv[1]) +else : + port = 25000 + +if len(sys.argv)==3 : + name = sys.argv[2] +else : + name = "datagramSamForward" + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=DATAGRAM PORT="+str(port)+" ID="+name+" DESTINATION=EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHNqwgkhJnBW4ymaRsdVmITAha-ff0UiALfKSlznqp5HcSewgMHbzQ0I01TQytFnW outbound.nickname="+name+" inbound.nickname="+name+" outbound.length=0\n") +sys.stdout.write(sess.recv(10000)) + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.bind(("", port)) +print "waiting on port:", port +while 1: + data, addr = s.recvfrom(40000) + print data, " received from ", addr, "length=", len(data) + diff --git a/apps/sam/Demos/datagramTests/samIn.py b/apps/sam/Demos/datagramTests/samIn.py new file mode 100755 index 0000000000000000000000000000000000000000..c2c0589f30e2629966e600af50bc057d6dad29b8 --- /dev/null +++ b/apps/sam/Demos/datagramTests/samIn.py @@ -0,0 +1,29 @@ +#!/usr/bin/python + + +# create a SAM datagram session that writes incoming messages on its master session stream +# and a listen forever +# usage : ./samIn.py [session name] + +import socket +import sys + +if len(sys.argv)==2 : + name = sys.argv[1] +else : + name = "datagramSamIn" + + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=DATAGRAM ID="+name+" DESTINATION=tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABngJSS8xMyF4t82otZmCDhrKjbm-QLMtOLoumwR28ebDHEd4clF6O7aRa3d3yRH7p\n") +sys.stdout.write(sess.recv(1000)) +while 1 : + chunk = sess.recv(10000) + sys.stdout.write(chunk+'\n') + if not chunk : break +print + diff --git a/apps/sam/Demos/datagramTests/samOut.py b/apps/sam/Demos/datagramTests/samOut.py new file mode 100755 index 0000000000000000000000000000000000000000..1a521334f9759e68ad6bef05b0d807a818835ec9 --- /dev/null +++ b/apps/sam/Demos/datagramTests/samOut.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +# sends a message to datagram destinations opened by samForward.py and samIn.py, using specified sending session name +# at least samForward.py should be running for results to be seen +# usage : ./samOut.py [ sendingSessionName [ message ... ] ] +# sendingSessionName : default = datagramSamForward +# message : default = "this is nice message" + +import socket +import sys +import time + +if len(sys.argv)>=2 : + name = sys.argv[1] +else : + name = "datagramSamForward" + +if len(sys.argv)>2 : + message = ''.join([s+' ' for s in sys.argv[2:]]).strip() +else : + message = "This is a nice message" + + +# client.py +port = 7655 +host = "localhost" +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.bind(("", 0)) +s.sendto("3.0 "+name+" tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA\n"+message, (host, port)) +s.sendto("3.0 "+name+" EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAA\n"+message, (host, port)) + diff --git a/apps/sam/Demos/rawTests/README.txt b/apps/sam/Demos/rawTests/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e79434f9541f302533b6e343c5bcd3cf2139fa4 --- /dev/null +++ b/apps/sam/Demos/rawTests/README.txt @@ -0,0 +1,15 @@ +# test example + +#in a first terminal, launch : + ./samIn.py inTest + +#in a second terminal, launch : + ./samForward.py 25000 forward + +#in a third terminal, launch : +l=0 +while [ $l -lt 1000 ] +do + l=$((l+1)) + ./samOut.py forward this is message n. $l +done diff --git a/apps/sam/Demos/rawTests/samForward.py b/apps/sam/Demos/rawTests/samForward.py new file mode 100755 index 0000000000000000000000000000000000000000..5a65b6614afaafb0f3f48a43a7b5bde1f4285343 --- /dev/null +++ b/apps/sam/Demos/rawTests/samForward.py @@ -0,0 +1,36 @@ +#!/usr/bin/python + +import socket +import sys + +# create a forward style SAM raw datagram session +# that forwards messages on specified port (default port : 25000) +# creates a standard datagram server that listens on this port forever +# usage : ./samForward.py [port [SAM session name]] + +if len(sys.argv)>=2 : + port = eval(sys.argv[1]) +else : + port = 25000 + +if len(sys.argv)==3 : + name = sys.argv[2] +else : + name = "rawSamForward" + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=RAW PORT="+str(port)+" ID="+name+" DESTINATION=EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHNqwgkhJnBW4ymaRsdVmITAha-ff0UiALfKSlznqp5HcSewgMHbzQ0I01TQytFnW\n") +sys.stdout.write(sess.recv(10000)) + +# listening server +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.bind(("", port)) +print "waiting on port:", port +while 1: + data, addr = s.recvfrom(40000) + print data, " received from ", addr, "length=", len(data) + diff --git a/apps/sam/Demos/rawTests/samIn.py b/apps/sam/Demos/rawTests/samIn.py new file mode 100755 index 0000000000000000000000000000000000000000..ee2c3cbc8b8abb8f043cc6d7a1066962a42f81f2 --- /dev/null +++ b/apps/sam/Demos/rawTests/samIn.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + + +# create a SAM datagram session that writes incoming messages on its master session stream +# and a listen forever +# usage : ./samIn.py [session name] + +import socket +import sys + +if len(sys.argv)==2 : + name = sys.argv[1] +else : + name = "rawSamIn" + + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=RAW ID="+name+" DESTINATION=tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABngJSS8xMyF4t82otZmCDhrKjbm-QLMtOLoumwR28ebDHEd4clF6O7aRa3d3yRH7p\n") +sys.stdout.write(sess.recv(1000)) + +# listen incoming messages +while 1 : + chunk = sess.recv(10000) + sys.stdout.write(chunk+'\n') + if not chunk : break +print + diff --git a/apps/sam/Demos/rawTests/samOut.py b/apps/sam/Demos/rawTests/samOut.py new file mode 100755 index 0000000000000000000000000000000000000000..b035d8997e7e9a0526de9dc41f4d6dacad74c188 --- /dev/null +++ b/apps/sam/Demos/rawTests/samOut.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +# sends a message to datagram destinations opened by samForward.py and samIn.py, using specified sending session name +# at least samForward.py should be running for results to be seen +# usage : ./samOut.py [ sendingSessionName [ message ... ] ] +# sendingSessionName : default = datagramSamForward +# message : default = "this is nice message" + +import socket +import sys +import time + +if len(sys.argv)>=2 : + name = sys.argv[1] +else : + name = "rawSamForward" + +if len(sys.argv)>2 : + message = ''.join([s+' ' for s in sys.argv[2:]]).strip() +else : + message = "This is a nice message" + + +# client.py +port = 7655 +host = "localhost" +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s.bind(("", 0)) +s.sendto("3.0 "+name+" tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA\n"+message, (host, port)) +s.sendto("3.0 "+name+" EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAA\n"+message, (host, port)) + diff --git a/apps/sam/Demos/streamTests/README.txt b/apps/sam/Demos/streamTests/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ce7ae57b53131aacb0bafac2736f46ea30b33de --- /dev/null +++ b/apps/sam/Demos/streamTests/README.txt @@ -0,0 +1,24 @@ +# test example + +#in a first terminal, launch : + ./samIn.py inTest + +#in a second terminal, launch : + ./samOut.py + +#and again + ./samOut.py + +########## + +# test example n°2 + +#in a first terminal, launch : + ./samForward.py inTest + +#in a second terminal, launch : + ./server.py + +#in a third terminal, launch : + ./samOut.py + diff --git a/apps/sam/Demos/streamTests/samForward.py b/apps/sam/Demos/streamTests/samForward.py new file mode 100755 index 0000000000000000000000000000000000000000..687b265f6d6f26d6d8a1718419376948903cf012 --- /dev/null +++ b/apps/sam/Demos/streamTests/samForward.py @@ -0,0 +1,64 @@ +#!/usr/bin/python + +import socket +import sys + +# create a master SAM stream session that opens a destination in I2P world +# then open another session that tells SAM to forward incoming connections +# to the specified address +# +# usage : +# ./samForward.py [ silent [ port [ sessionName [ host ] ] ] ] +# +# silent : should the first line of incoming socket contain the peer destination (true or false) +# port : port to which connections are forwarded (default : 25000) +# sessionName : session id (default : "forward") +# host : host to which connections are forwarded (default : this host) + +if len(sys.argv)>=2 : + silent = " SILENT="+sys.argv[1] +else : silent = " SILENT=false" + +if len(sys.argv)>=3 : + port = " PORT="+sys.argv[2] +else : port = " PORT=25000" + +if len(sys.argv)>=4 : + name = " ID="+sys.argv[3] +else : name = " ID=forward" + +if len(sys.argv)>=5 : + host = " HOST="+sys.argv[4] +else : host = "" + + + + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=STREAM"+name+" DESTINATION=tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABngJSS8xMyF4t82otZmCDhrKjbm-QLMtOLoumwR28ebDHEd4clF6O7aRa3d3yRH7p\n") +sys.stdout.write(sess.recv(1000)) + +sock = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sock.connect(("127.0.0.1",7656)); +sock.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sock.recv(1000)) +sock.send("STREAM FORWARD" + name + host + port + silent + "\n") +sys.stdout.write(sock.recv(1000)) + +l=0 +while 1 : + chunk = sock.recv(100) + sys.stdout.write(chunk) + if not chunk : break +print "Forward socket closed" +l=0 +while 1 : + chunk = sess.recv(100) + sys.stdout.write(chunk) + if not chunk : break + diff --git a/apps/sam/Demos/streamTests/samIn.py b/apps/sam/Demos/streamTests/samIn.py new file mode 100755 index 0000000000000000000000000000000000000000..ab2e3fa5252ff0f5046d39ae06cb9c4788dd0ecc --- /dev/null +++ b/apps/sam/Demos/streamTests/samIn.py @@ -0,0 +1,91 @@ +#!/usr/bin/python + + +# create an stream session +# then an "accept" stream connected to this session +# then another "accept" stream from the same session +# then listen from the first stream and then listen from the second +# usage : ./samIn.py [ silent [ name ] ] +# name : the session id ( defaults to InTest ) +# silent : true or false : tells wether we want to receive the incoming stream destination +# as first line + +import socket +import sys +import time + +if len(sys.argv)>=2 : + silent = " SILENT="+sys.argv[1] +else : silent = " SILENT=false" + +if len(sys.argv)>=3 : + name = sys.argv[2] +else : name = "inTest" + + + + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=STREAM ID="+name+" DESTINATION=tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABngJSS8xMyF4t82otZmCDhrKjbm-QLMtOLoumwR28ebDHEd4clF6O7aRa3d3yRH7p\n") +sys.stdout.write(sess.recv(1000)) + + + + + +def accept() : + sock = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) + sock.connect(("127.0.0.1",7656)); + sock.send("HELLO VERSION MIN=3.0 MAX=3.0\n") + sys.stdout.write(sock.recv(1000)) + sock.send("STREAM ACCEPT ID=" + name + silent+"\n") + print "STREAM ACCEPT ID="+name+silent + if (silent==" SILENT=false") : + sys.stdout.write( sock.recv(100) ) + return sock + +def echo( sock, lines ) : + l = 0 + while lines==-1 or l<lines : + chunk = sock.recv(1000) + if lines!=-1 : l = l + 1 + if not chunk : break + print chunk + sock.send(chunk) + print + + + +sock1 = accept() +time.sleep(1) + +sock2 = accept() + +print "Second listening session" +try : + echo(sock2, -1) +except : + print sock2 + +if silent == " SILENT=false" : + sys.stdout.write(sock1.recv(1000)) +else : + # we know sock1 is accepted if it receives a byte + sock1.recv(1) + +sock3 = accept() + + +print "First listening session" +echo(sock1, 2) +sock1.close() + +print "Third listening session" +echo(sock3, -1) + + diff --git a/apps/sam/Demos/streamTests/samOut.py b/apps/sam/Demos/streamTests/samOut.py new file mode 100755 index 0000000000000000000000000000000000000000..7e132f2c4ba79b30ffc4d9e9d9706634694cc2dc --- /dev/null +++ b/apps/sam/Demos/streamTests/samOut.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + + +# open a I2P stream destination +# then open another stream that connects to the destination created by samForward.py or samIn.py +# then send bytes through the stream +# usage : +# ./samOut.py [ silent [ sessionName ] ] +# +# silent : should the first incoming after the connection request contain the connection status message (true or false) +# sessionName : session id (default : "forward") + +import socket +import sys +import time + +if len(sys.argv)>=2 : + silent = " SILENT="+sys.argv[1] +else : silent = " SILENT=false" + +if len(sys.argv)>=3 : + name = " ID="+sys.argv[2] +else : name = " ID=testOutStream" + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=STREAM"+name+" DESTINATION=EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHNqwgkhJnBW4ymaRsdVmITAha-ff0UiALfKSlznqp5HcSewgMHbzQ0I01TQytFnW\n") +sys.stdout.write(sess.recv(1000)) + +sock = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sock.connect(("127.0.0.1",7656)); +sock.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sock.recv(1000)) +sock.send("STREAM CONNECT"+name+" DESTINATION=tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA"+silent+"\n") + +# wait for acknowledgement before sending data, if we asked for it +if (silent==" SILENT=false") : + sys.stdout.write(sock.recv(1000)) + +for i in range(1,11) : + sock.send(str(i)+'\n') + buf=sock.recv(1000) + sys.stdout.write(str(i)+' '+buf) + if not buf : break + +print + + diff --git a/apps/sam/Demos/streamTests/samOutWithNaming.py b/apps/sam/Demos/streamTests/samOutWithNaming.py new file mode 100755 index 0000000000000000000000000000000000000000..6aa6476bc2ef55563d3a697f9279795086e7295c --- /dev/null +++ b/apps/sam/Demos/streamTests/samOutWithNaming.py @@ -0,0 +1,51 @@ +#!/usr/bin/python + + +# open a I2P stream destination +# then open another stream that connects to the destination created by samForward.py or samIn.py +# then send bytes through the stream +# usage : +# ./samOut.py [ silent [ sessionName ] ] +# +# silent : should the first incoming after the connection request contain the connection status message (true or false) +# sessionName : session id (default : "forward") + +import socket +import sys +import time + +if len(sys.argv)>=2 : + silent = " SILENT="+sys.argv[1] +else : silent = " SILENT=false" + +if len(sys.argv)>=3 : + name = " ID="+sys.argv[2] +else : name = " ID=testOutStream" + +sess = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sess.connect(("127.0.0.1",7656)); +sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sess.recv(1000)) +sess.send("SESSION CREATE STYLE=STREAM"+name+" DESTINATION=EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHNqwgkhJnBW4ymaRsdVmITAha-ff0UiALfKSlznqp5HcSewgMHbzQ0I01TQytFnW\n") +sys.stdout.write(sess.recv(1000)) + +sock = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +sock.connect(("127.0.0.1",7656)); +sock.send("HELLO VERSION MIN=3.0 MAX=3.0\n") +sys.stdout.write(sock.recv(1000)) +sock.send("STREAM CONNECT"+name+" DESTINATION=http://amiga.i2p"+silent+"\n") + +# wait for acknowledgement before sending data, if we asked for it +if (silent==" SILENT=false") : + sys.stdout.write(sock.recv(1000)) + +while (1) : + buf=sock.recv(1000) + sys.stdout.write(buf) + if not buf : break + +print + + diff --git a/apps/sam/Demos/streamTests/server.py b/apps/sam/Demos/streamTests/server.py new file mode 100755 index 0000000000000000000000000000000000000000..829a37e321385468d12ea3939fb0e46381ed0c53 --- /dev/null +++ b/apps/sam/Demos/streamTests/server.py @@ -0,0 +1,41 @@ +#!/usr/bin/python + + +# echo server +# accepts a socket on specified port, writes on stdout and send back incoming data + +import socket +import sys + +if len(sys.argv)>=2 : + port = eval(sys.argv[1]) +else : port = 25000 + +#create an INET, STREAMing socket +serversocket = socket.socket( + socket.AF_INET, socket.SOCK_STREAM) +#bind the socket to a public host, +# and a well-known port +serversocket.bind(("0.0.0.0", port)) + #become a server socket +serversocket.listen(1) + + + #accept connections from outside +(clientsocket, address) = serversocket.accept() + #now do something with the clientsocket + #in this case, we'll pretend this is a threaded server + +i = 0 +while 1 : + chunk = clientsocket.recv(1024) + i = i + 1 + sys.stdout.write(str(i)+' '+chunk) + if not chunk: break + clientsocket.send(str(i)+' '+chunk) + + +clientsocket.close() + +print + diff --git a/apps/sam/doc/sam.3.0-protocol.txt b/apps/sam/doc/sam.3.0-protocol.txt new file mode 100644 index 0000000000000000000000000000000000000000..51c5597983a82a33f348163bb6c8c679ac28789f --- /dev/null +++ b/apps/sam/doc/sam.3.0-protocol.txt @@ -0,0 +1,487 @@ +---------------------------------------------------------------------- +Simple Anonymous Messaging (SAM version 3.0) +---------------------------------------------------------------------- +Client application talks to SAM bridge, which deals with +all of the I2P functionality (using the ministreaming +lib for virtual streams, or I2CP directly for async messages). + +All client<-->SAM bridge communication is unencrypted and +unauthenticated. Access to the SAM +bridge should be protected through firewalls or other means +(perhaps the bridge may have ACLs on what IPs it accepts +connections from). + +All of these SAM messages are sent on a single line in plain ASCII, +terminated by the newline character (\n). The formatting shown +below is merely for readability, and while the first two words in +each message must stay in their specific order, the ordering of +the key=value pairs can change (e.g. "ONE TWO A=B C=D" or +"ONE TWO C=D A=B" are both perfectly valid constructions). In +addition, the protocol is case-sensitive. +In the following, message examples are preceded by "-> " for +messages sent by the client to the SAM bridge, and by "<- " for +messages sent by the SAM bridge to the client. + +I2P communications can take three distinct forms: +* Virtual streams +* Repliable datagrams (messages with a FROM field) +* Anonymous datagrams (raw anonymous messages) + +I2P communications are supported by I2P sessions, and each I2P +session is bound to an address (called destination). An I2P session +is associated with one of the three types above, and cannot carry +communications of another type. + + +---------------------------------------------------------------------- +SAM connection handshake +---------------------------------------------------------------------- +No SAM communication can occur until after the client and bridge have +agreed on a protocol version, which is done by the client sending +a HELLO and the bridge sending a HELLO REPLY: + +-> HELLO VERSION MIN=$min MAX=$max + +and + +<- HELLO REPLY RESULT=OK VERSION=3.0 + +*** In order to force protocol version 3.0, the values of $min and $max +*** must be "3.0". + +If the SAM bridge cannot find a suitable version, it replies with : + +<- HELLO REPLY RESULT=NOVERSION + +If some error occurred, such as a bad request format, it replies with : + +<- HELLO REPLY RESULT=I2P_ERROR MESSAGE={$message} + + +---------------------------------------------------------------------- +SAM sessions +---------------------------------------------------------------------- +A SAM session is created by a client opening a socket to the SAM +bridge, operating a handshake, and sending a SESSION CREATE message, +and the session terminates when the socket is disconnected. + +Each registered I2P Destination is uniquely associated with a session ID +(or nickname). + +Each session is uniquely associated with : + * the socket from which the client creates the session + * its ID (or nickname) + +The session creation message can only use one of these forms (messages +received through other forms are answered with an error message) : + +-> SESSION CREATE + STYLE={STREAM,DATAGRAM,RAW} + ID={$nickname} + DESTINATION={$private_destination_key,TRANSIENT} + [option=value]* + +DESTINATION specifies what destination should be used for +sending and receiving messages/streams. It has to be a suitable +private base64 destination key. If the destination is +specified as TRANSIENT, the SAM bridge creates a new destination. + +{$nickname} is the choice of the client. No whitespace is allowed. + +Additional options given are passed to the I2P session +configuration if not interpreted by the SAM bridge (e.g. +outbound.length=0). These options are documented below. + +The SAM bridge itself should already be configured with what router +it should communicate over I2P through (though if need be there may +be a way to provide an override, e.g. i2cp.tcp.host=localhost and +i2cp.tcp.port=7654). + +After receiving the session create message, the SAM bridge will reply +with a session status message, as follows: + +If the creation was successful : +<- SESSION STATUS RESULT=OK DESTINATION={$private_destination_key} + +If the nickname is already associated with a session : +<- SESSION STATUS RESULT=DUPLICATED_ID + +If the destination is already in use : +<- SESSION STATUS RESULT=DUPLICATED_DEST + +If the destination is not a valid private destination key : +<- SESSION STATUS RESULT=INVALID_KEY + +If some other error has occurred : +<- SESSION STATUS RESULT=I2P_ERROR MESSAGE={$message} + +If it's not OK, the MESSAGE should contain human-readable information +as to why the session could not be created. + + +SAM sessions live and die with the socket they are associated with. +When the socket is closed, the session dies, and all communications +using the session die at the same time. And the other way round, when +the session dies for any reason, the SAM bridge closes the socket. + + +---------------------------------------------------------------------- +SAM virtual streams +---------------------------------------------------------------------- +Virtual streams are guaranteed to be sent reliably and in order, with +failure and success notification as soon as it is available. + +Streams are bidirectional communication sockets between two I2P +destinations, but their opening has to be requested by one of them. +Hereafter, CONNECT commands are used by the SAM client for such a +request. FORWARD / ACCEPT commands are used by the SAM client when +he wants to listen to requests coming from other I2P destinations. + + +----------------------------- +SAM virtual streams : CONNECT +----------------------------- +A client asks for a connection by : + * opening a new socket with the SAM bridge + * passing the same HELLO handshake as above + * sending the connection command : + +-> STREAM CONNECT + ID={$nickname} + DESTINATION=$peer_public_base64_key + [SILENCE={true,false}] + +This establishes a new virtual connection from the local session +whose ID is {$nickname} to the specified peer. + +If SILENCE=true is passed, the SAM bridge won't issue any other message +on the socket : if the connection fails, the socket will be closed. +If the connection succeeds, all remaining data passing through the +current socket is forwarded from and to the connected I2P destination +peer. + +If SILENCE=false, which is the default value, the SAM bridge sends a +last message to its client before forwarding or shutting down the +socket : + +<- STREAM STATUS + RESULT=$result + [MESSAGE=...] + +The RESULT value may be one of: + + OK + CANT_REACH_PEER + I2P_ERROR + INVALID_KEY + INVALID_ID + TIMEOUT + +If the RESULT is OK, all remaining data passing through the +current socket is forwarded from and to the connected I2P destination +peer. If the connection was not possible (timeout, etc), +RESULT will contain the appropriate error value (accompanied by an +optional human-readable MESSAGE), and the SAM bridge closes the +socket. + +---------------------------- +SAM virtual streams : ACCEPT +---------------------------- + +A client waits for an incoming connection request by : + * opening a new socket with the SAM bridge + * passing the same HELLO handshake as above + * sending the accept command : + +-> STREAM ACCEPT + ID={$nickname} + [SILENCE={true,false}] + +This makes the session ${nickname} listen for one incoming +connection request from the I2P network. + +The SAM bridge answers with : + +<- STREAM STATUS + RESULT=$result + [MESSAGE=...] + +The RESULT value may be one of: + + OK + I2P_ERROR + INVALID_ID + +If the result is not OK, the socket is closed immediately by the SAM +bridge. If the result is OK, the SAM bridge starts waiting for an +incoming connection request from another I2P peer. When a request +arrives, the SAM bridge accepts it and : + + * If SILENCE=true was passed, the SAM bridge won't issue any other message +on the client socket : all remaining data passing through the +current socket is forwarded from and to the connected I2P destination +peer. + * If SILENCE=false was passed, which is the default value, the SAM bridge +sends the client an ASCII line containing the base64 public destination key +of the requesting peer. After this '\n' terminated line, all remaining data +passing through the current socket is forwarded from and to the connected +I2P destination peer, until one of the peer closes the socket. + +----------------------------- +SAM virtual streams : FORWARD +----------------------------- + +A client can use a regular socket server and wait for connection requests +coming from I2P. For that, the client has to : + * open a new socket with the SAM bridge + * pass the same HELLO handshake as above + * send the forward command : + +-> STREAM FORWARD + ID={$nickname} + PORT={$port} + [HOST={$host}] + [SILENCE={true,false}] + +This makes the session ${nickname} listen for incoming +connection requests from the I2P network. + +The SAM bridge answers with : + +<- STREAM STATUS + RESULT=$result + [MESSAGE=...] + +The RESULT value may be one of: + + OK + I2P_ERROR + INVALID_ID + + * {$host} is the hostname or IP address of the socket server to which +SAM will forward connection requests. If not given, SAM takes the IP +of the socket that issued the forward command. + + * {$port} is the port number of the socket server to which SAM will +forward connection requests. It is mandatory. + +When a connexion request arrives from I2P, the SAM bridge requests a +socket connexion from {$host}:{$port}. If it is accepted after no more +than 3 seconds, SAM will accept the connexion from I2P, and then : + + * If SILENCE=true was passed, all data passing through the obtained +current socket is forwarded from and to the connected I2P destination +peer. + * If SILENCE=false was passed, which is the default value, the SAM bridge +sends on the obtained socket an ASCII line containing the base64 public +destination key of the requesting peer. After this '\n' terminated line, +all remaining data passing through the socket is forwarded from and to +the connected I2P destination peer, until one of the sides closes the +socket. + + + +The I2P router will stop listening to incoming connection requests as +soon as the "forwarding" socket is closed. + + + + +---------------------------------------------------------------------- +SAM repliable datagrams : sending a datagram +---------------------------------------------------------------------- +While I2P doesn't inherently contain a FROM address, for ease of use +an additional layer is provided as repliable datagrams - unordered +and unreliable messages of up to 31KB in size that include a FROM +address (leaving up to 1KB for header material). This FROM address +is authenticated internally by SAM (making use of the destination's +signing key to verify the source) and includes replay prevention. + +** First method : + +After establishing a SAM session with STYLE=DATAGRAM, the client can +send datagrams through SAM's UDP port (7655). + +The first line of a datagram sent through this port has to be in the +following format : + +3.0 {$nickname} {$base64_public_destination_key} + + * 3.0 is the version of SAM + * {$nickname} is the id of the DGRAM session that will be used + * {$base64_public_destination_key} is the destination of the + datagram + * this line is '\n' terminated. + +The first line will be discarded by SAM before sending the remaining +of the message to the specified destination. + +** Second method : + +Datagrams can also be sent through the socket from which the datagram +session was opened. See the "DATAGRAM SEND" command of SAM versions 1 +and 2. + +---------------------------------------------------------------------- +SAM repliable datagrams : receiving a datagram +---------------------------------------------------------------------- +Received datagrams are written by SAM on the socket from which the +datagram session was opened, unless specified otherwise by the CREATE +command. + +When a datagram arrives, the bridge delivers it to the client via the +message : + +<- DATAGRAM RECEIVED + DESTINATION=$base64key + SIZE=$numBytes\n[$numBytes of data] + +The SAM bridge never exposes to the client the authentication headers +or other fields, merely the data that the sender provided. This +continues until the session is closed (by the client dropping the +connection). + +---------------------------------------------------------------------- +SAM repliable datagrams : forwarding datagrams +---------------------------------------------------------------------- +When creating a datagram session, the client can ask SAM to forward +incoming messages to a specified ip:port. It does so by issuing the +CREATE command with PORT and HOST options : + +-> SESSION CREATE + STYLE=DATAGRAM + ID={$nickname} + DESTINATION={$private_destination_key,TRANSIENT} + PORT={$port} + [HOST={$host}] + [option=value]* + + * {$host} is the hostname or IP address of the datagram server to + which SAM will forward datagrams. If not given, SAM takes the + IP of the socket that issued the forward command. + + * {$port} is the port number of the datagram server to which SAM + will forward datagrams. + +When a datagram arrives, the bridge sends to the specified host:port +a message containing the following data : + +${sender_base64_destination_key}\n{$datagram_payload} + + +---------------------------------------------------------------------- +SAM anonymous datagrams +---------------------------------------------------------------------- +Squeezing the most out of I2P's bandwidth, SAM allows clients to send +and receive anonymous datagrams, leaving authentication and reply +information up to the client themselves. These datagrams are +unreliable and unordered, and may be up to 32KB in size. + +After establishing a SAM session with STYLE=RAW, the client can +send anonymous datagrams throug the SAM bridge exactly the same way +he sends non anonymous datagrams. + +Both ways of receiving datagrams are also available for anonymous +datagrams. + +When anonymous datagrams are to be written to the socket that created +the session,the bridge delivers it to the client via: + +<- RAW RECEIVED + SIZE=$numBytes\n[$numBytes of data] + +When anonymous datagrams are to be forwarded to some host:port, +the bridge sends to the specified host:port a message containing +the following data : + +{$datagram_payload} + + +---------------------------------------------------------------------- +SAM utility functionality +---------------------------------------------------------------------- +The following message can be used by the client to query the SAM +bridge for name resolution: + + NAMING LOOKUP + NAME=$name + +which is answered by + + NAMING REPLY + RESULT=$result + NAME=$name + [VALUE=$base64key] + [MESSAGE=$message] + + +The RESULT value may be one of: + + OK + INVALID_KEY + KEY_NOT_FOUND + +If NAME=ME, then the reply will contain the base64key used by the +current session (useful if you're using a TRANSIENT one). If $result +is not OK, MESSAGE may convey a descriptive message, such as "bad +format", etc. + +Public and private base64 keys can be generated using the following +message: + + DEST GENERATE + +which is answered by + + DEST REPLY + PUB=$pubkey + PRIV=$privkey + +---------------------------------------------------------------------- +RESULT values +---------------------------------------------------------------------- +These are the values that can be carried by the RESULT field, with +their meaning: + + OK Operation completed succesfully + CANT_REACH_PEER The peer exists, but cannot be reached + DUPLICATED_DEST The specified Destination is already in use + I2P_ERROR A generic I2P error (e.g. I2CP disconnection, etc.) + INVALID_KEY The specified key is not valid (bad format, etc.) + KEY_NOT_FOUND The naming system can't resolve the given name + PEER_NOT_FOUND The peer cannot be found on the network + TIMEOUT Timeout while waiting for an event (e.g. peer answer) + +---------------------------------------------------------------------- +Tunnel Pool Options +---------------------------------------------------------------------- + +These options can be passed in as name=value pairs at the end of a +SAM SESSION CREATE line. + + inbound.nickname - Name shows up in I2P router console. + inbound.quantity - Number of tunnels, default 2. + inbound.backupQuantity - Number of backup tunnels, default 0. + inbound.rebuildPeriod - Obsolete - ignored - the router controls rebuilding + inbound.duration - Tunnels last X ms, default 10*60*1000. + (change not recommended, will break anonymmity + if it works at all) + inbound.length - Depth of tunnels, default 2. + inbound.lengthVariance - If negative, randomly skews from + (length - variance) to + (length + variance). If positive, from + length to (length + var), inclusive. + Default -1. + inbound.allowZeroHop - Zero hop allowed? Default "true". + outbound.* - Same properties as inbound. + i2p.streaming.connectDelay - If 0, connect ASAP. If positive, wait + until X ms have passed or output stream + is flushed or buffer fills. Default 0. + i2p.streaming.maxWindowSize - Max window size, default 64. + +---------------------------------------------------------------------- +Client library implementations: +---------------------------------------------------------------------- + C/C++: libSAM: http://www.innographx.com/mpc/libsam/ or i2p/sam/c/ + Python: Python/I2P: http://dev.i2p.net/contrib/apps/sam/python/index.html + Others: See apps/sam/ in I2P CVS. diff --git a/apps/sam/java/build.xml b/apps/sam/java/build.xml index 78f9cdfb0a26af4c91cb8a504b8f1b50d5b0e1f8..6a987b3411587e724d4b9049ded9d6c8e96ac88b 100644 --- a/apps/sam/java/build.xml +++ b/apps/sam/java/build.xml @@ -4,6 +4,7 @@ <target name="build" depends="builddep, jar" /> <target name="builddep"> <ant dir="../../ministreaming/java/" target="build" /> + <ant dir="../../streaming/java/" target="build" /> <!-- ministreaming will build core --> </target> <condition property="depend.available"> @@ -18,6 +19,7 @@ <classpath> <pathelement location="../../../core/java/build/obj" /> <pathelement location="../../ministreaming/java/build/obj" /> + <pathelement location="../../streaming/java/build/obj" /> </classpath> </depend> </target> @@ -29,7 +31,7 @@ srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar:../../streaming/java/build/streaming.jar" > <compilerarg line="${javac.compilerargs}" /> </javac> </target> @@ -38,7 +40,7 @@ srcdir="./test" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar:../../streaming/java/build/streaming.jar" > <compilerarg line="${javac.compilerargs}" /> </javac> </target> @@ -46,7 +48,7 @@ <jar destfile="./build/sam.jar" basedir="./build/obj" includes="**/*.class"> <manifest> <attribute name="Main-Class" value="net.i2p.sam.SAMBridge" /> - <attribute name="Class-Path" value="i2p.jar mstreaming.jar" /> + <attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" /> </manifest> </jar> </target> @@ -57,7 +59,7 @@ <mkdir dir="./build" /> <mkdir dir="./build/javadoc" /> <javadoc - sourcepath="./src:../../../core/java/src:../../ministreaming/java/src" destdir="./build/javadoc" + sourcepath="./src:../../../core/java/src:../../ministreaming/java/src:../../streaming/java/src" destdir="./build/javadoc" packagenames="*" use="true" splitindex="true" @@ -69,9 +71,11 @@ <target name="cleandep" depends="clean"> <!-- ministreaming will clean core --> <ant dir="../../ministreaming/java/" target="distclean" /> + <ant dir="../../streaming/java/" target="distclean" /> </target> <target name="distclean" depends="clean"> <!-- ministreaming will clean core --> <ant dir="../../ministreaming/java/" target="distclean" /> + <ant dir="../../streaming/java/" target="distclean" /> </target> </project> diff --git a/apps/sam/java/src/net/i2p/sam/SAMBridge.java b/apps/sam/java/src/net/i2p/sam/SAMBridge.java index ee7e33bb4a442a014c2732fc4bd39f1665056718..d6ed45ffe6876181973121b4ffb570127817b9c7 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMBridge.java +++ b/apps/sam/java/src/net/i2p/sam/SAMBridge.java @@ -14,9 +14,10 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; +import java.net.InetSocketAddress; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -34,7 +35,7 @@ import net.i2p.util.Log; */ public class SAMBridge implements Runnable { private final static Log _log = new Log(SAMBridge.class); - private ServerSocket serverSocket; + private ServerSocketChannel serverSocket; private Properties i2cpProps; /** * filename in which the name to private key mapping should @@ -45,12 +46,23 @@ public class SAMBridge implements Runnable { * app designated destination name to the base64 of the I2P formatted * destination keys (Destination+PrivateKey+SigningPrivateKey) */ - private Map nameToPrivKeys; + private Map<String,String> nameToPrivKeys; private boolean acceptConnections = true; private static final int SAM_LISTENPORT = 7656; + public static final String DEFAULT_SAM_KEYFILE = "sam.keys"; + public static final String PROP_TCP_HOST = "sam.tcp.host"; + public static final String PROP_TCP_PORT = "sam.tcp.port"; + protected static final String DEFAULT_TCP_HOST = "0.0.0.0"; + protected static final String DEFAULT_TCP_PORT = "7656"; + + public static final String PROP_DATAGRAM_HOST = "sam.udp.host"; + public static final String PROP_DATAGRAM_PORT = "sam.udp.port"; + protected static final String DEFAULT_DATAGRAM_HOST = "0.0.0.0"; + protected static final String DEFAULT_DATAGRAM_PORT = "7655"; + private SAMBridge() {} @@ -64,16 +76,18 @@ public class SAMBridge implements Runnable { */ public SAMBridge(String listenHost, int listenPort, Properties i2cpProps, String persistFile) { persistFilename = persistFile; - nameToPrivKeys = new HashMap(8); + nameToPrivKeys = new HashMap<String,String>(8); loadKeys(); try { if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) { - serverSocket = new ServerSocket(listenPort, 0, InetAddress.getByName(listenHost)); + serverSocket = ServerSocketChannel.open(); + serverSocket.socket().bind(new InetSocketAddress(listenHost, listenPort)); if (_log.shouldLog(Log.DEBUG)) _log.debug("SAM bridge listening on " + listenHost + ":" + listenPort); } else { - serverSocket = new ServerSocket(listenPort); + serverSocket = ServerSocketChannel.open(); + serverSocket.socket().bind(new InetSocketAddress(listenPort)); if (_log.shouldLog(Log.DEBUG)) _log.debug("SAM bridge listening on 0.0.0.0:" + listenPort); } @@ -191,36 +205,50 @@ public class SAMBridge implements Runnable { } } + static class HelpRequested extends Exception {static final long serialVersionUID=0x1;} + /** * Usage: - * <pre>SAMBridge [[listenHost ]listenPort[ name=val]*]</pre> - * + * <pre>SAMBridge [ keyfile [listenHost ] listenPort [ name=val ]* ]</pre> + * or: + * <pre>SAMBridge [ name=val ]* </pre> + * * name=val options are passed to the I2CP code to build a session, * allowing the bridge to specify an alternate I2CP host and port, tunnel * depth, etc. - * @param args [[listenHost ]listenPort[ name=val]*] + * @param args [ keyfile [ listenHost ] listenPort [ name=val ]* ] */ public static void main(String args[]) { String keyfile = DEFAULT_SAM_KEYFILE; int port = SAM_LISTENPORT; - String host = "0.0.0.0"; + String host = DEFAULT_TCP_HOST; Properties opts = null; if (args.length > 0) { - keyfile = args[0]; - int portIndex = 1; - try { - port = Integer.parseInt(args[portIndex]); - } catch (NumberFormatException nfe) { - host = args[1]; - portIndex++; - try { - port = Integer.parseInt(args[portIndex]); - } catch (NumberFormatException nfe1) { - usage(); - return; - } - } - opts = parseOptions(args, portIndex+1); + try { + opts = parseOptions(args, 0); + keyfile = args[0]; + int portIndex = 1; + try { + if (args.length>portIndex) port = Integer.parseInt(args[portIndex]); + } catch (NumberFormatException nfe) { + host = args[portIndex]; + portIndex++; + try { + if (args.length>portIndex) port = Integer.parseInt(args[portIndex]); + } catch (NumberFormatException nfe1) { + try { + port = Integer.parseInt(opts.getProperty(SAMBridge.PROP_TCP_PORT, SAMBridge.DEFAULT_TCP_PORT)); + host = opts.getProperty(SAMBridge.PROP_TCP_HOST, SAMBridge.DEFAULT_TCP_HOST); + } catch (NumberFormatException e) { + usage(); + return; + } + } + } + } catch (HelpRequested e) { + usage(); + return; + } } SAMBridge bridge = new SAMBridge(host, port, opts, keyfile); I2PAppThread t = new I2PAppThread(bridge, "SAMListener"); @@ -236,10 +264,11 @@ public class SAMBridge implements Runnable { t.start(); } - private static Properties parseOptions(String args[], int startArgs) { + private static Properties parseOptions(String args[], int startArgs) throws HelpRequested { Properties props = new Properties(); // skip over first few options for (int i = startArgs; i < args.length; i++) { + if (args[i].equals("-h")) throw new HelpRequested(); int eq = args[i].indexOf('='); if (eq <= 0) continue; if (eq >= args[i].length()-1) continue; @@ -255,50 +284,76 @@ public class SAMBridge implements Runnable { private static void usage() { System.err.println("Usage: SAMBridge [keyfile [listenHost] listenPortNum[ name=val]*]"); + System.err.println("or:"); + System.err.println(" SAMBridge [ name=val ]*"); System.err.println(" keyfile: location to persist private keys (default sam.keys)"); System.err.println(" listenHost: interface to listen on (0.0.0.0 for all interfaces)"); System.err.println(" listenPort: port to listen for SAM connections on (default 7656)"); System.err.println(" name=val: options to pass when connecting via I2CP, such as "); System.err.println(" i2cp.host=localhost and i2cp.port=7654"); + System.err.println(""); + System.err.println("Host and ports of the SAM bridge can be specified with the alternate"); + System.err.println("form by specifying options "+SAMBridge.PROP_TCP_HOST+" and/or "+ + SAMBridge.PROP_TCP_PORT); + System.err.println(""); + System.err.println("Options "+SAMBridge.PROP_DATAGRAM_HOST+" and "+SAMBridge.PROP_DATAGRAM_PORT+ + " specify the listening ip"); + System.err.println("range and the port of SAM datagram server. This server is"); + System.err.println("only launched after a client creates the first SAM datagram"); + System.err.println("or raw session, after a handshake with SAM version >= 3.0."); + System.err.println(""); + System.err.println("The option loglevel=[DEBUG|WARN|ERROR|CRIT] can be used"); + System.err.println("for tuning the log verbosity.\n"); } public void run() { if (serverSocket == null) return; try { while (acceptConnections) { - Socket s = serverSocket.accept(); + SocketChannel s = serverSocket.accept(); if (_log.shouldLog(Log.DEBUG)) _log.debug("New connection from " - + s.getInetAddress().toString() + ":" - + s.getPort()); + + s.socket().getInetAddress().toString() + ":" + + s.socket().getPort()); - try { - SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps); - if (handler == null) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("SAM handler has not been instantiated"); + class HelloHandler implements Runnable { + SocketChannel s ; + SAMBridge parent ; + HelloHandler(SocketChannel s, SAMBridge parent) { + this.s = s ; + this.parent = parent ; + } + public void run() { try { - s.close(); - } catch (IOException e) {} - continue; - } - handler.setBridge(this); - handler.startHandling(); - } catch (SAMException e) { - if (_log.shouldLog(Log.ERROR)) - _log.error("SAM error: " + e.getMessage(), e); - try { - String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n"; - s.getOutputStream().write(reply.getBytes("ISO-8859-1")); - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("SAM Error sending error reply", ioe); - } - try { s.close(); } catch (IOException ioe) {} - } catch (Exception ee) { - try { s.close(); } catch (IOException ioe) {} - _log.log(Log.CRIT, "Unexpected error handling SAM connection", ee); - } + SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps); + if (handler == null) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("SAM handler has not been instantiated"); + try { + s.close(); + } catch (IOException e) {} + return; + } + handler.setBridge(parent); + handler.startHandling(); + } catch (SAMException e) { + if (_log.shouldLog(Log.ERROR)) + _log.error("SAM error: " + e.getMessage(), e); + try { + String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n"; + s.write(ByteBuffer.wrap(reply.getBytes("ISO-8859-1"))); + } catch (IOException ioe) { + if (_log.shouldLog(Log.ERROR)) + _log.error("SAM Error sending error reply", ioe); + } + try { s.close(); } catch (IOException ioe) {} + } catch (Exception ee) { + try { s.close(); } catch (IOException ioe) {} + _log.log(Log.CRIT, "Unexpected error handling SAM connection", ee); + } + } + } + new I2PAppThread(new HelloHandler(s,this), "HelloHandler").start(); } } catch (Exception e) { if (_log.shouldLog(Log.ERROR)) diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java index a3e20f7df8caedc475beaac4e0287bdc0490a831..c8d31b489d145f0f811013ad37ce874514368a33 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java @@ -30,7 +30,7 @@ public class SAMDatagramSession extends SAMMessageSession { private final static Log _log = new Log(SAMDatagramSession.class); public static int DGRAM_SIZE_MAX = 31*1024; - private SAMDatagramReceiver recv = null; + protected SAMDatagramReceiver recv = null; private I2PDatagramMaker dgramMaker; private I2PDatagramDissector dgramDissector = new I2PDatagramDissector(); @@ -84,9 +84,10 @@ public class SAMDatagramSession extends SAMMessageSession { public boolean sendBytes(String dest, byte[] data) throws DataFormatException { if (data.length > DGRAM_SIZE_MAX) throw new DataFormatException("Datagram size exceeded (" + data.length + ")"); - - byte[] dgram = dgramMaker.makeI2PDatagram(data); - + byte[] dgram ; + synchronized (dgramMaker) { + dgram = dgramMaker.makeI2PDatagram(data); + } return sendBytesThroughMessageSession(dest, dgram); } diff --git a/apps/sam/java/src/net/i2p/sam/SAMException.java b/apps/sam/java/src/net/i2p/sam/SAMException.java index e51e35ea4fcf8aad07dd23727022e4c1a606a932..ae965a4c8c66cf98ebbeff629cf4ba61cce60f79 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMException.java +++ b/apps/sam/java/src/net/i2p/sam/SAMException.java @@ -15,11 +15,13 @@ package net.i2p.sam; */ public class SAMException extends Exception { + static final long serialVersionUID = 1 ; + public SAMException() { - super(); + super(); } public SAMException(String s) { - super(s); + super(s); } } diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandler.java b/apps/sam/java/src/net/i2p/sam/SAMHandler.java index 64d824a5782dc8eb0622e994be704997f03a8a65..d53a5a66217f6906e63ee20ac5d24a7f29953ab7 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandler.java @@ -9,9 +9,8 @@ package net.i2p.sam; */ import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; +import java.nio.channels.SocketChannel; +import java.nio.ByteBuffer; import java.util.Properties; import net.i2p.util.I2PAppThread; @@ -32,8 +31,7 @@ public abstract class SAMHandler implements Runnable { protected SAMBridge bridge = null; private Object socketWLock = new Object(); // Guards writings on socket - private Socket socket = null; - private OutputStream socketOS = null; // Stream associated to socket + protected SocketChannel socket = null; protected int verMajor = 0; protected int verMinor = 0; @@ -53,10 +51,9 @@ public abstract class SAMHandler implements Runnable { * @param i2cpProps properties to configure the I2CP connection (host, port, etc) * @throws IOException */ - protected SAMHandler(Socket s, + protected SAMHandler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps) throws IOException { socket = s; - socketOS = socket.getOutputStream(); this.verMajor = verMajor; this.verMinor = verMinor; @@ -86,8 +83,8 @@ public abstract class SAMHandler implements Runnable { * @return input stream * @throws IOException */ - protected final InputStream getClientSocketInputStream() throws IOException { - return socket.getInputStream(); + protected final SocketChannel getClientSocket() { + return socket ; } /** @@ -98,13 +95,17 @@ public abstract class SAMHandler implements Runnable { * @param data A byte array to be written * @throws IOException */ - protected final void writeBytes(byte[] data) throws IOException { + protected final void writeBytes(ByteBuffer data) throws IOException { synchronized (socketWLock) { - socketOS.write(data); - socketOS.flush(); + writeBytes(data, socket); } } + static public void writeBytes(ByteBuffer data, SocketChannel out) throws IOException { + while (data.hasRemaining()) out.write(data); + out.socket().getOutputStream().flush(); + } + /** * If you're crazy enough to write to the raw socket, grab the write lock * with getWriteLock(), synchronize against it, and write to the getOut() @@ -112,7 +113,6 @@ public abstract class SAMHandler implements Runnable { * @return socket Write lock object */ protected Object getWriteLock() { return socketWLock; } - protected OutputStream getOut() { return socketOS; } /** * Write a string to the handler's socket. This method must @@ -121,21 +121,25 @@ public abstract class SAMHandler implements Runnable { * * @param str A byte array to be written * - * @return True is the string was successfully written, false otherwise + * @return True if the string was successfully written, false otherwise */ protected final boolean writeString(String str) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Sending the client: [" + str + "]"); - try { - writeBytes(str.getBytes("ISO-8859-1")); + return writeString(str, socket); + } + + public static boolean writeString(String str, SocketChannel out) + { + try { + writeBytes(ByteBuffer.wrap(str.getBytes("ISO-8859-1")), out); } catch (IOException e) { _log.debug("Caught IOException", e); return false; } - - return true; + return true ; } - + /** * Close the socket connected to the SAM client. * @@ -178,8 +182,8 @@ public abstract class SAMHandler implements Runnable { return ("SAM handler (class: " + this.getClass().getName() + "; SAM version: " + verMajor + "." + verMinor + "; client: " - + this.socket.getInetAddress().toString() + ":" - + this.socket.getPort() + ")"); + + this.socket.socket().getInetAddress().toString() + ":" + + this.socket.socket().getPort() + ")"); } public final void run() { diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java index 21a0e97d277b858f47d7ffcae8361a33fbc1bc4d..e9a51214b992dc427f95eb00f1ef63648e16bd46 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java @@ -9,9 +9,9 @@ package net.i2p.sam; */ import java.io.IOException; -import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.net.Socket; +import java.nio.channels.SocketChannel; +import java.nio.ByteBuffer; import java.util.Properties; import java.util.StringTokenizer; @@ -34,17 +34,17 @@ public class SAMHandlerFactory { * @throws SAMException if the connection handshake (HELLO message) was malformed * @return A SAM protocol handler, or null if the client closed before the handshake */ - public static SAMHandler createSAMHandler(Socket s, Properties i2cpProps) throws SAMException { + public static SAMHandler createSAMHandler(SocketChannel s, Properties i2cpProps) throws SAMException { String line; StringTokenizer tok; try { - line = DataHelper.readLine(s.getInputStream()); + line = DataHelper.readLine(s.socket().getInputStream()); if (line == null) { _log.debug("Connection closed by client"); return null; } - tok = new StringTokenizer(line, " "); + tok = new StringTokenizer(line.trim(), " "); } catch (IOException e) { throw new SAMException("Error reading from socket: " + e.getMessage()); @@ -84,14 +84,15 @@ public class SAMHandlerFactory { } String ver = chooseBestVersion(minVer, maxVer); - if (ver == null) - throw new SAMException("No version specified"); - // Let's answer positively try { - OutputStream out = s.getOutputStream(); - out.write(("HELLO REPLY RESULT=OK VERSION=" - + ver + "\n").getBytes("ISO-8859-1")); + if (ver == null) { + s.write(ByteBuffer.wrap(("HELLO REPLY RESULT=NOVERSION\n").getBytes("ISO-8859-1"))); + return null ; + } + // Let's answer positively + s.write(ByteBuffer.wrap(("HELLO REPLY RESULT=OK VERSION=" + + ver + "\n").getBytes("ISO-8859-1"))); } catch (UnsupportedEncodingException e) { _log.error("Caught UnsupportedEncodingException (" + e.getMessage() + ")"); @@ -115,6 +116,9 @@ public class SAMHandlerFactory { case 2: handler = new SAMv2Handler(s, verMajor, verMinor, i2cpProps); break; + case 3: + handler = new SAMv3Handler(s, verMajor, verMinor, i2cpProps); + break; default: _log.error("BUG! Trying to initialize the wrong SAM version!"); throw new SAMException("BUG! (in handler instantiation)"); @@ -128,6 +132,7 @@ public class SAMHandlerFactory { /* Return the best version we can use, or null on failure */ private static String chooseBestVersion(String minVer, String maxVer) { + int minMajor = getMajor(minVer), minMinor = getMinor(minVer); int maxMajor = getMajor(maxVer), maxMinor = getMinor(maxVer); @@ -143,6 +148,8 @@ public class SAMHandlerFactory { float fmaxVer = (float) maxMajor + (float) maxMinor / 10 ; + if ( ( fminVer <= 3.0 ) && ( fmaxVer >= 3.0 ) ) return "3.0" ; + if ( ( fminVer <= 2.0 ) && ( fmaxVer >= 2.0 ) ) return "2.0" ; if ( ( fminVer <= 1.0 ) && ( fmaxVer >= 1.0 ) ) return "1.0" ; diff --git a/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java b/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java index b52ecda65d676549df4dda155bfb1bcd8a46b711..cd1c6b1a57d3d78f71cf37deb015676142264fac 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java +++ b/apps/sam/java/src/net/i2p/sam/SAMInvalidDirectionException.java @@ -15,7 +15,8 @@ package net.i2p.sam; * @author human */ public class SAMInvalidDirectionException extends Exception { - + static final long serialVersionUID = 1 ; + public SAMInvalidDirectionException() { super(); } diff --git a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java index b29b2f84c5f214c05728441a9407fc0caee9b5af..2c8ed2756bec07c5c2f644d4bef9902a097c716e 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java @@ -109,8 +109,7 @@ public abstract class SAMMessageSession { * @throws DataFormatException */ protected boolean sendBytesThroughMessageSession(String dest, byte[] data) throws DataFormatException { - Destination d = new Destination(); - d.fromBase64(dest); + Destination d = SAMUtils.getDest(dest); if (_log.shouldLog(Log.DEBUG)) { _log.debug("Sending " + data.length + " bytes to " + dest); diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java index 7f56066b1b3e22712ce3a2e26a7e0bff1fc0b22b..92bf4960dd7bd36bfd51f0a45e016e759b5622a5 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java @@ -26,7 +26,7 @@ public class SAMRawSession extends SAMMessageSession { private final static Log _log = new Log(SAMRawSession.class); public static final int RAW_SIZE_MAX = 32*1024; - private SAMRawReceiver recv = null; + protected SAMRawReceiver recv = null; /** * Create a new SAM RAW session. * diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java b/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java index 6d6d824b5fcd92d8b196fd23586b4bc904fb7d73..a57ddd6811aea436e7c3311b5774f5725433ba92 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java +++ b/apps/sam/java/src/net/i2p/sam/SAMStreamReceiver.java @@ -9,6 +9,7 @@ package net.i2p.sam; */ import java.io.IOException; +import java.nio.ByteBuffer; import net.i2p.data.Destination; @@ -53,14 +54,13 @@ public interface SAMStreamReceiver { public void notifyStreamOutgoingConnection(int id, String result, String msg) throws IOException; /** - * Send a byte array to a SAM client. + * Transmit a byte array from I2P to a SAM client. * * @param id Connection id * @param data Byte array to be received - * @param len Number of bytes in data * @throws IOException */ - public void receiveStreamBytes(int id, byte data[], int len) throws IOException; + public void receiveStreamBytes(int id, ByteBuffer data) throws IOException; /** * Notify that a connection has been closed diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java index 280562e48ed9dee401d4ca0a6e328bafa970c0ab..aef2802bd867f9d2ec4f41ec6dd98998ff2f0d26 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java @@ -13,6 +13,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; import java.net.ConnectException; import java.net.NoRouteToHostException; import java.util.ArrayList; @@ -51,15 +53,15 @@ public class SAMStreamSession { protected SAMStreamReceiver recv = null; - private SAMStreamSessionServer server = null; + protected SAMStreamSessionServer server = null; protected I2PSocketManager socketMgr = null; private Object handlersMapLock = new Object(); /** stream id (Long) to SAMStreamSessionSocketReader */ - private HashMap handlersMap = new HashMap(); + private HashMap<Integer,SAMStreamSessionSocketReader> handlersMap = new HashMap<Integer,SAMStreamSessionSocketReader>(); /** stream id (Long) to StreamSender */ - private HashMap sendersMap = new HashMap(); + private HashMap<Integer,StreamSender> sendersMap = new HashMap<Integer,StreamSender>(); private Object idLock = new Object(); private int lastNegativeId = 0; @@ -76,6 +78,10 @@ public class SAMStreamSession { public static String PROP_FORCE_FLUSH = "sam.forceFlush"; public static String DEFAULT_FORCE_FLUSH = "false"; + public SAMStreamSession() { + + } + /** * Create a new SAM STREAM session. * @@ -166,7 +172,7 @@ public class SAMStreamSession { } } - private class DisconnectListener implements I2PSocketManager.DisconnectListener { + protected class DisconnectListener implements I2PSocketManager.DisconnectListener { public void sessionDisconnected() { close(); } @@ -572,19 +578,20 @@ public class SAMStreamSession { _log.debug("run() called for socket reader " + id); int read = -1; - byte[] data = new byte[SOCKET_HANDLER_BUF_SIZE]; + ByteBuffer data = ByteBuffer.allocateDirect(SOCKET_HANDLER_BUF_SIZE); try { InputStream in = i2pSocket.getInputStream(); while (stillRunning) { - read = in.read(data); + data.clear(); + read = Channels.newChannel(in).read(data); if (read == -1) { _log.debug("Handler " + id + ": connection closed"); break; } - - recv.receiveStreamBytes(id, data, read); + data.flip(); + recv.receiveStreamBytes(id, data); } } catch (IOException e) { _log.debug("Caught IOException", e); @@ -650,7 +657,7 @@ public class SAMStreamSession { protected class v1StreamSender extends StreamSender { - private List _data; + private List<ByteArray> _data; private int _id; private ByteCache _cache; private OutputStream _out = null; @@ -660,7 +667,7 @@ public class SAMStreamSession { public v1StreamSender ( I2PSocket s, int id ) throws IOException { super ( s, id ); - _data = new ArrayList(1); + _data = new ArrayList<ByteArray>(1); _id = id; _cache = ByteCache.getInstance(4, 32*1024); _out = s.getOutputStream(); diff --git a/apps/sam/java/src/net/i2p/sam/SAMUtils.java b/apps/sam/java/src/net/i2p/sam/SAMUtils.java index 8bb3fac3008a84270f9ff0dfd1e9fddd75e7509e..61578e333fb82d022992be794c9785e02a1acd8f 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMUtils.java +++ b/apps/sam/java/src/net/i2p/sam/SAMUtils.java @@ -8,6 +8,7 @@ package net.i2p.sam; * */ +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Enumeration; @@ -19,8 +20,11 @@ import net.i2p.I2PException; import net.i2p.client.I2PClient; import net.i2p.client.I2PClientFactory; import net.i2p.client.naming.NamingService; +import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; +import net.i2p.data.PrivateKey; +import net.i2p.data.SigningPrivateKey; import net.i2p.util.Log; /** @@ -73,6 +77,22 @@ public class SAMUtils { return false; } } + + public static class InvalidDestination extends Exception { + static final long serialVersionUID = 0x1 ; + } + public static void checkPrivateDestination(String dest) throws InvalidDestination { + ByteArrayInputStream destKeyStream = new ByteArrayInputStream(Base64.decode(dest)); + + try { + new Destination().readBytes(destKeyStream); + new PrivateKey().readBytes(destKeyStream); + new SigningPrivateKey().readBytes(destKeyStream); + } catch (Exception e) { + throw new InvalidDestination(); + } + } + /** * Resolved the specified hostname. @@ -101,6 +121,27 @@ public class SAMUtils { return dest; } + /** + * Resolve the destination from a key or a hostname + * + * @param s Hostname or key to be resolved + * + * @return the Destination for the specified hostname, or null if not found + */ + public static Destination getDest(String s) throws DataFormatException + { + Destination d = new Destination() ; + try { + d.fromBase64(s); + } catch (DataFormatException e) { + d = lookupHost(s, null); + if ( d==null ) { + throw e ; + } + } + return d ; + } + /** * Parse SAM parameters, and put them into a Propetries object * diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java index 93a9a8d6696d7e82f51a9674c73d43eb13926b3a..4e6bd5dc788fb49e276c380afa6170a0c43e5a9e 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java @@ -12,12 +12,11 @@ import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; -import java.io.InputStream; import java.io.InterruptedIOException; -import java.io.OutputStream; import java.net.ConnectException; import java.net.NoRouteToHostException; -import java.net.Socket; +import java.nio.channels.SocketChannel; +import java.nio.ByteBuffer; import java.util.Properties; import java.util.StringTokenizer; @@ -40,14 +39,15 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag private final static Log _log = new Log(SAMv1Handler.class); - private final static int IN_BUFSIZE = 2048; + protected SAMRawSession rawSession = null; + protected SAMDatagramSession datagramSession = null; + protected SAMStreamSession streamSession = null; + protected SAMRawSession getRawSession() {return rawSession ;} + protected SAMDatagramSession getDatagramSession() {return datagramSession ;} + protected SAMStreamSession getStreamSession() {return streamSession ;} - private SAMRawSession rawSession = null; - private SAMDatagramSession datagramSession = null; - protected SAMStreamSession streamSession = null; - - private long _id; - private static volatile long __id = 0; + protected long _id; + protected static volatile long __id = 0; /** * Create a new SAM version 1 handler. This constructor expects @@ -60,7 +60,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag * @throws SAMException * @throws IOException */ - public SAMv1Handler(Socket s, int verMajor, int verMinor) throws SAMException, IOException { + public SAMv1Handler(SocketChannel s, int verMajor, int verMinor) throws SAMException, IOException { this(s, verMajor, verMinor, new Properties()); } /** @@ -75,7 +75,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag * @throws SAMException * @throws IOException */ - public SAMv1Handler(Socket s, int verMajor, int verMinor, Properties i2cpProps) throws SAMException, IOException { + public SAMv1Handler(SocketChannel s, int verMajor, int verMinor, Properties i2cpProps) throws SAMException, IOException { super(s, verMajor, verMinor, i2cpProps); _id = ++__id; _log.debug("SAM version 1 handler instantiated"); @@ -101,16 +101,13 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag _log.debug("SAM handling started"); try { - InputStream in = getClientSocketInputStream(); - int b = -1; - while (true) { if (shouldStop()) { _log.debug("Stop request found"); break; } - msg = DataHelper.readLine(in); + msg = DataHelper.readLine(getClientSocket().socket().getInputStream()).trim(); if (msg == null) { _log.debug("Connection closed by client"); break; @@ -175,27 +172,27 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } catch (IOException e) { _log.error("Error closing socket: " + e.getMessage()); } - if (rawSession != null) { - rawSession.close(); + if (getRawSession() != null) { + getRawSession().close(); } - if (datagramSession != null) { - datagramSession.close(); + if (getDatagramSession() != null) { + getDatagramSession().close(); } - if (streamSession != null) { - streamSession.close(); + if (getStreamSession() != null) { + getStreamSession().close(); } } } /* Parse and execute a SESSION message */ - private boolean execSessionMessage(String opcode, Properties props) { + protected boolean execSessionMessage(String opcode, Properties props) { String dest = "BUG!"; try{ if (opcode.equals("CREATE")) { - if ((rawSession != null) || (datagramSession != null) - || (streamSession != null)) { + if ((getRawSession() != null) || (getDatagramSession() != null) + || (getStreamSession() != null)) { _log.debug("Trying to create a session, but one still exists"); return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n"); } @@ -293,7 +290,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } /* Parse and execute a DEST message*/ - private boolean execDestMessage(String opcode, Properties props) { + protected boolean execDestMessage(String opcode, Properties props) { if (opcode.equals("GENERATE")) { if (props.size() > 0) { @@ -318,7 +315,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } /* Parse and execute a NAMING message */ - private boolean execNamingMessage(String opcode, Properties props) { + protected boolean execNamingMessage(String opcode, Properties props) { if (opcode.equals("LOOKUP")) { if (props == null) { _log.debug("No parameters specified in NAMING LOOKUP message"); @@ -331,20 +328,23 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag return false; } - Destination dest; + Destination dest = null ; if (name.equals("ME")) { - if (rawSession != null) { - dest = rawSession.getDestination(); - } else if (streamSession != null) { - dest = streamSession.getDestination(); - } else if (datagramSession != null) { - dest = datagramSession.getDestination(); + if (getRawSession() != null) { + dest = getRawSession().getDestination(); + } else if (getStreamSession() != null) { + dest = getStreamSession().getDestination(); + } else if (getDatagramSession() != null) { + dest = getDatagramSession().getDestination(); } else { _log.debug("Lookup for SESSION destination, but session is null"); return false; } } else { - dest = SAMUtils.lookupHost(name, null); + try { + dest = SAMUtils.getDest(name); + } catch (DataFormatException e) { + } } if (dest == null) { @@ -364,8 +364,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag /* Parse and execute a DATAGRAM message */ - private boolean execDatagramMessage(String opcode, Properties props) { - if (datagramSession == null) { + protected boolean execDatagramMessage(String opcode, Properties props) { + if (getDatagramSession() == null) { _log.error("DATAGRAM message received, but no DATAGRAM session exists"); return false; } @@ -403,12 +403,12 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } try { - DataInputStream in = new DataInputStream(getClientSocketInputStream()); + DataInputStream in = new DataInputStream(getClientSocket().socket().getInputStream()); byte[] data = new byte[size]; in.readFully(data); - if (!datagramSession.sendBytes(dest, data)) { + if (!getDatagramSession().sendBytes(dest, data)) { _log.error("DATAGRAM SEND failed"); return true; } @@ -435,8 +435,8 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } /* Parse and execute a RAW message */ - private boolean execRawMessage(String opcode, Properties props) { - if (rawSession == null) { + protected boolean execRawMessage(String opcode, Properties props) { + if (getRawSession() == null) { _log.error("RAW message received, but no RAW session exists"); return false; } @@ -474,12 +474,12 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } try { - DataInputStream in = new DataInputStream(getClientSocketInputStream()); + DataInputStream in = new DataInputStream(getClientSocket().socket().getInputStream()); byte[] data = new byte[size]; in.readFully(data); - if (!rawSession.sendBytes(dest, data)) { + if (!getRawSession().sendBytes(dest, data)) { _log.error("RAW SEND failed"); return true; } @@ -507,7 +507,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag /* Parse and execute a STREAM message */ protected boolean execStreamMessage(String opcode, Properties props) { - if (streamSession == null) { + if (getStreamSession() == null) { _log.error("STREAM message received, but no STREAM session exists"); return false; } @@ -567,11 +567,11 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } try { - if (!streamSession.sendBytes(id, getClientSocketInputStream(), size)) { // data)) { + if (!getStreamSession().sendBytes(id, getClientSocket().socket().getInputStream(), size)) { // data)) { if (_log.shouldLog(Log.WARN)) _log.warn("STREAM SEND [" + size + "] failed"); boolean rv = writeString("STREAM CLOSED RESULT=CANT_REACH_PEER ID=" + id + " MESSAGE=\"Send of " + size + " bytes failed\"\n"); - streamSession.closeConnection(id); + getStreamSession().closeConnection(id); return rv; } @@ -622,7 +622,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag try { try { - if (!streamSession.connect(id, dest, props)) { + if (!getStreamSession().connect(id, dest, props)) { _log.debug("STREAM connection failed"); return false; } @@ -673,7 +673,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } } - boolean closed = streamSession.closeConnection(id); + boolean closed = getStreamSession().closeConnection(id); if ( (!closed) && (_log.shouldLog(Log.WARN)) ) _log.warn("Stream unable to be closed, but this is non fatal"); return true; @@ -691,7 +691,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag // SAMRawReceiver implementation public void receiveRawBytes(byte data[]) throws IOException { - if (rawSession == null) { + if (getRawSession() == null) { _log.error("BUG! Received raw bytes, but session is null!"); throw new NullPointerException("BUG! RAW session is null!"); } @@ -701,17 +701,18 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag String msgText = "RAW RECEIVED SIZE=" + data.length + "\n"; msg.write(msgText.getBytes("ISO-8859-1")); msg.write(data); + msg.flush(); if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); - writeBytes(msg.toByteArray()); + writeBytes(ByteBuffer.wrap(msg.toByteArray())); } public void stopRawReceiving() { _log.debug("stopRawReceiving() invoked"); - if (rawSession == null) { + if (getRawSession() == null) { _log.error("BUG! Got raw receiving stop, but session is null!"); throw new NullPointerException("BUG! RAW session is null!"); } @@ -726,7 +727,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag // SAMDatagramReceiver implementation public void receiveDatagramBytes(Destination sender, byte data[]) throws IOException { - if (datagramSession == null) { + if (getDatagramSession() == null) { _log.error("BUG! Received datagram bytes, but session is null!"); throw new NullPointerException("BUG! DATAGRAM session is null!"); } @@ -740,14 +741,14 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); msg.write(data); - - writeBytes(msg.toByteArray()); + msg.flush(); + writeBytes(ByteBuffer.wrap(msg.toByteArray())); } public void stopDatagramReceiving() { _log.debug("stopDatagramReceiving() invoked"); - if (datagramSession == null) { + if (getDatagramSession() == null) { _log.error("BUG! Got datagram receiving stop, but session is null!"); throw new NullPointerException("BUG! DATAGRAM session is null!"); } @@ -764,7 +765,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag public void streamSendAnswer( int id, String result, String bufferState ) throws IOException { - if ( streamSession == null ) + if ( getStreamSession() == null ) { _log.error ( "BUG! Want to answer to stream SEND, but session is null!" ); throw new NullPointerException ( "BUG! STREAM session is null!" ); @@ -782,7 +783,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag public void notifyStreamSendBufferFree( int id ) throws IOException { - if ( streamSession == null ) + if ( getStreamSession() == null ) { _log.error ( "BUG! Stream outgoing buffer is free, but session is null!" ); throw new NullPointerException ( "BUG! STREAM session is null!" ); @@ -796,7 +797,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag public void notifyStreamIncomingConnection(int id, Destination d) throws IOException { - if (streamSession == null) { + if (getStreamSession() == null) { _log.error("BUG! Received stream connection, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } @@ -810,7 +811,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag public void notifyStreamOutgoingConnection ( int id, String result, String msg ) throws IOException { - if ( streamSession == null ) + if ( getStreamSession() == null ) { _log.error ( "BUG! Received stream connection, but session is null!" ); throw new NullPointerException ( "BUG! STREAM session is null!" ); @@ -830,34 +831,28 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag } } - public void receiveStreamBytes(int id, byte data[], int len) throws IOException { - if (streamSession == null) { + public void receiveStreamBytes(int id, ByteBuffer data) throws IOException { + if (getStreamSession() == null) { _log.error("Received stream bytes, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } - String msgText = "STREAM RECEIVED ID=" + id +" SIZE=" + len + "\n"; + String msgText = "STREAM RECEIVED ID=" + id +" SIZE=" + data.remaining() + "\n"; if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); - byte prefix[] = msgText.getBytes("ISO-8859-1"); + ByteBuffer prefix = ByteBuffer.wrap(msgText.getBytes("ISO-8859-1")); - // dont waste so much memory - //ByteArrayOutputStream msg = new ByteArrayOutputStream(); - //msg.write(msgText.getBytes("ISO-8859-1")); - //msg.write(data, 0, len); - // writeBytes(msg.toByteArray()); Object writeLock = getWriteLock(); - OutputStream out = getOut(); synchronized (writeLock) { - out.write(prefix); - out.write(data, 0, len); - out.flush(); + while (prefix.hasRemaining()) socket.write(prefix); + while (data.hasRemaining()) socket.write(data); + socket.socket().getOutputStream().flush(); } } public void notifyStreamDisconnection(int id, String result, String msg) throws IOException { - if (streamSession == null) { + if (getStreamSession() == null) { _log.error("BUG! Received stream disconnection, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } @@ -873,7 +868,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag public void stopStreamReceiving() { _log.debug("stopStreamReceiving() invoked", new Exception("stopped")); - if (streamSession == null) { + if (getStreamSession() == null) { _log.error("BUG! Got stream receiving stop, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java index 75f1bd4b4788655240847d7cd126ec1a8d182cbe..fe1f379b7e0d3c4f1b7f8daa24972388cf759f65 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv2Handler.java @@ -9,7 +9,7 @@ package net.i2p.sam; */ import java.io.IOException; -import java.net.Socket; +import java.nio.channels.SocketChannel; import java.util.Properties; import net.i2p.data.DataFormatException; @@ -36,7 +36,7 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat * @param verMajor SAM major version to manage (should be 2) * @param verMinor SAM minor version to manage */ - public SAMv2Handler ( Socket s, int verMajor, int verMinor ) throws SAMException, IOException + public SAMv2Handler ( SocketChannel s, int verMajor, int verMinor ) throws SAMException, IOException { this ( s, verMajor, verMinor, new Properties() ); } @@ -52,7 +52,7 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat * @param i2cpProps properties to configure the I2CP connection (host, port, etc) */ - public SAMv2Handler ( Socket s, int verMajor, int verMinor, Properties i2cpProps ) throws SAMException, IOException + public SAMv2Handler ( SocketChannel s, int verMajor, int verMinor, Properties i2cpProps ) throws SAMException, IOException { super ( s, verMajor, verMinor, i2cpProps ); } @@ -72,7 +72,7 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat /* Parse and execute a STREAM message */ protected boolean execStreamMessage ( String opcode, Properties props ) { - if ( streamSession == null ) + if ( getStreamSession() == null ) { _log.error ( "STREAM message received, but no STREAM session exists" ); return false; @@ -173,7 +173,7 @@ public class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDat } } - streamSession.setReceiveLimit ( id, limit, nolimit ) ; + getStreamSession().setReceiveLimit ( id, limit, nolimit ) ; return true; } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java index de5b7851bc7de434f29dac13e3ac2c175893413a..4197597eb0d56e9f26bcd1cbab60b2669916786b 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv2StreamSession.java @@ -12,6 +12,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; +import java.nio.channels.Channels; +import java.nio.ByteBuffer; import java.net.ConnectException; import java.net.NoRouteToHostException; import java.util.ArrayList; @@ -140,9 +142,6 @@ public class SAMv2StreamSession extends SAMStreamSession public class StreamConnector implements Runnable { - private Object runningLock = new Object(); - private boolean stillRunning = true; - private int id; private Destination dest ; private I2PSocketOptions opts ; @@ -245,7 +244,7 @@ public class SAMv2StreamSession extends SAMStreamSession protected class v2StreamSender extends StreamSender { - private List _data; + private List<ByteArray> _data; private int _dataSize; private int _id; private ByteCache _cache; @@ -257,7 +256,7 @@ public class SAMv2StreamSession extends SAMStreamSession public v2StreamSender ( I2PSocket s, int id ) throws IOException { super ( s, id ); - _data = new ArrayList ( 1 ); + _data = new ArrayList<ByteArray> ( 1 ); _dataSize = 0; _id = id; _cache = ByteCache.getInstance ( 10, 32 * 1024 ); @@ -511,7 +510,7 @@ public class SAMv2StreamSession extends SAMStreamSession _log.debug ( "run() called for socket reader " + id ); int read = -1; - byte[] data = new byte[SOCKET_HANDLER_BUF_SIZE]; + ByteBuffer data = ByteBuffer.allocateDirect(SOCKET_HANDLER_BUF_SIZE); try { @@ -533,7 +532,8 @@ public class SAMv2StreamSession extends SAMStreamSession break ; } - read = in.read ( data ); + data.clear(); + read = Channels.newChannel(in).read ( data ); if ( read == -1 ) { @@ -542,8 +542,8 @@ public class SAMv2StreamSession extends SAMStreamSession } totalReceived += read ; - - recv.receiveStreamBytes ( id, data, read ); + data.flip(); + recv.receiveStreamBytes ( id, data ); } } catch ( IOException e ) diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java new file mode 100644 index 0000000000000000000000000000000000000000..69f14430df448c734cf5e19db6d32699f77374d7 --- /dev/null +++ b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java @@ -0,0 +1,90 @@ +/** + * @author MKVore + * + */ + +package net.i2p.sam; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.util.Properties; + +import net.i2p.client.I2PSessionException; +import net.i2p.data.DataFormatException; +import net.i2p.data.Destination; +import net.i2p.util.Log; + +import java.net.InetSocketAddress; +import java.net.SocketAddress ; +import java.nio.ByteBuffer; + +public class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Session, SAMDatagramReceiver { + + private final static Log _log = new Log ( SAMv3DatagramSession.class ); + + SAMv3Handler handler = null ; + SAMv3Handler.DatagramServer server = null ; + String nick = null ; + SocketAddress clientAddress = null ; + + public String getNick() { return nick; } + + /** + * build a DatagramSession according to informations registered + * with the given nickname + * @param nick nickname of the session + * @throws IOException + * @throws DataFormatException + * @throws I2PSessionException + */ + public SAMv3DatagramSession(String nick) + throws IOException, DataFormatException, I2PSessionException { + + super(SAMv3Handler.sSessionsHash.get(nick).getDest(), + SAMv3Handler.sSessionsHash.get(nick).getProps(), + null + ); + this.nick = nick ; + this.recv = this ; + this.server = SAMv3Handler.DatagramServer.getInstance() ; + + SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); + if ( rec==null ) throw new InterruptedIOException() ; + + this.handler = rec.getHandler(); + + Properties props = rec.getProps(); + String portStr = props.getProperty("PORT") ; + if ( portStr==null ) { + _log.debug("receiver port not specified. Current socket will be used."); + } + else { + int port = Integer.parseInt(portStr); + + String host = props.getProperty("HOST"); + if ( host==null ) { + host = rec.getHandler().getClientIP(); + _log.debug("no host specified. Taken from the client socket : " + host+':'+port); + } + + + this.clientAddress = new InetSocketAddress(host,port); + } + } + + public void receiveDatagramBytes(Destination sender, byte[] data) throws IOException { + if (this.clientAddress==null) { + this.handler.receiveDatagramBytes(sender, data); + } else { + String msg = sender.toBase64()+"\n"; + ByteBuffer msgBuf = ByteBuffer.allocate(msg.length()+data.length); + msgBuf.put(msg.getBytes("ISO-8859-1")); + msgBuf.put(data); + msgBuf.flip(); + this.server.send(this.clientAddress, msgBuf); + } + } + + public void stopDatagramReceiving() { + } +} diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java new file mode 100644 index 0000000000000000000000000000000000000000..7a64d84416c76b7a8ec629d434de392838c94579 --- /dev/null +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -0,0 +1,783 @@ +package net.i2p.sam; +/* + * free (adj.): unencumbered; not under the control of others + * Written by human in 2004 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + + +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.net.ConnectException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.NoRouteToHostException; +import java.nio.channels.DatagramChannel; +import java.nio.channels.SocketChannel; +import java.nio.ByteBuffer; +import java.util.Properties; +import java.util.HashMap; +import java.util.StringTokenizer; + +import net.i2p.I2PException; +import net.i2p.client.I2PSessionException; +import net.i2p.data.Base64; +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.data.Destination; +import net.i2p.util.Log; +import net.i2p.util.I2PAppThread; + +/** + * Class able to handle a SAM version 3 client connection. + * + * @author mkvore + */ + +public class SAMv3Handler extends SAMv1Handler +{ + private final static Log _log = new Log ( SAMv3Handler.class ); + + protected SAMv3RawSession rawSession = null ; + protected SAMv3DatagramSession datagramSession = null ; + protected SAMv3StreamSession streamSession = null ; + + protected SAMRawSession getRawSession() { + return rawSession ; + } + protected SAMDatagramSession getDatagramSession() { + return datagramSession ; + } + protected SAMStreamSession getStreamSession() { + return streamSession ; + } + + protected Session session = null ; + + interface Session { + String getNick(); + void close(); + boolean sendBytes(String dest, byte[] data) throws DataFormatException; + } + + /** + * Create a new SAM version 3 handler. This constructor expects + * that the SAM HELLO message has been still answered (and + * stripped) from the socket input stream. + * + * @param s Socket attached to a SAM client + * @param verMajor SAM major version to manage (should be 3) + * @param verMinor SAM minor version to manage + */ + public SAMv3Handler ( SocketChannel s, int verMajor, int verMinor ) throws SAMException, IOException + { + this ( s, verMajor, verMinor, new Properties() ); + } + + /** + * Create a new SAM version 3 handler. This constructor expects + * that the SAM HELLO message has been still answered (and + * stripped) from the socket input stream. + * + * @param s Socket attached to a SAM client + * @param verMajor SAM major version to manage (should be 3) + * @param verMinor SAM minor version to manage + * @param i2cpProps properties to configure the I2CP connection (host, port, etc) + */ + + public SAMv3Handler ( SocketChannel s, int verMajor, int verMinor, Properties i2cpProps ) throws SAMException, IOException + { + super ( s, verMajor, verMinor, i2cpProps ); + _log.debug("SAM version 3 handler instantiated"); + } + + public boolean verifVersion() + { + return (verMajor == 3 && verMinor == 0) ; + } + + static public class DatagramServer { + + private static DatagramServer _instance = null ; + private static DatagramChannel server = null ; + + public static DatagramServer getInstance() throws IOException { + return getInstance(new Properties()); + } + + public static DatagramServer getInstance(Properties props) throws IOException { + if (_instance==null) { + _instance = new DatagramServer(props); + } + return _instance ; + } + + public DatagramServer(Properties props) throws IOException { + if (server==null) { + server = DatagramChannel.open(); + } + + String host = props.getProperty(SAMBridge.PROP_DATAGRAM_HOST, SAMBridge.DEFAULT_DATAGRAM_HOST); + String portStr = props.getProperty(SAMBridge.PROP_DATAGRAM_PORT, SAMBridge.DEFAULT_DATAGRAM_PORT); + int port ; + try { + port = Integer.parseInt(portStr); + } catch (NumberFormatException e) { + port = Integer.parseInt(SAMBridge.DEFAULT_DATAGRAM_PORT); + } + + server.socket().bind(new InetSocketAddress(host, port)); + new I2PAppThread(new Listener(server), "DatagramListener").start(); + } + + public void send(SocketAddress addr, ByteBuffer msg) throws IOException { + server.send(msg, addr); + } + + class Listener implements Runnable { + + DatagramChannel server = null; + + public Listener(DatagramChannel server) + { + this.server = server ; + } + public void run() + { + ByteBuffer inBuf = ByteBuffer.allocateDirect(SAMRawSession.RAW_SIZE_MAX+1024); + + while (!Thread.interrupted()) + { + inBuf.clear(); + try { + server.receive(inBuf); + } catch (IOException e) { + break ; + } + inBuf.flip(); + ByteBuffer outBuf = ByteBuffer.wrap(new byte[inBuf.remaining()]); + outBuf.put(inBuf); + outBuf.flip(); + new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start(); + } + } + } + } + + public static class MessageDispatcher implements Runnable + { + ByteArrayInputStream is = null ; + + public MessageDispatcher(byte[] buf) + { + this.is = new java.io.ByteArrayInputStream(buf) ; + } + + public void run() { + String header = null ; + String nick ; + String dest ; + String version ; + + try { + header = DataHelper.readLine(is).trim(); + StringTokenizer tok = new StringTokenizer(header, " "); + if (tok.countTokens() != 3) { + // This is not a correct message, for sure + _log.debug("Error in message format"); + return; + } + version = tok.nextToken(); + if (!"3.0".equals(version)) return ; + nick = tok.nextToken(); + dest = tok.nextToken(); + + byte[] data = new byte[is.available()]; + is.read(data); + SessionRecord rec = sSessionsHash.get(nick); + if (rec!=null) { + rec.getHandler().session.sendBytes(dest,data); + } + } catch (Exception e) {} + } + } + + public class SessionRecord + { + protected String m_dest ; + protected Properties m_props ; + protected ThreadGroup m_threadgroup ; + protected SAMv3Handler m_handler ; + + public SessionRecord( String dest, Properties props, SAMv3Handler handler ) + { + m_dest = new String(dest) ; + m_props = new Properties() ; + m_props.putAll(props); + m_threadgroup = null ; + m_handler = handler ; + } + + public SessionRecord( SessionRecord in ) + { + m_dest = in.getDest(); + m_props = in.getProps(); + m_threadgroup = in.getThreadGroup(); + m_handler = in.getHandler(); + } + + synchronized public String getDest() + { + return new String(m_dest) ; + } + synchronized public Properties getProps() + { + Properties p = new Properties(); + p.putAll(m_props); + return m_props; + } + synchronized public SAMv3Handler getHandler() + { + return m_handler ; + } + synchronized public ThreadGroup getThreadGroup() + { + return m_threadgroup ; + } + synchronized public void createThreadGroup(String name) + { + if (m_threadgroup == null) + m_threadgroup = new ThreadGroup(name); + } + } + + public static class SessionsDB + { + static final long serialVersionUID = 0x1 ; + + class ExistingId extends Exception { + static final long serialVersionUID = 0x1 ; + } + class ExistingDest extends Exception { + static final long serialVersionUID = 0x1 ; + } + + HashMap<String, SessionRecord> map ; + + public SessionsDB() { + map = new HashMap<String, SessionRecord>() ; + } + + synchronized public boolean put( String nick, SessionRecord session ) throws ExistingId, ExistingDest + { + if ( map.containsKey(nick) ) { + throw new ExistingId(); + } + for ( SessionRecord r : map.values() ) { + if (r.getDest().equals(session.getDest())) { + throw new ExistingDest(); + } + } + + if ( !map.containsKey(nick) ) { + session.createThreadGroup("SAM session "+nick); + map.put(nick, session) ; + return true ; + } + else + return false ; + } + synchronized public boolean del( String nick ) + { + SessionRecord rec = map.get(nick); + + if ( rec!=null ) { + map.remove(nick); + return true ; + } + else + return false ; + } + synchronized public SessionRecord get(String nick) + { + return map.get(nick); + } + synchronized public boolean containsKey( String nick ) + { + return map.containsKey(nick); + } + } + + public static SessionsDB sSessionsHash = new SessionsDB() ; + + public String getClientIP() + { + return this.socket.socket().getInetAddress().getHostAddress(); + } + + boolean stolenSocket = false ; + + boolean streamForwardingSocket = false ; + + public void stealSocket() + { + stolenSocket = true ; + this.stopHandling(); + } + + public void handle() { + String msg = null; + String domain = null; + String opcode = null; + boolean canContinue = false; + StringTokenizer tok; + Properties props; + + this.thread.setName("SAMv3Handler " + _id); + _log.debug("SAM handling started"); + + try { + InputStream in = getClientSocket().socket().getInputStream(); + + while (true) { + if (shouldStop()) { + _log.debug("Stop request found"); + break; + } + String line = DataHelper.readLine(in) ; + if (line==null) { + _log.debug("Connection closed by client (line read : null)"); + break; + } + msg = line.trim(); + + if (_log.shouldLog(Log.DEBUG)) { + _log.debug("New message received: [" + msg + "]"); + } + + if(msg.equals("")) { + _log.debug("Ignoring newline"); + continue; + } + + tok = new StringTokenizer(msg, " "); + if (tok.countTokens() < 2) { + // This is not a correct message, for sure + _log.debug("Error in message format"); + break; + } + domain = tok.nextToken(); + opcode = tok.nextToken(); + if (_log.shouldLog(Log.DEBUG)) { + _log.debug("Parsing (domain: \"" + domain + + "\"; opcode: \"" + opcode + "\")"); + } + props = SAMUtils.parseParams(tok); + + if (domain.equals("STREAM")) { + canContinue = execStreamMessage(opcode, props); + } else if (domain.equals("SESSION")) { + if (i2cpProps != null) + props.putAll(i2cpProps); // make sure we've got the i2cp settings + canContinue = execSessionMessage(opcode, props); + } else if (domain.equals("DEST")) { + canContinue = execDestMessage(opcode, props); + } else if (domain.equals("NAMING")) { + canContinue = execNamingMessage(opcode, props); + } else if (domain.equals("DATAGRAM")) { + canContinue = execDatagramMessage(opcode, props); + } else { + _log.debug("Unrecognized message domain: \"" + + domain + "\""); + break; + } + + if (!canContinue) { + break; + } + } + } catch (IOException e) { + _log.debug("Caught IOException (" + + e.getMessage() + ") for message [" + msg + "]", e); + } catch (Exception e) { + _log.error("Unexpected exception for message [" + msg + "]", e); + } finally { + _log.debug("Stopping handler"); + + if (!this.stolenSocket) + { + try { + closeClientSocket(); + } catch (IOException e) { + _log.error("Error closing socket: " + e.getMessage()); + } + } + if (streamForwardingSocket) + { + if (this.getStreamSession()!=null) { + try { + this.streamSession.stopForwardingIncoming(); + } catch (SAMException e) { + _log.error("Error while stopping forwarding connections: " + e.getMessage()); + } catch (InterruptedIOException e) { + _log.error("Interrupted while stopping forwarding connections: " + e.getMessage()); + } + } + } + + + + die(); + } + } + + protected void die() { + SessionRecord rec = null ; + + if (session!=null) { + session.close(); + rec = sSessionsHash.get(session.getNick()); + } + if (rec!=null) { + rec.getThreadGroup().interrupt() ; + while (rec.getThreadGroup().activeCount()>0) + try { + Thread.sleep(1000); + } catch ( InterruptedException e) {} + rec.getThreadGroup().destroy(); + sSessionsHash.del(session.getNick()); + } + } + + /* Parse and execute a SESSION message */ + @Override + protected boolean execSessionMessage(String opcode, Properties props) { + + String dest = "BUG!"; + String nick = null ; + boolean ok = false ; + + try{ + if (opcode.equals("CREATE")) { + if ((this.getRawSession()!= null) || (this.getDatagramSession() != null) + || (this.getStreamSession() != null)) { + _log.debug("Trying to create a session, but one still exists"); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n"); + } + if (props == null) { + _log.debug("No parameters specified in SESSION CREATE message"); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No parameters for SESSION CREATE\"\n"); + } + + dest = props.getProperty("DESTINATION"); + if (dest == null) { + _log.debug("SESSION DESTINATION parameter not specified"); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"DESTINATION not specified\"\n"); + } + props.remove("DESTINATION"); + + + if (dest.equals("TRANSIENT")) { + _log.debug("TRANSIENT destination requested"); + ByteArrayOutputStream priv = new ByteArrayOutputStream(640); + SAMUtils.genRandomKey(priv, null); + + dest = Base64.encode(priv.toByteArray()); + } else { + _log.debug("Custom destination specified [" + dest + "]"); + } + + try { + SAMUtils.checkPrivateDestination(dest); + } catch ( SAMUtils.InvalidDestination e ) { + return writeString("SESSION STATUS RESULT=INVALID_KEY\n"); + } + + nick = props.getProperty("ID"); + if (nick == null) { + _log.debug("SESSION ID parameter not specified"); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"ID not specified\"\n"); + } + props.remove("ID"); + + + String style = props.getProperty("STYLE"); + if (style == null) { + _log.debug("SESSION STYLE parameter not specified"); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No SESSION STYLE specified\"\n"); + } + props.remove("STYLE"); + + + + // Record the session in the database sSessionsHash + Properties allProps = new Properties(); + allProps.putAll(i2cpProps); + allProps.putAll(props); + + + try { + sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ; + } catch (SessionsDB.ExistingId e) { + _log.debug("SESSION ID parameter already in use"); + return writeString("SESSION STATUS RESULT=DUPLICATED_ID\n"); + } catch (SessionsDB.ExistingDest e) { + return writeString("SESSION STATUS RESULT=DUPLICATED_DEST\n"); + } + + + // Create the session + + if (style.equals("RAW")) { + DatagramServer.getInstance(i2cpProps); + rawSession = newSAMRawSession(nick); + this.session = rawSession ; + } else if (style.equals("DATAGRAM")) { + DatagramServer.getInstance(i2cpProps); + datagramSession = newSAMDatagramSession(nick); + this.session = datagramSession ; + } else if (style.equals("STREAM")) { + streamSession = newSAMStreamSession(nick); + this.session = streamSession ; + } else { + _log.debug("Unrecognized SESSION STYLE: \"" + style +"\""); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized SESSION STYLE\"\n"); + } + ok = true ; + return writeString("SESSION STATUS RESULT=OK DESTINATION=" + + dest + "\n"); + } else { + _log.debug("Unrecognized SESSION message opcode: \"" + + opcode + "\""); + return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized opcode\"\n"); + } + } catch (DataFormatException e) { + _log.debug("Invalid destination specified"); + return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); + } catch (I2PSessionException e) { + _log.debug("I2P error when instantiating session", e); + return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); + } catch (SAMException e) { + _log.error("Unexpected SAM error", e); + return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); + } catch (IOException e) { + _log.error("Unexpected IOException", e); + return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n"); + } finally { + // unregister the session if it has not been created + if ( !ok && nick!=null ) { + sSessionsHash.del(nick) ; + session = null ; + } + } + } + + SAMv3StreamSession newSAMStreamSession(String login ) + throws IOException, DataFormatException, SAMException + { + return new SAMv3StreamSession( login ) ; + } + + SAMv3RawSession newSAMRawSession(String login ) + throws IOException, DataFormatException, SAMException, I2PSessionException + { + return new SAMv3RawSession( login ) ; + } + + SAMv3DatagramSession newSAMDatagramSession(String login ) + throws IOException, DataFormatException, SAMException, I2PSessionException + { + return new SAMv3DatagramSession( login ) ; + } + + /* Parse and execute a STREAM message */ + protected boolean execStreamMessage ( String opcode, Properties props ) + { + String nick = null ; + SessionRecord rec = null ; + + if ( session != null ) + { + _log.error ( "STREAM message received, but this session is a master session" ); + + try { + notifyStreamResult(true, "I2P_ERROR", "master session cannot be used for streams"); + } catch (IOException e) {} + return false; + } + + nick = props.getProperty("ID"); + if (nick == null) { + _log.debug("SESSION ID parameter not specified"); + try { + notifyStreamResult(true, "I2P_ERROR", "ID not specified"); + } catch (IOException e) {} + return false ; + } + props.remove("ID"); + + rec = sSessionsHash.get(nick); + + if ( rec==null ) { + _log.debug("STREAM SESSION ID does not exist"); + try { + notifyStreamResult(true, "INVALID_ID", "STREAM SESSION ID does not exist"); + } catch (IOException e) {} + return false ; + } + + streamSession = rec.getHandler().streamSession ; + + if (streamSession==null) { + _log.debug("specified ID is not a stream session"); + try { + notifyStreamResult(true, "I2P_ERROR", "specified ID is not a STREAM session"); + } catch (IOException e) {} + return false ; + } + + if ( opcode.equals ( "CONNECT" ) ) + { + return execStreamConnect ( props ); + } + else if ( opcode.equals ( "ACCEPT" ) ) + { + return execStreamAccept ( props ); + } + else if ( opcode.equals ( "FORWARD") ) + { + return execStreamForwardIncoming( props ); + } + else + { + _log.debug ( "Unrecognized RAW message opcode: \"" + + opcode + "\"" ); + try { + notifyStreamResult(true, "I2P_ERROR", "Unrecognized RAW message opcode: "+opcode ); + } catch (IOException e) {} + return false; + } + } + + + protected boolean execStreamConnect( Properties props) { + try { + if (props == null) { + notifyStreamResult(true,"I2P_ERROR","No parameters specified in STREAM CONNECT message"); + _log.debug("No parameters specified in STREAM CONNECT message"); + return false; + } + boolean verbose = props.getProperty("SILENT","false").equals("false"); + + String dest = props.getProperty("DESTINATION"); + if (dest == null) { + notifyStreamResult(verbose, "I2P_ERROR", "Destination not specified in RAW SEND message"); + _log.debug("Destination not specified in RAW SEND message"); + return false; + } + props.remove("DESTINATION"); + + try { + streamSession.connect( this, dest, props ); + return true ; + } catch (DataFormatException e) { + _log.debug("Invalid destination in STREAM CONNECT message"); + notifyStreamResult ( verbose, "INVALID_KEY", null ); + } catch (ConnectException e) { + _log.debug("STREAM CONNECT failed: " + e.getMessage()); + notifyStreamResult ( verbose, "CONNECTION_REFUSED", null ); + } catch (NoRouteToHostException e) { + _log.debug("STREAM CONNECT failed: " + e.getMessage()); + notifyStreamResult ( verbose, "CANT_REACH_PEER", null ); + } catch (InterruptedIOException e) { + _log.debug("STREAM CONNECT failed: " + e.getMessage()); + notifyStreamResult ( verbose, "TIMEOUT", null ); + } catch (I2PException e) { + _log.debug("STREAM CONNECT failed: " + e.getMessage()); + notifyStreamResult ( verbose, "I2P_ERROR", e.getMessage() ); + } + } catch (IOException e) { + } + return false ; + } + + protected boolean execStreamForwardIncoming( Properties props ) { + try { + try { + streamForwardingSocket = true ; + streamSession.startForwardingIncoming(props); + notifyStreamResult( true, "OK", null ); + return true ; + } catch (SAMException e) { + _log.debug("Forwarding STREAM connections failed: " + e.getMessage()); + notifyStreamResult ( true, "I2P_ERROR", "Forwarding failed : " + e.getMessage() ); + } + } catch (IOException e) { + } + return false ; + } + + protected boolean execStreamAccept( Properties props ) + { + boolean verbose = props.getProperty( "SILENT", "false").equals("false"); + try { + try { + notifyStreamResult(verbose, "OK", null); + streamSession.accept(this, verbose); + return true ; + } catch (InterruptedIOException e) { + _log.debug("STREAM ACCEPT failed: " + e.getMessage()); + notifyStreamResult( verbose, "TIMEOUT", e.getMessage() ); + } catch (I2PException e) { + _log.debug("STREAM ACCEPT failed: " + e.getMessage()); + notifyStreamResult ( verbose, "I2P_ERROR", e.getMessage() ); + } catch (SAMException e) { + _log.debug("STREAM ACCEPT failed: " + e.getMessage()); + notifyStreamResult ( verbose, "ALREADY_ACCEPTING", null ); + } + } catch (IOException e) { + } + return false ; + } + + + public void notifyStreamResult(boolean verbose, String result, String message) throws IOException + { + if (!verbose) return ; + + String out = "STREAM STATUS RESULT="+result; + if (message!=null) + out = out + " MESSAGE=\"" + message + "\""; + out = out + '\n'; + + if ( !writeString ( out ) ) + { + throw new IOException ( "Error notifying connection to SAM client" ); + } + } + + public void notifyStreamIncomingConnection(Destination d) throws IOException { + if (getStreamSession() == null) { + _log.error("BUG! Received stream connection, but session is null!"); + throw new NullPointerException("BUG! STREAM session is null!"); + } + + if (!writeString(d.toBase64() + "\n")) { + throw new IOException("Error notifying connection to SAM client"); + } + } + + public static void notifyStreamIncomingConnection(SocketChannel client, Destination d) throws IOException { + if (!writeString(d.toBase64() + "\n", client)) { + throw new IOException("Error notifying connection to SAM client"); + } + } + +} + diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java new file mode 100644 index 0000000000000000000000000000000000000000..3695bf3ddaf8294f85841f4ff4c3bef2bab650e0 --- /dev/null +++ b/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java @@ -0,0 +1,90 @@ +/** + * + */ +package net.i2p.sam; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.Properties; + +import net.i2p.client.I2PSessionException; +import net.i2p.data.DataFormatException; +import net.i2p.util.Log; + +/** + * @author MKVore + * + */ +public class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Session, SAMRawReceiver { + + String nick = null ; + SAMv3Handler handler = null ; + SAMv3Handler.DatagramServer server ; + private final static Log _log = new Log ( SAMv3DatagramSession.class ); + SocketAddress clientAddress = null ; + + public String getNick() { return nick; } + + /** + * Build a Raw Datagram Session according to information + * registered with the given nickname + * + * @param nick nickname of the session + * @throws IOException + * @throws DataFormatException + * @throws I2PSessionException + */ + public SAMv3RawSession(String nick) + throws IOException, DataFormatException, I2PSessionException { + + super(SAMv3Handler.sSessionsHash.get(nick).getDest(), + SAMv3Handler.sSessionsHash.get(nick).getProps(), + SAMv3Handler.sSessionsHash.get(nick).getHandler() + ); + this.nick = nick ; + this.recv = this ; + this.server = SAMv3Handler.DatagramServer.getInstance() ; + + SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); + if ( rec==null ) throw new InterruptedIOException() ; + + this.handler = rec.getHandler(); + + Properties props = rec.getProps(); + + + String portStr = props.getProperty("PORT") ; + if ( portStr==null ) { + _log.debug("receiver port not specified. Current socket will be used."); + } + else { + int port = Integer.parseInt(portStr); + + String host = props.getProperty("HOST"); + if ( host==null ) { + host = rec.getHandler().getClientIP(); + + _log.debug("no host specified. Taken from the client socket : " + host +':'+port); + } + + + this.clientAddress = new InetSocketAddress(host,port); + } + } + + public void receiveRawBytes(byte[] data) throws IOException { + if (this.clientAddress==null) { + this.handler.receiveRawBytes(data); + } else { + ByteBuffer msgBuf = ByteBuffer.allocate(data.length); + msgBuf.put(data); + msgBuf.flip(); + this.server.send(this.clientAddress, msgBuf); + } + } + + public void stopRawReceiving() {} +} diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java new file mode 100644 index 0000000000000000000000000000000000000000..26d99fa014eb04dcd25a341770e01e9fd5327cb2 --- /dev/null +++ b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java @@ -0,0 +1,408 @@ +package net.i2p.sam; +/* + * free (adj.): unencumbered; not under the control of others + * Written by human in 2004 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.ConnectException; +import java.net.NoRouteToHostException; +import java.util.Properties; + +import net.i2p.I2PException; +import net.i2p.client.I2PClient; +import net.i2p.client.streaming.I2PServerSocket; +import net.i2p.client.streaming.I2PSocket; +import net.i2p.client.streaming.I2PSocketManagerFactory; +import net.i2p.client.streaming.I2PSocketOptions; +import net.i2p.data.Base64; +import net.i2p.data.DataFormatException; +import net.i2p.data.Destination; +import net.i2p.util.I2PAppThread; +import net.i2p.util.Log; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.ByteBuffer ; +import java.nio.channels.SocketChannel; + +/** + * SAMv3 STREAM session class. + * + * @author mkvore + */ + +public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Session +{ + + private final static Log _log = new Log ( SAMv3StreamSession.class ); + + protected final int BUFFER_SIZE = 1024 ; + + protected Object socketServerLock = new Object(); + protected I2PServerSocket socketServer = null; + + protected String nick ; + + public String getNick() { + return nick ; + } + + /** + * Create a new SAM STREAM session, according to information + * registered with the given nickname + * + * @param login The nickname + * @throws IOException + * @throws DataFormatException + * @throws SAMException + */ + public SAMv3StreamSession(String login) + throws IOException, DataFormatException, SAMException + { + initSAMStreamSession(login); + } + + public static SAMv3Handler.SessionsDB getDB() + { + return SAMv3Handler.sSessionsHash ; + } + + private void initSAMStreamSession(String login) + throws IOException, DataFormatException, SAMException { + + SAMv3Handler.SessionRecord rec = getDB().get(login); + String dest = rec.getDest() ; + ByteArrayInputStream ba_dest = new ByteArrayInputStream(Base64.decode(dest)); + + this.recv = rec.getHandler(); + + _log.debug("SAM STREAM session instantiated"); + + Properties allprops = new Properties(); + allprops.putAll(System.getProperties()); + allprops.putAll(rec.getProps()); + + String i2cpHost = allprops.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1"); + int i2cpPort ; + String port = allprops.getProperty(I2PClient.PROP_TCP_PORT, "7654"); + try { + i2cpPort = Integer.parseInt(port); + } catch (NumberFormatException nfe) { + throw new SAMException("Invalid I2CP port specified [" + port + "]"); + } + + _log.debug("Creating I2PSocketManager..."); + socketMgr = I2PSocketManagerFactory.createManager(ba_dest, + i2cpHost, + i2cpPort, + allprops); + if (socketMgr == null) { + throw new SAMException("Error creating I2PSocketManager towards "+i2cpHost+":"+i2cpPort); + } + + socketMgr.addDisconnectListener(new DisconnectListener()); + this.nick = login ; + } + + /** + * Connect the SAM STREAM session to the specified Destination + * + * @param handler The handler that communicates with the requesting client + * @param dest Base64-encoded Destination to connect to + * @param props Options to be used for connection + * + * @throws DataFormatException if the destination is not valid + * @throws ConnectException if the destination refuses connections + * @throws NoRouteToHostException if the destination can't be reached + * @throws InterruptedIOException if the connection timeouts + * @throws I2PException if there's another I2P-related error + * @throws IOException + */ + public void connect ( SAMv3Handler handler, String dest, Properties props ) + throws I2PException, ConnectException, NoRouteToHostException, + DataFormatException, InterruptedIOException, IOException { + + boolean verbose = (props.getProperty("SILENT", "false").equals("false")); + Destination d = SAMUtils.getDest(dest); + + I2PSocketOptions opts = socketMgr.buildOptions(props); + if (props.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null) + opts.setConnectTimeout(60 * 1000); + + _log.debug("Connecting new I2PSocket..."); + + // blocking connection (SAMv3) + + I2PSocket i2ps = socketMgr.connect(d, opts); + + SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); + + if ( rec==null ) throw new InterruptedIOException() ; + + handler.notifyStreamResult(verbose, "OK", null) ; + + handler.stealSocket() ; + + ReadableByteChannel fromClient = handler.getClientSocket(); + ReadableByteChannel fromI2P = Channels.newChannel(i2ps.getInputStream()); + WritableByteChannel toClient = handler.getClientSocket(); + WritableByteChannel toI2P = Channels.newChannel(i2ps.getOutputStream()); + + (new Thread(rec.getThreadGroup(), new I2PAppThread(new Pipe(fromClient,toI2P, "SAMPipeClientToI2P"), "SAMPipeClientToI2P"), "SAMPipeClientToI2P")).start(); + (new Thread(rec.getThreadGroup(), new I2PAppThread(new Pipe(fromI2P,toClient, "SAMPipeI2PToClient"), "SAMPipeI2PToClient"), "SAMPipeI2PToClient")).start(); + + } + + /** + * Accept an incoming STREAM + * + * @param handler The handler that communicates with the requesting client + * @param verbose If true, SAM will send the Base64-encoded peer Destination of an + * incoming socket as the first line of data sent to its client + * on the handler socket + * + * @throws DataFormatException if the destination is not valid + * @throws ConnectException if the destination refuses connections + * @throws NoRouteToHostException if the destination can't be reached + * @throws InterruptedIOException if the connection timeouts + * @throws I2PException if there's another I2P-related error + * @throws IOException + */ + public void accept(SAMv3Handler handler, boolean verbose) + throws I2PException, InterruptedIOException, IOException, SAMException { + + synchronized( this.socketServerLock ) + { + if (this.socketServer!=null) { + _log.debug("a socket server is already defined for this destination"); + throw new SAMException("a socket server is already defined for this destination"); + } + this.socketServer = this.socketMgr.getServerSocket(); + } + + I2PSocket i2ps; + i2ps = this.socketServer.accept(); + + synchronized( this.socketServerLock ) + { + this.socketServer = null ; + } + + SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); + + if ( rec==null ) throw new InterruptedIOException() ; + + if (verbose) + handler.notifyStreamIncomingConnection(i2ps.getPeerDestination()) ; + + handler.stealSocket() ; + ReadableByteChannel fromClient = handler.getClientSocket(); + ReadableByteChannel fromI2P = Channels.newChannel(i2ps.getInputStream()); + WritableByteChannel toClient = handler.getClientSocket(); + WritableByteChannel toI2P = Channels.newChannel(i2ps.getOutputStream()); + + (new Thread(rec.getThreadGroup(), new I2PAppThread(new Pipe(fromClient,toI2P, "SAMPipeClientToI2P"), "SAMPipeClientToI2P"), "SAMPipeClientToI2P")).start(); + (new Thread(rec.getThreadGroup(), new I2PAppThread(new Pipe(fromI2P,toClient, "SAMPipeI2PToClient"), "SAMPipeI2PToClient"), "SAMPipeI2PToClient")).start(); + } + + + public void startForwardingIncoming( Properties props ) throws SAMException, InterruptedIOException + { + SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); + boolean verbose = props.getProperty("SILENT", "false").equals("false"); + + if ( rec==null ) throw new InterruptedIOException() ; + + String portStr = props.getProperty("PORT") ; + if ( portStr==null ) { + _log.debug("receiver port not specified"); + throw new SAMException("receiver port not specified"); + } + int port = Integer.parseInt(portStr); + + String host = props.getProperty("HOST"); + if ( host==null ) { + host = rec.getHandler().getClientIP(); + _log.debug("no host specified. Taken from the client socket : " + host +':'+port); + } + + + synchronized( this.socketServerLock ) + { + if (this.socketServer!=null) { + _log.debug("a socket server is already defined for this destination"); + throw new SAMException("a socket server is already defined for this destination"); + } + this.socketServer = this.socketMgr.getServerSocket(); + } + + SocketForwarder forwarder = new SocketForwarder(host, port, this, verbose); + (new Thread(rec.getThreadGroup(), new I2PAppThread(forwarder, "SAMStreamForwarder"), "SAMStreamForwarder")).start(); + } + + public class SocketForwarder extends Thread + { + String host = null ; + int port = 0 ; + SAMv3StreamSession session; + boolean verbose; + + SocketForwarder(String host, int port, SAMv3StreamSession session, boolean verbose) { + this.host = host ; + this.port = port ; + this.session = session ; + this.verbose = verbose ; + } + + public void run() + { + while (session.getSocketServer()!=null) { + + // wait and accept a connection from I2P side + I2PSocket i2ps = null ; + try { + i2ps = session.getSocketServer().accept(); + } catch (Exception e) {} + + if (i2ps==null) { + continue ; + } + + // open a socket towards client + java.net.InetSocketAddress addr = new java.net.InetSocketAddress(host,port); + + SocketChannel clientServerSock = null ; + try { + clientServerSock = SocketChannel.open(addr) ; + } + catch ( IOException e ) { + continue ; + } + if (clientServerSock==null) { + try { + i2ps.close(); + } catch (IOException ee) {} + continue ; + } + + // build pipes between both sockets + try { + if (this.verbose) + SAMv3Handler.notifyStreamIncomingConnection( + clientServerSock, i2ps.getPeerDestination()); + ReadableByteChannel fromClient = clientServerSock ; + ReadableByteChannel fromI2P = Channels.newChannel(i2ps.getInputStream()); + WritableByteChannel toClient = clientServerSock ; + WritableByteChannel toI2P = Channels.newChannel(i2ps.getOutputStream()); + (new I2PAppThread(new Pipe(fromClient,toI2P, "SAMPipeClientToI2P"), "SAMPipeClientToI2P")).start(); + (new I2PAppThread(new Pipe(fromI2P,toClient, "SAMPipeI2PToClient"), "SAMPipeI2PToClient")).start(); + + } catch (IOException e) { + try { + clientServerSock.close(); + } catch (IOException ee) {} + try { + i2ps.close(); + } catch (IOException ee) {} + continue ; + } + } + } + } + public class Pipe extends Thread + { + ReadableByteChannel in ; + WritableByteChannel out ; + ByteBuffer buf ; + + public Pipe(ReadableByteChannel in, WritableByteChannel out, String name) + { + super(name); + this.in = in ; + this.out = out ; + this.buf = ByteBuffer.allocate(BUFFER_SIZE) ; + } + + public void run() + { + try { + while (!Thread.interrupted() && (in.read(buf)>=0 || buf.position() != 0)) { + buf.flip(); + out.write(buf); + buf.compact(); + } + } + catch (IOException e) + { + this.interrupt(); + } + try { + in.close(); + } + catch (IOException e) {} + try { + buf.flip(); + while (buf.hasRemaining()) + out.write(buf); + } + catch (IOException e) {} + try { + out.close(); + } + catch (IOException e) {} + } + } + + public I2PServerSocket getSocketServer() + { + synchronized ( this.socketServerLock ) { + return this.socketServer ; + } + } + /** + * stop Forwarding Incoming connection coming from I2P + * @throws SAMException + * @throws InterruptedIOException + */ + public void stopForwardingIncoming() throws SAMException, InterruptedIOException + { + SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); + + if ( rec==null ) throw new InterruptedIOException() ; + + I2PServerSocket server = null ; + synchronized( this.socketServerLock ) + { + if (this.socketServer==null) { + _log.debug("no socket server is defined for this destination"); + throw new SAMException("no socket server is defined for this destination"); + } + server = this.socketServer ; + this.socketServer = null ; + _log.debug("nulling socketServer in stopForwardingIncoming. Object " + this ); + } + try { + server.close(); + } catch ( I2PException e) {} + } + + /** + * Close the stream session + */ + @Override + public void close() { + socketMgr.destroySocketManager(); + } + + public boolean sendBytes(String s, byte[] b) throws DataFormatException + { + throw new DataFormatException(null); + } +} diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMEventHandler.java b/apps/sam/java/src/net/i2p/sam/client/SAMEventHandler.java index 7df1a23242eb95c411cad13033c4d580bcc5777f..9df867aa5542f915d190c2fc5fd4404d38dbab00 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMEventHandler.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMEventHandler.java @@ -12,17 +12,17 @@ import net.i2p.util.Log; * */ public class SAMEventHandler extends SAMClientEventListenerImpl { - private I2PAppContext _context; + //private I2PAppContext _context; private Log _log; private Boolean _helloOk; private Object _helloLock = new Object(); private Boolean _sessionCreateOk; private Object _sessionCreateLock = new Object(); private Object _namingReplyLock = new Object(); - private Map _namingReplies = new HashMap(); + private Map<String,String> _namingReplies = new HashMap<String,String>(); public SAMEventHandler(I2PAppContext ctx) { - _context = ctx; + //_context = ctx; _log = ctx.logManager().getLog(getClass()); } diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java index 4e9d1133b063ed52e47c27b1d9143476718add2b..80db744a3167468fbf0e6e516685092ad963a5ab 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java @@ -31,10 +31,10 @@ public class SAMStreamSend { private OutputStream _samOut; private InputStream _samIn; private SAMReader _reader; - private boolean _dead; + //private boolean _dead; private SAMEventHandler _eventHandler; /** Connection id (Integer) to peer (Flooder) */ - private Map _remotePeers; + private Map<Integer, Sender> _remotePeers; public static void main(String args[]) { if (args.length < 4) { @@ -42,7 +42,7 @@ public class SAMStreamSend { return; } I2PAppContext ctx = new I2PAppContext(); - String files[] = new String[args.length - 3]; + //String files[] = new String[args.length - 3]; SAMStreamSend sender = new SAMStreamSend(ctx, args[0], args[1], args[2], args[3]); sender.startup(); } @@ -50,14 +50,14 @@ public class SAMStreamSend { public SAMStreamSend(I2PAppContext ctx, String samHost, String samPort, String destFile, String dataFile) { _context = ctx; _log = ctx.logManager().getLog(SAMStreamSend.class); - _dead = false; + //_dead = false; _samHost = samHost; _samPort = samPort; _destFile = destFile; _dataFile = dataFile; _conOptions = ""; _eventHandler = new SendEventHandler(_context); - _remotePeers = new HashMap(); + _remotePeers = new HashMap<Integer,Sender>(); } public void startup() { @@ -207,7 +207,6 @@ public class SAMStreamSend { _started = _context.clock().now(); _context.statManager().addRateData("send." + _connectionId + ".started", 1, 0); byte data[] = new byte[1024]; - long value = 0; long lastSend = _context.clock().now(); while (!_closed) { try { diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java index 8d29e37994136d5698e07ffb11fa0fd688ec489a..406150b367596fc451836b509220dc078812818d 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java @@ -31,10 +31,10 @@ public class SAMStreamSink { private OutputStream _samOut; private InputStream _samIn; private SAMReader _reader; - private boolean _dead; + //private boolean _dead; private SAMEventHandler _eventHandler; /** Connection id (Integer) to peer (Flooder) */ - private Map _remotePeers; + private Map<Integer, Sink> _remotePeers; public static void main(String args[]) { if (args.length < 4) { @@ -49,14 +49,14 @@ public class SAMStreamSink { public SAMStreamSink(I2PAppContext ctx, String samHost, String samPort, String destFile, String sinkDir) { _context = ctx; _log = ctx.logManager().getLog(SAMStreamSink.class); - _dead = false; + //_dead = false; _samHost = samHost; _samPort = samPort; _destFile = destFile; _sinkDir = sinkDir; _conOptions = ""; _eventHandler = new SinkEventHandler(_context); - _remotePeers = new HashMap(); + _remotePeers = new HashMap<Integer,Sink>(); } public void startup() { @@ -70,7 +70,8 @@ public class SAMStreamSink { String ourDest = handshake(); _log.debug("Handshake complete. we are " + ourDest); if (ourDest != null) { - boolean written = writeDest(ourDest); + //boolean written = + writeDest(ourDest); _log.debug("Dest written"); } } diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java index 2d198ad66e75bc4af62fa1aa24fe7b2ab293dd60..30d849ba4411de595c149ebaaf12e56b2bf4820a 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java @@ -2,8 +2,6 @@ package net.i2p.client.streaming; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.ArrayList; -import java.util.List; import net.i2p.I2PAppContext; import net.i2p.util.Log; @@ -41,7 +39,7 @@ class ConnectionHandler { _context = context; _log = context.logManager().getLog(ConnectionHandler.class); _manager = mgr; - _synQueue = new LinkedBlockingQueue(MAX_QUEUE_SIZE); + _synQueue = new LinkedBlockingQueue<Packet>(MAX_QUEUE_SIZE); _active = false; _acceptTimeout = DEFAULT_ACCEPT_TIMEOUT; } @@ -126,7 +124,7 @@ class ConnectionHandler { if (timeoutMs <= 0) { try { syn = _synQueue.take(); // waits forever - } catch (InterruptedException ie) { break;} + } catch (InterruptedException ie) { } // { break;} } else { long remaining = expiration - _context.clock().now(); // (dont think this applies anymore for LinkedBlockingQueue) diff --git a/apps/streaming/java/src/net/i2p/client/streaming/MessageHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/MessageHandler.java index 75adf6e593bc5d4dbbb77983c1202146fbc6dc89..1ff65248ddd27c623ae3770435eea4cbc5968d99 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/MessageHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/MessageHandler.java @@ -73,8 +73,8 @@ public class MessageHandler implements I2PSessionListener { * @param session that has been terminated */ public void disconnected(I2PSession session) { - if (_log.shouldLog(Log.ERROR)) - _log.error("I2PSession disconnected"); + if (_log.shouldLog(Log.WARN)) + _log.warn("I2PSession disconnected"); _manager.disconnectAllHard(); List listeners = null; diff --git a/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java b/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java index 197b9275412b1f8fa538c78e1a518b3b421d0de5..827be5b04fb6e035629c582a533716eae2eea625 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java @@ -213,7 +213,7 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat timeRemaining = 10*1000; wait(timeRemaining); } - } catch (InterruptedException ie) { break; } + } catch (InterruptedException ie) { }//{ break; } } if (!writeSuccessful()) releasePayload(); diff --git a/build.xml b/build.xml index 6ed84ca7342ec9807598e7c8c1773c6f3e102044..fc251a40a99bb0d477ab5bd4f74ca99487b23cd9 100644 --- a/build.xml +++ b/build.xml @@ -25,6 +25,10 @@ <echo message=" javadoc: generate javadoc for the entire project into ./build/javadoc" /> <echo message=" slackpkg: generate Slackware packages in ./Slackware/i2p and ./Slackware/i2p-base" /> <echo message=" debianhowto: instructions on building Debian packages" /> + <echo message=" updaterWithDesktopgui: tar the built files and desktopgui in an i2pupdate.zip" /> + <echo message=" pkgWithDesktopgui: distclean then package everything up with the desktopgui" /> + <echo message=" distWithDesktopgui: pkgWithDesktopgui and javadoc" /> + <echo message=" distcleanWithDesktopgui: clean up all derived files (including desktopgui files)" /> </target> <target name="debianhowto"> <echo message="To build debian packages, you must run dpkg-buildpackage as root in the source directory. It will then run ant for you. dpkg-buildpackage is found in the 'dpkg-dev' package. Also it should work fine to use the 'fakeroot' package with dpkg-buildpackage, if you don't want to run as root. Please read 'man dpkg-buildpackage' before building any packages yourself." /> diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index 9e42eef5fa3e983f083c76c0b850c9da444e9b2f..a5d8ed94de3003a0e21717c41eeb0aaac2a5160b 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -16,7 +16,6 @@ import java.net.Socket; import java.net.UnknownHostException; import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -90,7 +89,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa protected I2PAppContext _context; /** monitor for waiting until a lease set has been granted */ - private Object _leaseSetWait = new Object(); + private final Object _leaseSetWait = new Object(); /** whether the session connection has already been closed (or not yet opened) */ protected boolean _closed; @@ -101,7 +100,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** have we received the current date from the router yet? */ private boolean _dateReceived; /** lock that we wait upon, that the SetDateMessageHandler notifies */ - private Object _dateReceivedLock = new Object(); + private final Object _dateReceivedLock = new Object(); /** * thread that we tell when new messages are available who then tells us @@ -253,6 +252,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa try { if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "connect begin to " + _hostname + ":" + _portNum); _socket = new Socket(_hostname, _portNum); + // _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it. _out = _socket.getOutputStream(); synchronized (_out) { _out.write(I2PClient.PROTOCOL_BYTE); diff --git a/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java b/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java index a3e5e57a7f870087cff8648ca15e39bce4d7d3d9..58b5cae9f29005e774df26d8bb407ecd0ca86a0a 100644 --- a/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java @@ -4,18 +4,16 @@ package net.i2p.client; * public domain */ -import java.io.IOException; import java.io.InputStream; import java.util.concurrent.LinkedBlockingQueue; -import java.util.HashSet; import java.util.Properties; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.SessionKey; -import net.i2p.data.SessionTag; import net.i2p.data.i2cp.MessagePayloadMessage; import net.i2p.util.Log; import net.i2p.util.SimpleScheduler; @@ -97,6 +95,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { * 255 disallowed * @param port 1-65535 or PORT_ANY for all */ + @Override public void addSessionListener(I2PSessionListener lsnr, int proto, int port) { _demultiplexer.addListener(lsnr, proto, port); } @@ -107,11 +106,13 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { * @param proto 1-254 or 0 for all; 255 disallowed * @param port 1-65535 or 0 for all */ + @Override public void addMuxedSessionListener(I2PSessionMuxedListener l, int proto, int port) { _demultiplexer.addMuxedListener(l, proto, port); } /** removes the specified listener (only) */ + @Override public void removeListener(int proto, int port) { _demultiplexer.removeListener(proto, port); } @@ -149,6 +150,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { * @param fromPort 1-65535 or 0 for unset * @param toPort 1-65535 or 0 for unset */ + @Override public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expires, int proto, int fromPort, int toPort) @@ -198,24 +200,40 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { protected class MuxedAvailabilityNotifier extends AvailabilityNotifier { private LinkedBlockingQueue<MsgData> _msgs; - private boolean _alive; + private volatile boolean _alive = false; private static final int POISON_SIZE = -99999; - + private final AtomicBoolean stopping = new AtomicBoolean(false); + public MuxedAvailabilityNotifier() { _msgs = new LinkedBlockingQueue(); } - - public void stopNotifying() { - _msgs.clear(); - if (_alive) { - _alive = false; - try { - _msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0)); - } catch (InterruptedException ie) {} + + @Override + public void stopNotifying() { + boolean again = true; + synchronized (stopping) { + if( !stopping.getAndSet(true)) { + if (_alive == true) { + // System.out.println("I2PSessionMuxedImpl.stopNotifying()"); + _msgs.clear(); + while(again) { + try { + _msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0)); + again = false; + // System.out.println("I2PSessionMuxedImpl.stopNotifying() success."); + } catch (InterruptedException ie) { + continue; + } + } + } + _alive = false; + stopping.set(false); + } + // stopping.notifyAll(); } } - /** unused */ + @Override public void available(long msgId, int size) { throw new IllegalArgumentException("no"); } public void available(long msgId, int size, int proto, int fromPort, int toPort) { @@ -224,20 +242,24 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { } catch (InterruptedException ie) {} } + @Override public void run() { - _alive = true; - while (true) { - MsgData msg; + MsgData msg; + _alive=true; + while (_alive) { try { msg = _msgs.take(); } catch (InterruptedException ie) { + _log.debug("I2PSessionMuxedImpl.run() InterruptedException " + String.valueOf(_msgs.size()) + " Messages, Alive " + _alive); continue; } - if (msg.size == POISON_SIZE) + if (msg.size == POISON_SIZE) { + // System.out.println("I2PSessionMuxedImpl.run() POISONED"); break; + } try { - _demultiplexer.messageAvailable(I2PSessionMuxedImpl.this, msg.id, - msg.size, msg.proto, msg.fromPort, msg.toPort); + _demultiplexer.messageAvailable(I2PSessionMuxedImpl.this, + msg.id, msg.size, msg.proto, msg.fromPort, msg.toPort); } catch (Exception e) { _log.error("Error notifying app of message availability"); } diff --git a/core/java/src/net/i2p/data/i2cp/I2CPMessageReader.java b/core/java/src/net/i2p/data/i2cp/I2CPMessageReader.java index 5c79d94f3c70ca356c0e2a8918451299953fe761..461c4b08a4f9dbf25de23be53c896e406e818540 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 50315edcd199ca59741c0f48c30d5bc4525d01c7..e802d6da420f72b0376247745ecd01b812954eda 100644 --- a/history.txt +++ b/history.txt @@ -1,5 +1,135 @@ +2009-05-12 sponge + * BOB clean up, change println's to _log.warn, bump BOB version + * I2PSessionMuxedImpl.java changes as per zzz, and they test OK for me. + +2009-05-12 mkvore + * SAM: fix: warnings when generating javadoc + +2009-05-11 zzz + * Connect client: Fix NPE when used with advanced i2ptunnel features + * Context: Don't instantiate unused AdminManager + * logs.jsp: Put critical log at the top + * NetDb: Don't accept stores of our own LeaseSets or RouterInfo + +2009-05-11 mkvore + * SAM: fix: removed ERROR level logging when a client disconnects + +2009-05-09 sponge + * merge + +2009-05-09 sponge + * fixed OOM on lock (woops! my bad!) + +2009-05-08 Mathiasdm + * desktopgui: moved files to stop polluting the namespace + (everything now in net.i2p.desktopgui) + * desktopgui: some variable renaming in general configuration + +2009-05-07 mkvore + * SAM: version 3 added + * SAM: blocking case corrected on simultaneous client connection (v.1-3) + +2009-05-07 zzz + * Add nibble.i2p to proxy list and hosts.txt + +2009-05-07 zzz + * Addressbook: Name the thread + * Console: + - More IE button fixes, try harder to not refresh the iframe after shutdown + - Disable idle options for streamr client, it will never be + idle because it pings the server + * Floodfill Monitor: Slow down the volunteers + * Throttle: Throttle at 90% so we throttle before we WRED + +2009-05-06 Mathiasdm + * 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 ;)) + +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 + +2009-05-01 zzz + * Build files: + - Fix up susidns build file so it will work with gcj + - Add consoleDocs target + * Client: Fix race NPE (thanks sponge) + * Console: fix ERR-UDP Disabled and Inbound TCP host/port not set + * I2CP: Fix race NPE + * I2PTunnel: + - Try to fix locking to prevent duplicate destinations when using + the new option new-dest-on-resume. Still not right for shared clients + but should be better for non-shared. + * Router console: + - Add jbigi and cpu info to logs.jsp + * Session key manager: + - Log before a hang maybe + * URL Launcher: + - Launcher on linux was stopping after trying opera, whether it succeeded or failed. + Now it keeps going to try firefox, etc. as designed. + - Extend default delay from 5s to 15s so it will reliably start + +2009-04-27 sponge + * more BOB fixes, complete with warnings when things go wrong, and + success messages when things turn around and go right. Terminates + early so that applications wait no more than 10 seconds or so. + * Reversed a few earlier patches that caused some odd behavior. + * Changed some core println()'s to debugging messages. + +2009-04-27 zzz + * Build files: + - New updaterWithJettyFixes target, build it for pkg + - Pass compiler args down from top build.xml + * GarlicMessageBuilder: Reduce bundled tags to 40 (was 100) + * i2psnark: Add Postman2 tracker + * I2PTunnel: Allow spaces in dest and proxy lists + * NetDb: + - Adjust RouterInfo expiration down to control memory usage + - Display LeaseSets and RouterInfos on separate console pages + * NTCP: + - Correct the meanings of the i2np.ntcp.autoip and i2np.ntcp.autoport + advanced config. If you have one of these set but not the other, you + will have to adjust your configuration on config.jsp. + * RouterConsole: iframe tweaks + * StatisticsManager: Cleanup + * Streaming: Don't let jrandom yell so loud + * Tunnel Pool: Don't self-destruct if more than 6 IB tunnels configured + +2009-04-25 sponge + * I2PSessionMuxedImpl atomic fixes + * BOB fixes. This should be the final bug wack. Good Luck to everybody! + +2009-04-23 zzz + * Blocklist: cleanup + * eepget: handle -h, --help, bad options, etc. + (http://forum.i2p/viewtopic.php?p=16261#16261) + * Fragmenter: don't re-throw the corrupt fragment IllegalStateException, + to limit the damage - root cause still not found + * i2psnark: (http://forum.i2p/viewtopic.php?t=3317) + - Change file limit to 512 (was 256) + - Change size limit to 10GB (was 5GB) + - Change request size to 16KB (was 32KB) + - Change pipeline to 5 (was 3) + * logs.jsp: Move version info to the top + * Jetty: Fix temp dir name handling on windows, which was + causing susidns not to start + (http://forum.i2p/viewtopic.php?t=3364) + * NTCP: Prevent IllegalStateException + * PeerProfile: + - Replace a hot lock with concurrent RW lock + - Rewrite ugly IP Restriction code + - Also use transport IP in restriction code + * RouterConsole: Make summary bar a refreshing iframe + * Transport: Start the previously unused CleanupUnreachable + 2009-04-21 sponge - * Code janator work, basic corrections involving @Override, and + * Code janitor work, basic corrections involving @Override, and appling final where it is important. Also fixed some equals methods and commented places that need fixing. diff --git a/hosts.txt b/hosts.txt index 95ca28af62be0cdbcca1c6feb0756aa7d5b8fb0c..44cdacd754d4b9955406c02e4760761ed9d57e5c 100644 --- a/hosts.txt +++ b/hosts.txt @@ -313,3 +313,5 @@ tracker.mastertracker.i2p=VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT codevoid.i2p=tV-4GJjgYIoCDTTJ91nfDbhSnT8B2o3v-TUfHtiAAjJJdroCAEDbmJWFPUQJEEispvrjNe~fP7VAYkk9fAhSrmdBLtEGB3NUESdiZEPsDtKJBdxijPGb1erZF2Z6eYHoK-t5g7MWWTsgLz~4xn211Jpfa-T4pqL2tcjsa7ixsaMpHF8NXFrITdyxSJRPz8OnHYgDR~ULFyzroi255MpiSUBzGcUZEiQSFLHLhjT5D5tP~gfJirFnfgOHvzWBK9L7y91qY~gYvM2eDcxMxq4Ac1gw0JeahkzAk3j6Spco3LHW3bJvELopf1QmLFu3nfPaegH1Hejt9AhXEH~FV-~M9F1BePipcIYlm7nKyre3aVPLYDZSCvkUx~8nnD3HEpMijD8fdfqSFPU7aZQe19a7rZJUbX~a4M3rBDO-C4uAid6Uznb1tLu2XR1GVVITGHaLwmumImXjlU~1nEnluBQB6iBQPZ9xJccArlYgWSooR9gpyN93PwTPsPe5cPkxCFuxAAAA echelon.i2p=w6zK9m4fqSfvJck9EGIR1wRIbWsEQ2DkjZ-VI57ESFqLqbTIA1cD5nOfSSbpELqPyhjifdrNiBNAsSdyil3C0a2B7CGtwUcTS2dCG0tKf2nAbvpsbcCK17nI4Xbu5KqZU0y3hJ~l7rcJqQBR0nfV5cU30ZDrpQV6VL875cihGlnmwLFq6qSzNcEb88Nw6wFG~FIgB2PJ6A3jJyuTnLrdiMvwqgD6nSyeOylOgBCsNxXh8-drrhASjladfNrwjlGRCZTiQ~H92HIyOwiabDiG3TUugMaFWs87yuXnZ~ni9jgjoAMFo8xV8Od2BiRgCxkZoMU07FhgUjew9qtXNa04wkexf3gx77nVPhqE0GHqCuwHwmBVf92RdYEys76u~akaOMq5UhayDpCBCaHiYLkKDNqmh47tfMCwxf6z8VIcR4zv25QfJDIWPs~RA~9U7m4raytiAs5PvYZBn4B3SqOL8XdkL9sDT54sQXbsYCJr3olu6ieMtNWlmos0uohYXNUyAAAA crstrack.i2p=b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA +tracker2.postman.i2p=lnQ6yoBTxQuQU8EQ1FlF395ITIQF-HGJxUeFvzETLFnoczNjQvKDbtSB7aHhn853zjVXrJBgwlB9sO57KakBDaJ50lUZgVPhjlI19TgJ-CxyHhHSCeKx5JzURdEW-ucdONMynr-b2zwhsx8VQCJwCEkARvt21YkOyQDaB9IdV8aTAmP~PUJQxRwceaTMn96FcVenwdXqleE16fI8CVFOV18jbJKrhTOYpTtcZKV4l1wNYBDwKgwPx5c0kcrRzFyw5~bjuAKO~GJ5dR7BQsL7AwBoQUS4k1lwoYrG1kOIBeDD3XF8BWb6K3GOOoyjc1umYKpur3G~FxBuqtHAsDRICkEbKUqJ9mPYQlTSujhNxiRIW-oLwMtvayCFci99oX8MvazPS7~97x0Gsm-onEK1Td9nBdmq30OqDxpRtXBimbzkLbR1IKObbg9HvrKs3L-kSyGwTUmHG9rSQSoZEvFMA-S0EXO~o4g21q1oikmxPMhkeVwQ22VHB0-LZJfmLr4SAAAA +nibble.i2p=V2XQ31BQWcwLcBNz2ywb4xy0Q1GMjdziQyjKql-lGdYPOX7w9g3j8IkA1jfW6YYwNi5QZc0JurjrSNH1yx6Y1goI8SB1l-yWdzst73fGWo6B1UtL45XrfXPg5k34RpktCNa4KoeIsUnGnxHQESSj5hw389hvexKXlkAHXQg9eUfbBYyzZc~~Kt4YdYX4cfMpXXjg443kyEiwKisOaRuiEN-YjqZ8pJTyAQsOKNg8hL3e15XFNPfAAkCSsALPAqj0~HZDwCZDeV0Cp4iaCGjw8tsNQ7xBeSjnhOeMoZKtrPAbbK4vNh7OIcakcVu16ykfEf-FcqbPQQe9rjilMy8V-BcjhggjUcZmtWj9qE7RMfUFpbAIfNHgWXTl5yR5V~brqxxuBxHQWn4oyB5NpY02dBkvvxXwdk~XFzXlSz~uEZKVswvI8rUHR4a2N3YDss5iQ~uscvKwNvsTZiDUaN66~CacZLYU9BtDBNnAxClz9LSu5b9CiunKeacbH6l5qrPpAAAA diff --git a/installer/resources/clients.config b/installer/resources/clients.config index 170f4c8fe5f0a6c5098f61a1247521295ec44406..88bba5f9a8a957ac44b1ee5edcc833bdf509ffea 100644 --- a/installer/resources/clients.config +++ b/installer/resources/clients.config @@ -1,32 +1,32 @@ # fire up the web console clientApp.0.args=7657 ::1,127.0.0.1 ./webapps/ clientApp.0.main=net.i2p.router.web.RouterConsoleRunner -clientApp.0.name=webConsole +clientApp.0.name=Web console clientApp.0.onBoot=true clientApp.0.startOnLoad=true # SAM bridge clientApp.1.main=net.i2p.sam.SAMBridge -clientApp.1.name=SAMBridge +clientApp.1.name=SAM application bridge clientApp.1.args=sam.keys 127.0.0.1 7656 i2cp.tcp.host=127.0.0.1 i2cp.tcp.port=7654 clientApp.1.startOnLoad=false # poke the i2ptunnels defined in i2ptunnel.config clientApp.2.main=net.i2p.i2ptunnel.TunnelControllerGroup -clientApp.2.name=Tunnels +clientApp.2.name=Application tunnels clientApp.2.args=i2ptunnel.config clientApp.2.startOnLoad=true # run our own eepsite with a seperate jetty instance clientApp.3.main=org.mortbay.jetty.Server -clientApp.3.name=eepsite +clientApp.3.name=My eepsite web server clientApp.3.args=eepsite/jetty.xml clientApp.3.delay=30 clientApp.3.startOnLoad=true # load a browser pointing at the web console whenever we start up clientApp.4.main=net.i2p.apps.systray.UrlLauncher -clientApp.4.name=consoleBrowser +clientApp.4.name=Browser launch at startup clientApp.4.args=http://127.0.0.1:7657/index.jsp clientApp.4.delay=15 clientApp.4.startOnLoad=true @@ -35,5 +35,5 @@ clientApp.4.startOnLoad=true clientApp.5.args= clientApp.5.delay=10 clientApp.5.main=net.i2p.BOB.BOB -clientApp.5.name=BOB +clientApp.5.name=BOB application bridge clientApp.5.startOnLoad=false diff --git a/installer/resources/i2ptunnel.config b/installer/resources/i2ptunnel.config index 48d18b95ec10335d88de0240203fadfd12de4241..c0dd002dbddf6460999aad737b6eb97fdfb7e007 100644 --- a/installer/resources/i2ptunnel.config +++ b/installer/resources/i2ptunnel.config @@ -5,7 +5,7 @@ tunnel.0.type=httpclient tunnel.0.sharedClient=true tunnel.0.interface=127.0.0.1 tunnel.0.listenPort=4444 -tunnel.0.proxyList=false.i2p +tunnel.0.proxyList=false.i2p,nibble.i2p tunnel.0.i2cpHost=127.0.0.1 tunnel.0.i2cpPort=7654 tunnel.0.option.inbound.nickname=shared clients diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index c9a95dd552208c43145fa8b634cb375b7656635f..2c9a1319ea24cd2ab5ece01a1cdd265522185046 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -999,8 +999,7 @@ public class Router { } public static void main(String args[]) { - System.out.println("Starting I2P " + RouterVersion.VERSION + "-" + RouterVersion.BUILD); - System.out.println(RouterVersion.ID); + System.out.println("Starting I2P " + RouterVersion.FULL_VERSION); installUpdates(); verifyWrapperConfig(); Router r = new Router(); diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 1d4797d6fc46971d6b640b96122df2e67994299a..e4b934bb21ad025f6d07e78f0ce4187bfdf9af95 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,11 +15,15 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $"; + /** deprecated */ + public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 1; + public final static long BUILD = 14; + /** for example "-test" */ + public final static String EXTRA = ""; + public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; public static void main(String args[]) { - System.out.println("I2P Router version: " + VERSION + "-" + BUILD); + System.out.println("I2P Router version: " + FULL_VERSION); System.out.println("Router ID: " + RouterVersion.ID); System.out.println("I2P Core version: " + CoreVersion.VERSION); System.out.println("Core ID: " + CoreVersion.ID);