gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r22350 - in gnunet-java: . src/org/gnunet src/org/gnunet/co


From: gnunet
Subject: [GNUnet-SVN] r22350 - in gnunet-java: . src/org/gnunet src/org/gnunet/construct src/org/gnunet/construct/parsers src/org/gnunet/core src/org/gnunet/dht src/org/gnunet/mesh src/org/gnunet/peerinfo src/org/gnunet/requests src/org/gnunet/statistics src/org/gnunet/testing src/org/gnunet/util test/org/gnunet/testing test/org/gnunet/util tools
Date: Wed, 27 Jun 2012 17:30:13 +0200

Author: dold
Date: 2012-06-27 17:30:13 +0200 (Wed, 27 Jun 2012)
New Revision: 22350

Added:
   gnunet-java/src/org/gnunet/hello/
   gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java
   gnunet-java/src/org/gnunet/peerinfo/InfoEnd.java
   gnunet-java/src/org/gnunet/peerinfo/ListAllPeersMessage.java
   gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java
   gnunet-java/src/org/gnunet/requests/
   gnunet-java/src/org/gnunet/requests/Request.java
   gnunet-java/src/org/gnunet/requests/RequestQueue.java
   gnunet-java/src/org/gnunet/testing/TestingServer.java
   gnunet-java/src/org/gnunet/util/HelloMessage.java
   gnunet-java/test/org/gnunet/util/ClientServerTest.java
Removed:
   gnunet-java/src/org/gnunet/peerinfo/HelloMessage.java
   gnunet-java/src/org/gnunet/util/RequestQueue.java
Modified:
   gnunet-java/ISSUES
   gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java
   gnunet-java/src/org/gnunet/construct/MessageLoader.java
   gnunet-java/src/org/gnunet/construct/MsgMap.txt
   gnunet-java/src/org/gnunet/construct/parsers/IntegerUtil.java
   gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
   gnunet-java/src/org/gnunet/core/Core.java
   gnunet-java/src/org/gnunet/dht/DistributedHashTable.java
   gnunet-java/src/org/gnunet/mesh/Mesh.java
   gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java
   gnunet-java/src/org/gnunet/peerinfo/ListPeerMessage.java
   gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java
   gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java
   gnunet-java/src/org/gnunet/statistics/Statistics.java
   gnunet-java/src/org/gnunet/testing/TestingSetup.java
   gnunet-java/src/org/gnunet/testing/TestingSubsystem.java
   gnunet-java/src/org/gnunet/util/AbsoluteTime.java
   gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java
   gnunet-java/src/org/gnunet/util/Client.java
   gnunet-java/src/org/gnunet/util/Connection.java
   gnunet-java/src/org/gnunet/util/GnunetMessage.java
   gnunet-java/src/org/gnunet/util/PeerIdentity.java
   gnunet-java/src/org/gnunet/util/Program.java
   gnunet-java/src/org/gnunet/util/Resolver.java
   gnunet-java/src/org/gnunet/util/Scheduler.java
   gnunet-java/src/org/gnunet/util/Server.java
   gnunet-java/src/org/gnunet/util/Service.java
   gnunet-java/test/org/gnunet/testing/TestingSetupTest.java
   gnunet-java/test/org/gnunet/util/ResolverTest.java
   gnunet-java/test/org/gnunet/util/ServerExample.java
   gnunet-java/tools/build
Log:
implemented peerinfo, server/service, client/server testing utilities

Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2012-06-27 15:28:20 UTC (rev 22349)
+++ gnunet-java/ISSUES  2012-06-27 15:30:13 UTC (rev 22350)
@@ -186,4 +186,31 @@
 * can peerinfo return more than one record per peer?
 
 
+--------------------------------------------------------------
 
+* see mantis for problem with the signal pipe
+
+* what should the gnunet-testing-run-server tool be called, now that
+  there already is plain gnunet-testing?
+
+* where should TESTMessage and HELLOMessage, PeerIdentity, HashCode go?
+ * and do we want to call them TESTMessage or TestMessage?
+
+
+* had a bug in the IPv6 address parsing code
+ * tried to fix it / rewrite it, eventually got frustrating
+ * found out guava has an implementation of this :)
+  * also implements shortening (like ::1)
+  * by reading the code: implementing all this correctly would not have been a 
fun time
+
+
+* TestingServer now allows the client/connection/server to be tested easily
+ * found quite some bugs during this
+
+* thoughts about exponential backoff / the client-connection stuff in GNUnet 
and gnunet-java
+ * why do we wait the entire backoff period, if the connection could be 
available earlier?
+
+
+* discuss what mesh does, what transport does
+ * i found the documentation for transport on gnunet.org
+ * the is not much information about mesh, except for the source code

Modified: gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java      
2012-06-27 15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java      
2012-06-27 15:30:13 UTC (rev 22350)
@@ -20,6 +20,9 @@
 
 package org.gnunet.construct;
 
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+
 import javax.annotation.processing.*;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.element.Element;
@@ -41,10 +44,12 @@
 /**
  * Creates a resource file 'MsgMap.txt' in the package 'org.gnunet.construct'.
  */
address@hidden({"org.gnunet.construct.UnionCase"})
address@hidden("org.gnunet.construct.UnionCase")
 @SupportedSourceVersion(SourceVersion.RELEASE_6)
 public class MessageIdAnnotationProcessor extends AbstractProcessor {
-    Map<String, Map<Integer, String>> unionmap = new HashMap<String, 
Map<Integer, String>>(100);
+    // a mapping from (union, id) to member
+    //private final Map<String, Map<Integer, String>> unionmap = new 
HashMap<String, Map<Integer, String>>(100);
+    private final Table<String, Integer, String> idToMember = 
HashBasedTable.create();
 
     @Override
     public boolean process(Set<? extends TypeElement> typeElements, 
RoundEnvironment roundEnvironment) {
@@ -67,15 +72,13 @@
 
             try {
                 Writer w = outfile.openWriter();
-                for (Map.Entry<String, Map<Integer, String>> outerEntry : 
unionmap.entrySet()) {
-                    for (Map.Entry<Integer, String> innerEntry : 
outerEntry.getValue().entrySet()) {
-                        w.write(outerEntry.getKey() + "|" + 
innerEntry.getKey() + "=" + innerEntry.getValue() + "\n");
-                    }
+                for (Table.Cell<String, Integer, String> cell : 
idToMember.cellSet()) {
+                    w.write(cell.getRowKey() + '|' + cell.getColumnKey() + '=' 
+ cell.getValue() + '\n');
                 }
 
                 DateFormat fmt = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
 
-                w.write("# generated " + fmt.format(new Date()) + "\n");
+                w.write("# generated " + fmt.format(new Date()) + '\n');
                 w.close();
             } catch (IOException e) {
                 
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Could not 
write MsgMap.txt");
@@ -86,7 +89,6 @@
         } else {
             for (Element e : 
roundEnvironment.getElementsAnnotatedWith(UnionCase.class)) {
                 UnionCase ann = e.getAnnotation(UnionCase.class);
-                String targetName = getClassName(e);
                 // get the uppermost parent class that implements 
MessageUnion. This is the union type.
                 // processingEnv.getElementUtils().
                 
//processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "element :" + 
e.toString());
@@ -105,10 +107,7 @@
                     return false;
                 }
                 String unionName = 
getClassName(types.asElement(unionInterface));
-                if (!unionmap.containsKey(unionName)) {
-                    unionmap.put(unionName, new HashMap<Integer, String>(10));
-                }
-                unionmap.get(unionName).put(ann.value(), getClassName(e));
+                idToMember.put(unionName, ann.value(), getClassName(e));
             }
         }
 
@@ -122,16 +121,17 @@
      * @param e the Element representing a class
      * @return the fully qualified class name
      */
-    String getClassName(Element e) {
+    private String getClassName(Element e) {
+
         assert e.getKind().isClass();
 
         String name = e.getSimpleName().toString();
-        String pkg = 
processingEnv.getElementUtils().getPackageOf(e).getQualifiedName().toString() + 
".";
+        String pkg = 
processingEnv.getElementUtils().getPackageOf(e).getQualifiedName().toString() + 
'.';
 
         String outer = "";
 
-        while ((e = e.getEnclosingElement()) != null && e.getKind().isClass()) 
{
-            outer = e.getSimpleName() + "$" + outer;
+        while (((e = e.getEnclosingElement()) != null) && 
e.getKind().isClass()) {
+            outer = String.format("%s$%s", e.getSimpleName(), outer);
         }
 
         return pkg + outer + name;

Modified: gnunet-java/src/org/gnunet/construct/MessageLoader.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageLoader.java     2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/construct/MessageLoader.java     2012-06-27 
15:30:13 UTC (rev 22350)
@@ -94,7 +94,7 @@
             String line;
             while ((line = in.readLine()) != null) {
                 // skip empty lines and comments
-                if (line.length() == 0 || line.charAt(0) == '#')
+                if (line.isEmpty() || line.charAt(0) == '#')
                     continue;
                 String[] m = line.split("=");
                 if (m.length != 2)

Modified: gnunet-java/src/org/gnunet/construct/MsgMap.txt
===================================================================
--- gnunet-java/src/org/gnunet/construct/MsgMap.txt     2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/construct/MsgMap.txt     2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -4,13 +4,13 @@
 org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TESTMessage
 
org.gnunet.util.GnunetMessage$Body|70=org.gnunet.core.NotifyInboundTrafficMessage
 
org.gnunet.util.GnunetMessage$Body|71=org.gnunet.core.NotifyOutboundTrafficMessage
+org.gnunet.util.GnunetMessage$Body|4=org.gnunet.util.Resolver$GetMessage
 org.gnunet.util.GnunetMessage$Body|64=org.gnunet.core.InitMessage
-org.gnunet.util.GnunetMessage$Body|4=org.gnunet.util.Resolver$GetMessage
 org.gnunet.util.GnunetMessage$Body|5=org.gnunet.util.Resolver$ResolverResponse
 org.gnunet.util.GnunetMessage$Body|65=org.gnunet.core.InitReplyMessage
 org.gnunet.util.GnunetMessage$Body|143=org.gnunet.dht.ClientGetMessage
+org.gnunet.util.GnunetMessage$Body|142=org.gnunet.dht.ClientPutMessage
 org.gnunet.util.GnunetMessage$Body|67=org.gnunet.core.ConnectNotifyMessage
-org.gnunet.util.GnunetMessage$Body|142=org.gnunet.dht.ClientPutMessage
 org.gnunet.util.GnunetMessage$Body|76=org.gnunet.core.SendMessage
 org.gnunet.util.GnunetMessage$Body|74=org.gnunet.core.SendMessageRequest
 org.gnunet.util.GnunetMessage$Body|75=org.gnunet.core.SendMessageReady
@@ -20,6 +20,9 @@
 
org.gnunet.util.GnunetMessage$Body|321=org.gnunet.nse.NetworkSizeEstimation$StartMessage
 org.gnunet.util.GnunetMessage$Body|144=org.gnunet.dht.ClientGetStopMessage
 org.gnunet.util.GnunetMessage$Body|145=org.gnunet.dht.ClientResultMessage
+org.gnunet.util.GnunetMessage$Body|332=org.gnunet.peerinfo.InfoMessage
+org.gnunet.util.GnunetMessage$Body|333=org.gnunet.peerinfo.InfoEnd
+org.gnunet.util.GnunetMessage$Body|331=org.gnunet.peerinfo.ListAllPeersMessage
 org.gnunet.util.GnunetMessage$Body|149=org.gnunet.dht.MonitorGetMessage
 org.gnunet.util.GnunetMessage$Body|150=org.gnunet.dht.MonitorGetRespMessage
 org.gnunet.util.GnunetMessage$Body|151=org.gnunet.dht.MonitorPutMessage
@@ -29,4 +32,4 @@
 org.gnunet.util.GnunetMessage$Body|168=org.gnunet.statistics.SetMessage
 
org.gnunet.util.GnunetMessage$Body|173=org.gnunet.statistics.WatchResponseMessage
 org.gnunet.util.GnunetMessage$Body|172=org.gnunet.statistics.WatchMessage
-# generated 2012/05/30 13:59:09
+# generated 2012/06/27 15:23:37

Modified: gnunet-java/src/org/gnunet/construct/parsers/IntegerUtil.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/IntegerUtil.java       
2012-06-27 15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/construct/parsers/IntegerUtil.java       
2012-06-27 15:30:13 UTC (rev 22350)
@@ -59,9 +59,6 @@
     public static void writeLong(final long val, final ByteBuffer dstBuf, 
boolean isSigned, int byteSize) {
         long myval = val;
 
-        int startPos = dstBuf.position();
-
-
         // position of the last byte we are responsible to write
         int last = dstBuf.position() + byteSize - 1;
 

Modified: 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2012-06-27 15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2012-06-27 15:30:13 UTC (rev 22350)
@@ -70,7 +70,7 @@
         for (int i = 0; i < elemNumber; ++i) {
             Message elemObj;
 
-            elemObj = (Message) 
ReflectUtil.<Message>justInstantiate(arrayElementType);
+            elemObj = (Message) ReflectUtil.justInstantiate(arrayElementType);
 
 
             Array.set(arr, i, elemObj);

Modified: gnunet-java/src/org/gnunet/core/Core.java
===================================================================
--- gnunet-java/src/org/gnunet/core/Core.java   2012-06-27 15:28:20 UTC (rev 
22349)
+++ gnunet-java/src/org/gnunet/core/Core.java   2012-06-27 15:30:13 UTC (rev 
22350)
@@ -22,6 +22,8 @@
 
 import org.gnunet.construct.Construct;
 import org.gnunet.construct.MessageLoader;
+import org.gnunet.requests.Request;
+import org.gnunet.requests.RequestQueue;
 import org.gnunet.util.*;
 import org.grothoff.Runabout;
 import org.slf4j.Logger;
@@ -82,7 +84,7 @@
     /**
      * Information about the requests on connected peers.
      */
-    private class ConnectedPeerInfo {
+    private static class ConnectedPeerInfo {
         public Map<Integer, NotifyTransmitReadyRequest> requestsToPeer = new 
HashMap<Integer,
                 NotifyTransmitReadyRequest>(1);
         public int nextSmrId;
@@ -93,7 +95,7 @@
      * Request to transmit a message, sent after the corresponding 
NotifyTransmitRequest has been
      * approved by core.
      */
-    private class TransmitRequest extends RequestQueue.Request {
+    private static class TransmitRequest extends Request {
         public NotifyTransmitReadyRequest origin;
         public GnunetMessage message;
 
@@ -123,7 +125,7 @@
     /**
      * Sent after we get a SendMessageReady
      */
-    private class NotifyTransmitReadyRequest extends RequestQueue.Request {
+    private static class NotifyTransmitReadyRequest extends Request {
         public AbsoluteTime deadline;
         public int size;
         public int priority;
@@ -158,7 +160,7 @@
         }
     }
 
-    private class InitRequest extends RequestQueue.Request {
+    private class InitRequest extends Request {
         @Override
         public AbsoluteTime getDeadline() {
             return AbsoluteTime.FOREVER;
@@ -265,8 +267,7 @@
                 }
             });
 
-            Cancelable c = requestQueue.add(transmitRequest);
-            req.transmitRequestCancel = c;
+            req.transmitRequestCancel = requestQueue.add(transmitRequest);
         }
 
         @Override

Modified: gnunet-java/src/org/gnunet/dht/DistributedHashTable.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/DistributedHashTable.java    2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/dht/DistributedHashTable.java    2012-06-27 
15:30:13 UTC (rev 22350)
@@ -20,6 +20,8 @@
 
 package org.gnunet.dht;
 
+import org.gnunet.requests.Request;
+import org.gnunet.requests.RequestQueue;
 import org.gnunet.util.*;
 import org.gnunet.util.getopt.Option;
 import org.gnunet.util.getopt.OptionAction;
@@ -67,7 +69,7 @@
         requestQueue = new RequestQueue(client, new DHTMessageReceiver());
     }
 
-    private class PutRequest extends RequestQueue.Request {
+    private class PutRequest extends Request {
         public AbsoluteTime deadline;
         public byte[] data;
         public HashCode key;
@@ -104,7 +106,7 @@
     }
 
 
-    private class GetRequest extends RequestQueue.Request {
+    private class GetRequest extends Request {
         public long uid;
         public HashCode key;
         public ResultCallback cb;
@@ -135,7 +137,7 @@
         }
     }
 
-    private class MonitorRequest extends RequestQueue.Request {
+    private class MonitorRequest extends Request {
 
         public int blockType;
         public HashCode key;

Added: gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java                   
        (rev 0)
+++ gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java   2012-06-27 
15:30:13 UTC (rev 22350)
@@ -0,0 +1,15 @@
+package org.gnunet.mesh;
+
+import org.gnunet.construct.UInt16;
+import org.gnunet.util.GnunetMessage;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class ClientConnectMessage implements GnunetMessage.Body {
+    @UInt16
+    public int applications;
+    public int types;
+}

Modified: gnunet-java/src/org/gnunet/mesh/Mesh.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/Mesh.java   2012-06-27 15:28:20 UTC (rev 
22349)
+++ gnunet-java/src/org/gnunet/mesh/Mesh.java   2012-06-27 15:30:13 UTC (rev 
22350)
@@ -27,7 +27,7 @@
  * @author Florian Dold
  */
 public class Mesh {
-    public class Tunnel {
+    public static class Tunnel {
         public void destroy() {
             // ...
         }

Deleted: gnunet-java/src/org/gnunet/peerinfo/HelloMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/HelloMessage.java       2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/peerinfo/HelloMessage.java       2012-06-27 
15:30:13 UTC (rev 22350)
@@ -1,50 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2011, 2012 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING.  If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-package org.gnunet.peerinfo;
-
-import org.gnunet.construct.*;
-
-/**
- * A HELLO message is used to exchange information about
- * transports with other peers.  This struct is always
- * followed by the actual network addresses which have
- * the format:
- *
- * 1) transport-name (0-terminated)
- * 2) address-length (uint16_t, network byte order; possibly
- *    unaligned!)
- * 3) address expiration (GNUNET_TIME_AbsoluteNBO); possibly
- *    unaligned!)
- * 4) address (address-length bytes; possibly unaligned!)
- *
- * @author Florian Dold
- */
address@hidden(16)
-public class HelloMessage implements Message {
-    @UInt32
-    public int reserved;
-
-    @NestedMessage
-    public RsaPublicKeyBinaryEncoded publicKey;
-
-    @ByteFill
-    public byte[] addresses;
-}

Added: gnunet-java/src/org/gnunet/peerinfo/InfoEnd.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/InfoEnd.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/peerinfo/InfoEnd.java    2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -0,0 +1,14 @@
+package org.gnunet.peerinfo;
+
+import org.gnunet.construct.UnionCase;
+import org.gnunet.util.GnunetMessage;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
address@hidden(333)
+public class InfoEnd implements GnunetMessage.Body {
+
+}

Modified: gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java        2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java        2012-06-27 
15:30:13 UTC (rev 22350)
@@ -22,18 +22,28 @@
 
 import org.gnunet.construct.NestedMessage;
 import org.gnunet.construct.UInt32;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.util.HelloMessage;
+import org.gnunet.util.GnunetMessage;
 import org.gnunet.util.PeerIdentity;
 
 /**
  * @author Florian Dold
  */
-public class InfoMessage {
address@hidden(332)
+public class InfoMessage implements GnunetMessage.Body {
+    /**
+     * Always zero.
+     */
     @UInt32
     public int reserved;
+    /**
+     * About which peer are we talking here?
+     */
     @NestedMessage
     public PeerIdentity peerIdentity;
     /**
-     * Hello of the peer, only there if available.
+     * HELLO of the peer, null if no HELLO present.
      */
     @NestedMessage(optional = true)
     public HelloMessage hello;

Copied: gnunet-java/src/org/gnunet/peerinfo/ListAllPeersMessage.java (from rev 
22266, gnunet-java/src/org/gnunet/peerinfo/ListPeerMessage.java)
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/ListAllPeersMessage.java                
                (rev 0)
+++ gnunet-java/src/org/gnunet/peerinfo/ListAllPeersMessage.java        
2012-06-27 15:30:13 UTC (rev 22350)
@@ -0,0 +1,37 @@
+/*
+ This file is part of GNUnet.
+ (C) 2011, 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.peerinfo;
+
+import org.gnunet.construct.NestedMessage;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.PeerIdentity;
+
+/**
+ * Message requesting a listing of all known peers,
+ * possibly restricted to the specified peer identity.
+ *
+ * @author Florian Dold
+ */
address@hidden(331)
+public class ListAllPeersMessage implements GnunetMessage.Body {
+}

Modified: gnunet-java/src/org/gnunet/peerinfo/ListPeerMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/ListPeerMessage.java    2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/peerinfo/ListPeerMessage.java    2012-06-27 
15:30:13 UTC (rev 22350)
@@ -20,7 +20,10 @@
 
 package org.gnunet.peerinfo;
 
+import org.gnunet.construct.NestedMessage;
+import org.gnunet.construct.UInt32;
 import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.PeerIdentity;
 
 /**
  * Message requesting a listing of all known peers,
@@ -29,5 +32,8 @@
  * @author Florian Dold
  */
 public class ListPeerMessage implements GnunetMessage.Body {
-
+    @UInt32
+    public int reserved;
+    @NestedMessage
+    public PeerIdentity peer;
 }

Modified: gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java   2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java   2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -20,7 +20,13 @@
 
 package org.gnunet.peerinfo;
 
+
+import org.gnunet.util.HelloMessage;
+import org.gnunet.requests.Request;
+import org.gnunet.requests.RequestQueue;
 import org.gnunet.util.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Interface to the service that maintains all known hosts.
@@ -28,20 +34,45 @@
  * @author Florian Dold
  */
 public class PeerInfo {
-    private Client client;
-    private RequestQueue requests;
+    private static final Logger logger = LoggerFactory
+            .getLogger(AbsoluteTime.class);
 
 
-    public interface PeerIterator {
-        public void onPeer(PeerIdentity peerIdentity, HelloMessage hello);
-        public void onEnd();
-    }
+    private final RequestQueue requests;
+    private PeerIterateRequest activeRequest;
 
-    private class PeerInfoMessageReceiver implements MessageReceiver {
+
+    private class PeerIterateRequest extends Request {
+        public PeerIdentity peer;
+        public PeerProcessor peerProcessor;
         @Override
-        public void process(GnunetMessage.Body msg) {
+        public void transmit(Connection.MessageSink sink) {
+            if (peer == null) {
+                ListAllPeersMessage lapm = new ListAllPeersMessage();
+                sink.send(lapm);
+            } else {
+                ListPeerMessage lpm = new ListPeerMessage();
+                lpm.peer = peer;
+                sink.send(lpm);
+            }
+            activeRequest = this;
+            requests.clog();
         }
+    }
 
+    private class PeerInfoMessageReceiver extends RunaboutMessageReceiver {
+        public void visit(InfoEnd infoEnd) {
+            activeRequest.peerProcessor.onEnd();
+            activeRequest = null;
+            requests.unclog();
+        }
+        public void visit(InfoMessage infoMessage) {
+            if (activeRequest == null) {
+                logger.warn("PEERINFO sent info message, but no request is 
active");
+            }
+            activeRequest.peerProcessor.onPeer(infoMessage.peerIdentity, 
infoMessage.hello);
+        }
+
         @Override
         public void handleError() {
         }
@@ -49,21 +80,46 @@
 
 
     public PeerInfo(Configuration cfg) {
-        client = new Client("peerinfo", cfg);
+        Client client = new Client("peerinfo", cfg);
         requests = new RequestQueue(client, new PeerInfoMessageReceiver());
     }
 
-    public Cancelable iterate(RelativeTime timeout, PeerIterator iterator) {
-        return null;
+    public Cancelable iterate(RelativeTime timeout, PeerProcessor iterator) {
+        return iterate(timeout, null, iterator);
     }
 
-    public Cancelable iterate(RelativeTime timeout, PeerIdentity peer, 
PeerIterator iterator) {
-        return null;
+    public Cancelable iterate(RelativeTime timeout, PeerIdentity peer, 
PeerProcessor iterator) {
+        PeerIterateRequest peerIterateRequest = new PeerIterateRequest();
+        peerIterateRequest.peer = peer;
+        peerIterateRequest.peerProcessor = iterator;
+        peerIterateRequest.setDeadline(timeout.toAbsolute());
+        return requests.add(peerIterateRequest);
     }
 
     public void disconnect() {
-
+        requests.destroy();
     }
 
+    public static void main(String... args) {
+        new Program(args) {
 
+            @Override
+            public void run() {
+                final PeerInfo peerInfo = new PeerInfo(getConfiguration());
+                peerInfo.iterate(RelativeTime.FOREVER, new PeerProcessor() {
+                    @Override
+                    public void onPeer(PeerIdentity peerIdentity, HelloMessage 
hello) {
+                        System.out.println("got peer");
+                    }
+
+                    @Override
+                    public void onEnd() {
+                        System.out.println("got peer end");
+                        peerInfo.disconnect();
+                    }
+                });
+            }
+        }.start();
+
+    }
 }

Added: gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java                      
        (rev 0)
+++ gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java      2012-06-27 
15:30:13 UTC (rev 22350)
@@ -0,0 +1,12 @@
+package org.gnunet.peerinfo;
+
+import org.gnunet.util.HelloMessage;
+import org.gnunet.util.PeerIdentity;
+
+/**
+ * Callback class to receive known peers and their HELLOs.
+ */
+public interface PeerProcessor {
+    public void onPeer(PeerIdentity peerIdentity, HelloMessage hello);
+    public void onEnd();
+}

Modified: gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java  
2012-06-27 15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java  
2012-06-27 15:30:13 UTC (rev 22350)
@@ -21,13 +21,14 @@
 package org.gnunet.peerinfo;
 
 import org.gnunet.construct.FixedSizeByteArray;
+import org.gnunet.construct.Message;
 import org.gnunet.construct.UInt16;
 import org.gnunet.construct.UInt8;
 
 /**
  * @author Florian Dold
  */
-public class RsaPublicKeyBinaryEncoded {
+public class RsaPublicKeyBinaryEncoded implements Message {
     public static final int GNUNET_CRYPTO_RSA_KEY_LENGTH = 258;
 
     /**

Added: gnunet-java/src/org/gnunet/requests/Request.java
===================================================================
--- gnunet-java/src/org/gnunet/requests/Request.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/requests/Request.java    2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -0,0 +1,65 @@
+package org.gnunet.requests;
+
+import org.gnunet.util.AbsoluteTime;
+import org.gnunet.util.Connection;
+import org.gnunet.util.RelativeTime;
+
+/**
+* ...
+*
+* @author Florian Dold
+*/
+public abstract class Request {
+    protected AbsoluteTime deadline = AbsoluteTime.FOREVER;
+
+    /**
+     * Called whenever the request could not be transmitted due to timeout.
+     *
+     * @return
+     */
+    public boolean onTransmitTimeout() {
+        // per default, just drop the message on timeout!
+        return false;
+    }
+
+    /**
+     *
+     *
+     * @return true if the request should be kept after the destroy request
+     */
+    public boolean onDestroy() {
+        // per default, do not keep on destroy
+        return false;
+    }
+
+    /**
+     * @return true if the request should be kept after the reconnect
+     */
+    public boolean onReconnect() {
+        // per default, do not keep on reconnect
+        return false;
+    }
+
+    /**
+     * @param alreadyTransmitted true if message has already been sent over 
the network
+     */
+    public void onCancel(boolean alreadyTransmitted) {
+        // do nothing
+    }
+
+    public void setDeadline(AbsoluteTime deadline) {
+        this.deadline = deadline;
+    }
+
+    /**
+     * Called to determine after how long the request should time out.
+     * Per default, the deadline is FOREVER.
+     *
+     * @return
+     */
+    public AbsoluteTime getDeadline() {
+        return deadline;
+    }
+
+    public abstract void transmit(Connection.MessageSink sink);
+}

Copied: gnunet-java/src/org/gnunet/requests/RequestQueue.java (from rev 22266, 
gnunet-java/src/org/gnunet/util/RequestQueue.java)
===================================================================
--- gnunet-java/src/org/gnunet/requests/RequestQueue.java                       
        (rev 0)
+++ gnunet-java/src/org/gnunet/requests/RequestQueue.java       2012-06-27 
15:30:13 UTC (rev 22350)
@@ -0,0 +1,294 @@
+/*
+ This file is part of GNUnet.
+ (C) 2011, 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.requests;
+
+import org.gnunet.util.*;
+
+import java.util.LinkedList;
+
+/**
+ * Generic queues for Requests to be sent to the service.
+ */
+public class RequestQueue {
+    // todo: implement more efficiently (attributes instead of multiple queues)
+
+    /**
+     * Requests to be transmitted to the service.
+     */
+    private final LinkedList<Request> requestsAwaitingTransmit = new 
LinkedList<Request>();
+
+    /**
+     * Persistent requests. Will be informed about reconnect / destroy events 
even
+     * if already transmitted. Have to be canceled manually.
+     */
+    private final LinkedList<Request> persistentRequests = new 
LinkedList<Request>();
+
+    /**
+     * List of all requests from requestAwaitingTransmit and 
persistentRequest, containing no duplicates.
+     */
+    private final LinkedList<Request> allRequests = new LinkedList<Request>();
+
+    /**
+     * The designated receiver for all messages.
+     */
+    private MessageReceiver receiver;
+
+    /**
+     * The active transmit request handle, if any.
+     */
+    private Cancelable currentTransmit;
+
+    /**
+     * Current receive handler.
+     */
+    private Cancelable currentReceive;
+
+    /**
+     * True if we should not send further requests until queue is unclogged.
+     */
+    private boolean clogged = false;
+
+    private boolean destroyed = false;
+    private final Client client;
+
+    public RequestQueue(Client client, MessageReceiver receiver) {
+        this.client = client;
+        this.receiver = receiver;
+    }
+
+    /**
+     * Handle next request.
+     */
+    private void handleNextTransmit() {
+        if (clogged) {
+            return;
+        }
+
+        // return if we are already transmitting something
+        if (currentTransmit != null) {
+            return;
+        }
+
+        final Request request = requestsAwaitingTransmit.poll();
+        if (request == null) {
+            handleReceive();
+            return;
+        }
+
+        AbsoluteTime deadline = request.getDeadline();
+        if (deadline == null) {
+            throw new AssertionError("getDeadline() must return a non-null 
AbsoluteTime");
+        }
+
+        currentTransmit = client.notifyTransmitReady(deadline.getRemaining(), 
true, 0, new MessageTransmitter() {
+            @Override
+            public void transmit(Connection.MessageSink sink) {
+                currentTransmit = null;
+
+                try {
+                    request.transmit(sink);
+                } finally {
+                    handleReceive();
+                    handleNextTransmit();
+                }
+            }
+
+            @Override
+            public void handleError() {
+                throw new AssertionError("not implemented");
+            }
+        });
+    }
+
+    /**
+     * Continue receiving if necessary.
+     */
+    private void handleReceive() {
+        if (currentReceive != null || destroyed || !client.isConnected()) {
+            return;
+        }
+        currentReceive = client.receive(RelativeTime.FOREVER, new 
MessageReceiver() {
+            @Override
+            public void process(GnunetMessage.Body msg) {
+                currentReceive = null;
+
+                try {
+                    receiver.process(msg);
+                } finally {
+                    handleNextTransmit();
+                    handleReceive();
+                }
+            }
+
+            @Override
+            public void handleError() {
+                receiver.handleError();
+            }
+        });
+    }
+
+    /**
+     * Add a request to the end of the queue.
+     *
+     * @param request request to be added
+     * @return a handle to cancel the request
+     */
+    public Cancelable add(final Request request) {
+        allRequests.add(request);
+        requestsAwaitingTransmit.add(request);
+        handleNextTransmit();
+
+        return new Cancelable() {
+            @Override
+            public void cancel() {
+                RequestQueue.this.requestsAwaitingTransmit.remove(request);
+                RequestQueue.this.persistentRequests.remove(request);
+                RequestQueue.this.allRequests.remove(request);
+                request.onCancel(!requestsAwaitingTransmit.contains(request));
+            }
+        };
+    }
+
+
+    /**
+     * Add a request so that it will get notified about reconnect/destroy 
events,
+     * even if it already has been transmitted.
+     */
+    public Cancelable addPersistent(final Request request) {
+        persistentRequests.add(request);
+        return add(request);
+    }
+
+
+    /**
+     * Add a request to the front of the queue, this request will be sent as
+     * the next message (if not preempted by another sendNext).
+     *
+     * @param request request to be sent next
+     * @return a handle to cancel the request
+     */
+    public Cancelable sendNext(final Request request) {
+        requestsAwaitingTransmit.addFirst(request);
+        handleNextTransmit();
+        // todo: should this really return Cancelable? When do we want to 
cancel a request added by sendNext?
+        return new Cancelable() {
+            @Override
+            public void cancel() {
+                RequestQueue.this.requestsAwaitingTransmit.remove(request);
+                RequestQueue.this.persistentRequests.remove(request);
+                RequestQueue.this.allRequests.remove(request);
+                request.onCancel(!requestsAwaitingTransmit.contains(request));
+            }
+        };
+    }
+
+    /**
+     * Reconnect the client and notify all pending request of the reconnect.
+     */
+    public void reconnect() {
+        client.reconnect();
+        currentReceive = null;
+        currentTransmit = null;
+
+        final LinkedList<Request> remove = new LinkedList<Request>();
+
+
+        for (Request r : allRequests) {
+            boolean keep = r.onReconnect();
+            if (!keep) {
+                remove.add(r);
+            } else {
+                // retransmit an apparently persistent request.
+                if (!requestsAwaitingTransmit.contains(r)) {
+                    requestsAwaitingTransmit.add(r);
+                }
+            }
+        }
+        requestsAwaitingTransmit.removeAll(remove);
+        persistentRequests.removeAll(remove);
+        allRequests.removeAll(remove);
+
+        // only transmit, receive should only be called after the first 
transmit
+        handleNextTransmit();
+    }
+
+    /**
+     * Notify all request of the shutdown. Does not actually destroy the 
connection.
+     */
+    public void shutdown() {
+        final LinkedList<Request> remove = new LinkedList<Request>();
+
+        for (Request r : allRequests) {
+            boolean keep = r.onDestroy();
+            if (!keep) {
+                remove.add(r);
+            } else {
+                // retransmit an apparently persistent request.
+                if (!requestsAwaitingTransmit.contains(r)) {
+                    requestsAwaitingTransmit.add(r);
+                }
+            }
+        }
+        requestsAwaitingTransmit.removeAll(remove);
+        persistentRequests.removeAll(remove);
+        allRequests.removeAll(remove);
+
+        handleNextTransmit();
+        handleReceive();
+    }
+
+    /**
+     * Cancel all requests and destroy the connection.
+     */
+    public void destroy() {
+        destroyed = true;
+        allRequests.clear();
+        persistentRequests.clear();
+        requestsAwaitingTransmit.clear();
+        if (currentTransmit != null) {
+            currentTransmit.cancel();
+        }
+        if (currentReceive != null) {
+            currentReceive.cancel();
+        }
+    }
+
+    /**
+     * Allow no further requests to be transmitted until the queue is 
unclogged.
+     */
+    public void clog() {
+        if (clogged) {
+            throw new AssertionError("double clog");
+        }
+        clogged = true;
+    }
+
+    /**
+     * Unclog the queue, must have been previously clogged.
+     */
+    public void unclog() {
+        if (!clogged) {
+            throw new AssertionError("unclogg before clog");
+        }
+        clogged = false;
+        handleNextTransmit();
+    }
+}

Modified: gnunet-java/src/org/gnunet/statistics/Statistics.java
===================================================================
--- gnunet-java/src/org/gnunet/statistics/Statistics.java       2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/statistics/Statistics.java       2012-06-27 
15:30:13 UTC (rev 22350)
@@ -26,6 +26,8 @@
 
 package org.gnunet.statistics;
 
+import org.gnunet.requests.Request;
+import org.gnunet.requests.RequestQueue;
 import org.gnunet.util.*;
 import org.gnunet.util.getopt.Option;
 import org.gnunet.util.getopt.OptionAction;
@@ -74,7 +76,7 @@
     /**
      * A request to the statistics service.
      */
-    private abstract class StatisticsRequest extends RequestQueue.Request {
+    private abstract class StatisticsRequest extends Request {
         public String name;
         public String subsystem;
         public AbsoluteTime deadline;
@@ -171,7 +173,7 @@
         }
     }
 
-    private static class TESTRequest extends RequestQueue.Request {
+    private static class TESTRequest extends Request {
         private AbsoluteTime deadline;
 
         public TESTRequest(AbsoluteTime deadline) {
@@ -377,7 +379,7 @@
                 } else {
                     if (unprocessedArgs.length == 0) {
                         if (watch) {
-                            final Cancelable c = 
statistics.watch(subsystemName, statisticsName,
+                            statistics.watch(subsystemName, statisticsName,
                                     new StatisticsReceiver() {
                                         @Override
                                         public void onReceive(String 
subsystem, String name, long value) {

Added: gnunet-java/src/org/gnunet/testing/TestingServer.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/TestingServer.java                       
        (rev 0)
+++ gnunet-java/src/org/gnunet/testing/TestingServer.java       2012-06-27 
15:30:13 UTC (rev 22350)
@@ -0,0 +1,59 @@
+package org.gnunet.testing;
+
+import org.gnunet.util.Client;
+import org.gnunet.util.RelativeTime;
+import org.gnunet.util.Server;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.ServerSocketChannel;
+
+/**
+ * Server with an ephemeral port.
+ * Can spawn clients connected to the server for testing.
+ *
+ * @author Florian Dold
+ */
+public class TestingServer {
+    public final Server server;
+    private final ServerSocketChannel srvChan;
+
+    TestingServer() {
+        this(RelativeTime.FOREVER, true);
+    }
+
+    public TestingServer(RelativeTime idleTimeout, boolean requireFound) {
+        try {
+            srvChan = ServerSocketChannel.open();
+            srvChan.configureBlocking(false);
+
+            // bind to ephemeral port
+            srvChan.socket().bind(null);
+        } catch (IOException e) {
+            throw new RuntimeException("TestingServer creation failed");
+        }
+
+        server = new Server(idleTimeout, requireFound);
+        server.addAcceptSocket(srvChan);
+
+    }
+
+    /**
+     * Create a client connected to this server.
+     *
+     * @return a client connected to this server
+     */
+    public Client createClient() {
+        SocketAddress socketAddress = srvChan.socket().getLocalSocketAddress();
+
+        if (!(socketAddress instanceof InetSocketAddress)) {
+            throw new RuntimeException("unknown type of socket address");
+        }
+        InetSocketAddress saddr = (InetSocketAddress) socketAddress;
+
+        return new Client(saddr.getHostName(), 
srvChan.socket().getLocalPort());
+    }
+
+}

Modified: gnunet-java/src/org/gnunet/testing/TestingSetup.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/TestingSetup.java        2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/testing/TestingSetup.java        2012-06-27 
15:30:13 UTC (rev 22350)
@@ -21,8 +21,12 @@
 package org.gnunet.testing;
 
 import org.gnunet.util.Program;
+import org.gnunet.util.RelativeTime;
 
 /**
+ * A testing setup is responsible for configuring the loggers during testing, 
and can
+ * start gnunet subsystems (like statistics, core, etc.).
+ *
  * @author Florian Dold
  */
 public class TestingSetup {
@@ -54,6 +58,14 @@
         return new TestingSubsystem(name);
     }
 
+    public TestingServer createServer() {
+        return new TestingServer();
+    }
+
+    public TestingServer createServer(RelativeTime idleTimeout, boolean 
requireFound) {
+        return new TestingServer(idleTimeout, requireFound);
+    }
+
     public TestingSetup() {
         String log = System.getenv("GNJ_LOGLEVEL");
         if (log != null) {

Modified: gnunet-java/src/org/gnunet/testing/TestingSubsystem.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/TestingSubsystem.java    2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/testing/TestingSubsystem.java    2012-06-27 
15:30:13 UTC (rev 22350)
@@ -48,7 +48,7 @@
 
     TestingSubsystem(String service) {
         try {
-            p = Runtime.getRuntime().exec(new 
String[]{"gnunet-testing-run-service", service});
+            p = Runtime.getRuntime().exec(new 
String[]{"gnunet-testing-run-service", "-s", service});
         } catch (IOException e) {
             throw new TestingSetup.SetupException(e);
         }
@@ -64,7 +64,7 @@
             throw new TestingSetup.SetupException(e);
         }
 
-        if (!started.equals("started")) {
+        if (!started.equals("ok")) {
             throw new TestingSetup.SetupException("could not start service ('" 
+ started + "')");
         }
 

Modified: gnunet-java/src/org/gnunet/util/AbsoluteTime.java
===================================================================
--- gnunet-java/src/org/gnunet/util/AbsoluteTime.java   2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/AbsoluteTime.java   2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -90,7 +90,7 @@
         }
         final RelativeTime dur = start.getDuration();
         final double exp = dur.getMilliseconds() * total
-                / finished;
+                / (double) finished;
         return new RelativeTime((long) exp);
     }
 

Modified: gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java    2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java    2012-06-27 
15:30:13 UTC (rev 22350)
@@ -38,7 +38,7 @@
 
 
     public AbsoluteTimeMessage(final AbsoluteTime t) {
-        if (t.equals(RelativeTime.FOREVER)) {
+        if (t.equals(AbsoluteTime.FOREVER)) {
             this.value__ = -1;
         } else {
             this.value__ = t.getMilliseconds();

Modified: gnunet-java/src/org/gnunet/util/Client.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Client.java 2012-06-27 15:28:20 UTC (rev 
22349)
+++ gnunet-java/src/org/gnunet/util/Client.java 2012-06-27 15:30:13 UTC (rev 
22350)
@@ -37,22 +37,20 @@
     /**
      * Host this client should be connected to.
      */
-    private int port;
-    private String hostname;
+    private final int port;
+    private final String hostname;
 
-    private Cancelable connectTimeoutHandle;
-
     /**
      * Initial value for connectBackoff.
      *
      */
-    private final RelativeTime INITAL_BACKOFF = 
RelativeTime.MILLISECOND.multiply(20);
+    private static final RelativeTime INITAL_BACKOFF = 
RelativeTime.MILLISECOND.multiply(5);
 
     /**
      * Maximum value for connectBackoff.
      *
      */
-    private final RelativeTime MAX_BACKOFF = RelativeTime.SECOND.multiply(5);
+    private static final RelativeTime MAX_BACKOFF = 
RelativeTime.SECOND.multiply(5);
 
     /**
      * The time to wait after an error occured while connecting.
@@ -62,6 +60,12 @@
     private RelativeTime connectBackoff = INITAL_BACKOFF;
 
     /**
+     * True if we are waiting for the client to connect before we can ask it 
to do
+     * notifyTransmitReady.
+     */
+    private boolean notifyTransmitReadyDelayed;
+
+    /**
      * Create a connection to a service.
      *
      * @param serviceName name of the service
@@ -81,7 +85,19 @@
         reconnect();
     }
 
+    /**
+     * Create a connection to a service with the specified hostname and port.
+     *
+     * @param hostname hostname of the service
+     * @param port port of the service
+     */
+    public Client(String hostname, int port) {
+        this.hostname = hostname;
+        this.port = port;
+        reconnect();
+    }
 
+
     /**
      * Receive one message from the service. Can only be called after sending 
a message to the server.
      *
@@ -93,7 +109,7 @@
     }
 
 
-    private class DelayedTransmitHandle implements Cancelable {
+    private static class DelayedTransmitHandle implements Cancelable {
         Cancelable realTransmitHandle;
         Cancelable timeoutHandle;
         @Override
@@ -121,12 +137,16 @@
         if (connection.isConnected()) {
             return connection.notifyTransmitReady(0, timeout, transmitter);
         } else {
-            logger.debug("notifyTransmitReady delayed");
+            notifyTransmitReadyDelayed = true;
             final DelayedTransmitHandle delayedTransmitHandle = new 
DelayedTransmitHandle();
             delayedTransmitHandle.timeoutHandle = 
Scheduler.addDelayed(connectBackoff, new Scheduler.Task() {
                 @Override
                 public void run(Scheduler.RunContext ctx) {
+                    if (connection == null) {
+                        return;
+                    }
                     if (connection.isConnected()) {
+                        notifyTransmitReadyDelayed = false;
                         connection.notifyTransmitReady(0, timeout, 
transmitter);
                     } else {
                         logger.debug("still not connected, retrying in {}ms", 
connectBackoff.getMilliseconds());
@@ -153,11 +173,14 @@
      * Disconnect from the service. Cancel all pending receive/transmit 
requests.
      */
     public void disconnect() {
+        if (notifyTransmitReadyDelayed) {
+            logger.error("disconnecting while notifyTransmitReady is pending");
+        }
         connection.disconnect();
         connection = null;
     }
 
     public boolean isConnected() {
-        return connection != null && connection.isConnected();
+        return (connection != null) && connection.isConnected();
     }
 }

Modified: gnunet-java/src/org/gnunet/util/Connection.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Connection.java     2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/Connection.java     2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -76,8 +76,7 @@
 
 
     /**
-     * The handle for the current transmission. The current transmission either
-     * writes data to the channel or waits for the channel to connect
+     * The handle for the current transmission. Writes data to the socket.
      */
     private TransmitHelper currentTransmitHelper = null;
     /**
@@ -318,6 +317,9 @@
         }
 
         private void schedule() {
+            if (disconnected) {
+                return;
+            }
             // timeout is forever, because there is no way to directly limit 
the transmission time
             // of a message, only the max. wait time before transmission.
             // cancel must be called on the transmitTask if we disconnect
@@ -438,7 +440,6 @@
             return;
         }
         if (connected) {
-            logger.debug("client successfully connected to " + 
channel.toString());
             if (currentTransmitHelper != null) {
                 currentTransmitHelper.start();
             }
@@ -515,6 +516,9 @@
      * @return a handle that can be used to cancel the transmit request, null 
if request could be satisfied immediately
      */
     public TransmitHandle notifyTransmitReady(int size, RelativeTime timeout, 
final MessageTransmitter transmitter) {
+        if (disconnected) {
+            throw new AssertionError("notifyTransmitReady called on a closed 
connection");
+        }
         if (nextTransmitHelper != null) {
             throw new AssertionError(
                     "previous transmit request must have completed before 
calling notifyTransmitReady again");
@@ -547,26 +551,29 @@
     }
 
     /**
-     * Disconnect. Cancel pending receive/transmit requests.
+     * Disconnect. There must not be any pending transmit/receive requests.
+     * Any buffered data scheduled for writing is discarded.
      */
     public void disconnect() {
         if (disconnected) {
-            logger.warn("disconnect called twice");
-            Thread.dumpStack();
+            logger.error("disconnect called twice");
         }
         disconnected = true;
 
-        logger.debug("" + this + ".disconnect()");
-        if (nextTransmitHelper != null) {
-            nextTransmitHelper.cancel();
-            nextTransmitHelper = null;
-        }
+
         if (currentTransmitHelper != null) {
             currentTransmitHelper.cancel();
             currentTransmitHelper = null;
         }
 
+        if (nextTransmitHelper != null) {
+            logger.error("disconnect called, but there is a 
notifyTransmitReady pending");
+            nextTransmitHelper.cancel();
+            nextTransmitHelper = null;
+        }
+
         if (currentReceiveHelper != null) {
+            logger.error("disconnect called, but there is a receive pending");
             currentReceiveHelper.cancel();
             currentReceiveHelper = null;
         }
@@ -587,7 +594,6 @@
             }
             connectionChannel = null;
         }
-
     }
 
 }

Modified: gnunet-java/src/org/gnunet/util/GnunetMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/util/GnunetMessage.java  2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/GnunetMessage.java  2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -32,7 +32,7 @@
  *
  */
 public final class GnunetMessage implements Message {
-    public final int MINIMAL_SIZE = Header.SIZE;
+    public static final int MINIMAL_SIZE = Header.SIZE;
 
 
     /**

Copied: gnunet-java/src/org/gnunet/util/HelloMessage.java (from rev 22266, 
gnunet-java/src/org/gnunet/peerinfo/HelloMessage.java)
===================================================================
--- gnunet-java/src/org/gnunet/util/HelloMessage.java                           
(rev 0)
+++ gnunet-java/src/org/gnunet/util/HelloMessage.java   2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -0,0 +1,50 @@
+/*
+ This file is part of GNUnet.
+ (C) 2011, 2012 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.util;
+
+import org.gnunet.construct.*;
+import org.gnunet.peerinfo.RsaPublicKeyBinaryEncoded;
+
+/**
+ * A HELLO message is used to exchange information about
+ * transports with other peers.  This struct is always
+ * followed by the actual network addresses which have
+ * the format:
+ *
+ * 1) transport-name (0-terminated)
+ * 2) address-length (uint16_t, network byte order; possibly
+ *    unaligned!)
+ * 3) address expiration (GNUNET_TIME_AbsoluteNBO); possibly
+ *    unaligned!)
+ * 4) address (address-length bytes; possibly unaligned!)
+ *
+ * @author Florian Dold
+ */
+public class HelloMessage implements Message {
+    @UInt32
+    public int reserved;
+
+    @NestedMessage
+    public RsaPublicKeyBinaryEncoded publicKey;
+
+    @ByteFill
+    public byte[] addresses;
+}

Modified: gnunet-java/src/org/gnunet/util/PeerIdentity.java
===================================================================
--- gnunet-java/src/org/gnunet/util/PeerIdentity.java   2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/PeerIdentity.java   2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -52,7 +52,7 @@
 
     @Override
     public boolean equals(Object obj) {
-        return Arrays.equals(((PeerIdentity) obj).data, this.data);
+        return obj != null && obj instanceof PeerIdentity && 
Arrays.equals(((PeerIdentity) obj).data, this.data);
     }
 
     @Override

Modified: gnunet-java/src/org/gnunet/util/Program.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Program.java        2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/Program.java        2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -37,7 +37,7 @@
  */
 public abstract class Program {
     private static final Logger logger = LoggerFactory
-            .getLogger(Resolver.class);
+            .getLogger(Program.class);
 
 
     protected final Configuration cfg = new Configuration();
@@ -46,35 +46,34 @@
             description = "Path of the configuration file",
             argumentName = "FILENAME",
             action = OptionAction.STORE_STRING)
-    public String cfgFileName = null;
+    public String cfgFileName;
 
     @Option(shortname = "h", longname = "help",
             description = "print this help message",
             action = OptionAction.SET)
-    public boolean printHelp = false;
+    public boolean printHelp;
 
     @Option(shortname = "v", longname = "version",
             description = "print version",
             action = OptionAction.SET)
-    public boolean showVersion = false;
+    public boolean showVersion;
 
 
     @Option(shortname = "L", longname = "log",
             description = "configure logging to use LOGLEVEL",
             argumentName = "LOGLEVEL",
             action = OptionAction.STORE_STRING)
-    public String logLevel = null;
+    public String logLevel;
 
     @Option(shortname = "l", longname = "logfile",
             description = "configure logging to write logs to LOGFILE",
             argumentName = "LOGFILE",
             action = OptionAction.STORE_STRING)
-    public String logFile = null;
+    public String logFile;
 
 
-    protected final String[] unprocessedArgs;
+    protected String[] unprocessedArgs;
 
-    private Parser optParser;
     private final String[] args;
 
 
@@ -86,20 +85,13 @@
      * @param args array of command line arguments to parse. used to 
automatically load additional settings
      *             and configure log levels.
      */
-    public Program(String[] args) {
+    public Program(String... args) {
         this.args = args;
-        optParser = new Parser(this);
-        unprocessedArgs = optParser.parse(args);
 
-        configureLogging(logLevel, logFile);
-
-        cfg.loadDefaults();
-
-        if (cfgFileName != null) {
-            cfg.parse(cfgFileName);
-        }
-
-        Resolver.getInstance().setConfiguration(cfg);
+        /*
+         * Remember: We can't parse command line arguments here, as java's 
initialization order
+         * dictates that member variables of subclasses are initialized 
*after* the superclass constructor (here).
+         */
     }
 
     public static void configureLogging(String logLevel, String logFile) {
@@ -163,7 +155,20 @@
     /**
      * Start the Program as the initial task of the Scheduler.
      */
-    public final void start() {
+    public void start() {
+        Parser optParser = new Parser(this);
+        unprocessedArgs = optParser.parse(args);
+
+        configureLogging(logLevel, logFile);
+
+        cfg.loadDefaults();
+
+        if (cfgFileName != null) {
+            cfg.parse(cfgFileName);
+        }
+
+        Resolver.getInstance().setConfiguration(cfg);
+
         if (showVersion) {
             System.out.println(makeVersionDescription());
         } else if (printHelp) {
@@ -172,10 +177,6 @@
         } else {
             Scheduler.run(new Scheduler.Task() {
                 public void run(Scheduler.RunContext c) {
-                    // the (default)constructor of any derived instances 
overwrites the call
-                    // to parse in the constructor, do it again here!
-                    // todo: this is too hacky, find better solution than 
parsing twice!
-                    optParser.parse(args);
                     Program.this.run();
                 }
             });
@@ -191,4 +192,3 @@
         return cfg;
     }
 }
- 
\ No newline at end of file

Deleted: gnunet-java/src/org/gnunet/util/RequestQueue.java
===================================================================
--- gnunet-java/src/org/gnunet/util/RequestQueue.java   2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/RequestQueue.java   2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -1,282 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2011, 2012 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING.  If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-package org.gnunet.util;
-
-import java.util.LinkedList;
-
-/**
- * Generic queues for Requests to be sent to the service.
- */
-public class RequestQueue {
-    // todo: implement more efficiently (attributes instead of multiple queues)
-
-    /**
-     * Requests to be transmitted to the service.
-     */
-    private final LinkedList<Request> requestsAwaitingTransmit = new 
LinkedList<Request>();
-
-    /**
-     * Persistent requests. Will be informed about reconnect / destroy events 
even
-     * if already transmitted. Have to be canceled manually.
-     */
-    private final LinkedList<Request> persistentRequests = new 
LinkedList<Request>();
-
-    /**
-     * List of all requests from requestAwaitingTransmit and 
persistentRequest, containing no duplicates.
-     */
-    private final LinkedList<Request> allRequests = new LinkedList<Request>();
-
-    /**
-     * The designated receiver for all messages.
-     */
-    private MessageReceiver receiver;
-
-    /**
-     * The active transmit request handle, if any.
-     */
-    private Cancelable currentTransmit;
-
-    /**
-     * Current receive handler.
-     */
-    private Cancelable currentReceive;
-
-    private boolean destroyed = false;
-    private final Client client;
-
-    public static abstract class Request {
-
-        public boolean onTransmitTimeout() {
-            // per default, just drop the message on timeout!
-            return false;
-        }
-
-        /**
-         * @return true if the request should be kept after the destroy request
-         */
-        public boolean onDestroy() {
-            // per default, do not keep on destroy
-            return false;
-        }
-
-        /**
-         * @return true if the request should be kept after the reconnect
-         */
-        public boolean onReconnect() {
-            // per default, do not keep on reconnect
-            return false;
-        }
-
-        /**
-         * @param alreadyTransmitted true if message has already been sent 
over the network
-         */
-        public void onCancel(boolean alreadyTransmitted) {
-            // do nothing
-        }
-
-        public abstract AbsoluteTime getDeadline();
-
-        public abstract void transmit(Connection.MessageSink sink);
-    }
-
-    public RequestQueue(Client client, MessageReceiver receiver) {
-        this.client = client;
-        this.receiver = receiver;
-    }
-
-    /**
-     * Handle next request.
-     */
-    private void handleNextTransmit() {
-        if (currentTransmit != null) {
-            return;
-        }
-
-        final Request request = requestsAwaitingTransmit.poll();
-        if (request == null) {
-            handleReceive();
-            return;
-        }
-
-        AbsoluteTime deadline = request.getDeadline();
-        if (deadline == null) {
-            throw new AssertionError("getDeadline() must return a non-null 
AbsoluteTime");
-        }
-
-        currentTransmit = client.notifyTransmitReady(deadline.getRemaining(), 
true, 0, new MessageTransmitter() {
-            @Override
-            public void transmit(Connection.MessageSink sink) {
-                currentTransmit = null;
-
-                try {
-                    request.transmit(sink);
-                } finally {
-                    handleReceive();
-                    handleNextTransmit();
-                }
-            }
-
-            @Override
-            public void handleError() {
-                throw new AssertionError("not implemented");
-            }
-        });
-    }
-
-    private void handleReceive() {
-        if (currentReceive != null || destroyed || !client.isConnected()) {
-            return;
-        }
-        currentReceive = client.receive(RelativeTime.FOREVER, new 
MessageReceiver() {
-            @Override
-            public void process(GnunetMessage.Body msg) {
-                currentReceive = null;
-
-                try {
-                    receiver.process(msg);
-                } finally {
-                    handleNextTransmit();
-                    handleReceive();
-                }
-            }
-
-            @Override
-            public void handleError() {
-                receiver.handleError();
-            }
-        });
-    }
-
-    public Cancelable add(final Request request) {
-        allRequests.add(request);
-        requestsAwaitingTransmit.add(request);
-        handleNextTransmit();
-
-        return new Cancelable() {
-            @Override
-            public void cancel() {
-                RequestQueue.this.requestsAwaitingTransmit.remove(request);
-                RequestQueue.this.persistentRequests.remove(request);
-                RequestQueue.this.allRequests.remove(request);
-                request.onCancel(!requestsAwaitingTransmit.contains(request));
-            }
-        };
-    }
-
-
-    /**
-     * Add a request so that it will get notified about reconnect/destroy 
events,
-     * even if it already has been transmitted.
-     */
-    public Cancelable addPersistent(final Request request) {
-        persistentRequests.add(request);
-        return add(request);
-    }
-
-    /**
-     * Add a message to the queue that will be sent before all other messages 
in the queue.
-     */
-    // should this really be cancelable?
-    public Cancelable sendNext(final Request request) {
-        requestsAwaitingTransmit.addFirst(request);
-        handleNextTransmit();
-        return new Cancelable() {
-            @Override
-            public void cancel() {
-                RequestQueue.this.requestsAwaitingTransmit.remove(request);
-                RequestQueue.this.persistentRequests.remove(request);
-                RequestQueue.this.allRequests.remove(request);
-                request.onCancel(!requestsAwaitingTransmit.contains(request));
-            }
-        };
-    }
-
-    /**
-     * Reconnect the client and notify all pending request of the reconnect.
-     */
-    public void reconnect() {
-        client.reconnect();
-        currentReceive = null;
-        currentTransmit = null;
-
-        final LinkedList<Request> remove = new LinkedList<Request>();
-
-
-        for (Request r : allRequests) {
-            boolean keep = r.onReconnect();
-            if (!keep) {
-                remove.add(r);
-            } else {
-                // retransmit an apparently persistent request.
-                if (!requestsAwaitingTransmit.contains(r)) {
-                    requestsAwaitingTransmit.add(r);
-                }
-            }
-        }
-        requestsAwaitingTransmit.removeAll(remove);
-        persistentRequests.removeAll(remove);
-        allRequests.removeAll(remove);
-
-        // only transmit, receive should only be called after the first 
transmit
-        handleNextTransmit();
-    }
-
-    /**
-     * Notify all request of the shutdown.
-     */
-    public void shutdown() {
-        final LinkedList<Request> remove = new LinkedList<Request>();
-
-        for (Request r : allRequests) {
-            boolean keep = r.onDestroy();
-            if (!keep) {
-                remove.add(r);
-            } else {
-                // retransmit an apparently persistent request.
-                if (!requestsAwaitingTransmit.contains(r)) {
-                    requestsAwaitingTransmit.add(r);
-                }
-            }
-        }
-        requestsAwaitingTransmit.removeAll(remove);
-        persistentRequests.removeAll(remove);
-        allRequests.removeAll(remove);
-
-        handleNextTransmit();
-        handleReceive();
-    }
-
-    /**
-     * Cancel all requests and destroy the connection.
-     */
-    public void destroy() {
-        destroyed = true;
-        allRequests.clear();
-        persistentRequests.clear();
-        requestsAwaitingTransmit.clear();
-        if (currentTransmit != null) {
-            currentTransmit.cancel();
-        }
-        if (currentReceive != null) {
-            currentReceive.cancel();
-        }
-    }
-}

Modified: gnunet-java/src/org/gnunet/util/Resolver.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Resolver.java       2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/Resolver.java       2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -20,6 +20,7 @@
 
 package org.gnunet.util;
 
+import com.google.common.net.InetAddresses;
 import org.gnunet.construct.*;
 import org.gnunet.construct.ProtocolViolation;
 import org.gnunet.util.getopt.Option;
@@ -42,12 +43,20 @@
     private static final Logger logger = LoggerFactory
             .getLogger(Resolver.class);
 
-    private static Resolver singletonInstance = null;
+    private static Resolver singletonInstance;
 
-    private Configuration cfg = null;
+    private Configuration cfg;
 
-    private Client client = null;
+    private Client client;
 
+    public static InetAddress getInetAddressFromString(String ipString) {
+        try {
+            return InetAddresses.forString(ipString);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
     @UnionCase(4)
     public static class GetMessage implements GnunetMessage.Body {
         static final int DIRECTION_GET_IP = 0;
@@ -65,7 +74,8 @@
         public Address addr;
     }
 
-    public static interface Address extends MessageUnion {}
+    public interface Address extends MessageUnion {
+    }
 
     @UnionCase(GetMessage.DIRECTION_GET_IP)
     public static class TextualAddress implements Address {
@@ -92,85 +102,7 @@
         public byte[] addr;
     }
 
-
     /**
-     * Return the IPv4 InetAddress corresponding to ip
-     *
-     * @param ip the ip address, e.g. "127.0.0.1"
-     * @return the IPv4 InetAddress corresponding to ip, null if ip is not a 
IPv4 address.
-     */
-    public InetAddress getInet4AddressFromString(String ip) {
-        String[] components = ip.split("[.]");
-        if (components.length != 4) {
-            return null;
-        }
-        byte[] addr = new byte[4];
-        for (int i = 0; i < 4; ++i) {
-            try {
-                addr[i] = Byte.parseByte(components[i]);
-            } catch (NumberFormatException e) {
-                return null;
-            }
-        }
-        try {
-            return Inet4Address.getByAddress(ip, addr);
-        } catch (UnknownHostException e) {
-            throw new AssertionError();
-        }
-    }
-
-    /**
-     * Return the IPv6 InetAddress corresponding to ip
-     *
-     * @param ip the ip address, e.g. "::1"
-     * @return the IPv4 InetAddress corresponding to ip, null if ip is not a 
IPv4 address.
-     */
-    public InetAddress getInet6AddressFromString(String ip) {
-        String[] components = ip.split(":");
-        if (components.length > 8) {
-            return null;
-        }
-        byte[] addr = new byte[16];
-        boolean substituted = false;
-        for (int i = 0; i < 16; ++i) {
-            if (components[i].isEmpty()) {
-                if (substituted) {
-                    // only one substitution
-                    return null;
-                }
-                i = 16 - i - (components.length - 1);
-            } else {
-                try {
-                    addr[i] = Byte.parseByte(components[i], 16);
-                } catch (NumberFormatException e) {
-                    return null;
-                }
-            }
-        }
-        try {
-            return Inet6Address.getByAddress(ip, addr);
-        } catch (UnknownHostException e) {
-            return null;
-        }
-    }
-
-
-    /**
-     * Get address from numeric textual IP address. May be IPv4 or IPv6
-     *
-     * @param ip textual IP address
-     * @return null if address is not numeric, the corresponding InetAddress 
object otherwise
-     */
-    public InetAddress getInetAddressFromString(String ip) {
-        // check for IPv4-address:
-        InetAddress inAddr = getInet4AddressFromString(ip);
-        if (inAddr != null) {
-            return inAddr;
-        }
-        return getInet6AddressFromString(ip);
-    }
-
-    /**
      * Callback object for hostname resolution.
      */
     public interface AddressCallback {
@@ -286,8 +218,8 @@
             cb.onFinished();
             return null;
         }
-
         InetAddress inetAddr = getInetAddressFromString(hostname);
+
         if (inetAddr != null) {
             cb.onAddress(inetAddr);
             cb.onFinished();

Modified: gnunet-java/src/org/gnunet/util/Scheduler.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Scheduler.java      2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/Scheduler.java      2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -54,10 +54,10 @@
         }
     }
 
-    public static final int EVENT_READ = 0, EVENT_WRITE = 1, EVENT_ACCEPT = 2, 
EVENT_CONNECT = 3;
-    public static final int[] eventToInterestOp = new 
int[]{SelectionKey.OP_READ, SelectionKey.OP_WRITE,
+    private static final int EVENT_READ = 0, EVENT_WRITE = 1, EVENT_ACCEPT = 
2, EVENT_CONNECT = 3;
+    private static final int[] eventToInterestOp = new 
int[]{SelectionKey.OP_READ, SelectionKey.OP_WRITE,
             SelectionKey.OP_ACCEPT, SelectionKey.OP_CONNECT};
-    public static final Reason[] eventToReason = new 
Reason[]{Reason.READ_READY, Reason.WRITE_READY,
+    private static final Reason[] eventToReason = new 
Reason[]{Reason.READ_READY, Reason.WRITE_READY,
             Reason.ACCEPT_READY, Reason.CONNECT_READY};
 
 

Modified: gnunet-java/src/org/gnunet/util/Server.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Server.java 2012-06-27 15:28:20 UTC (rev 
22349)
+++ gnunet-java/src/org/gnunet/util/Server.java 2012-06-27 15:30:13 UTC (rev 
22350)
@@ -45,6 +45,9 @@
     private List<DisconnectHandler> disconnectHandlers = new 
LinkedList<DisconnectHandler>();
     private ArrayList<Class> expectedMessages;
 
+    private boolean shutdownRequested;
+    private Cancelable acceptTask;
+
     public interface DisconnectHandler {
         void onDisconnect(ClientHandle clientHandle);
     }
@@ -56,8 +59,9 @@
 
         private int referenceCount = 0;
         private Connection.ReceiveHandle currentReceive;
-        private boolean shutdownRequested;
 
+        private boolean isMonitor;
+
         private ClientHandle(SocketChannel accept) {
             connection = new Connection(accept);
             clientTimeout = idleTimeout;
@@ -130,6 +134,9 @@
         public void disconnect() {
             connection.disconnect();
             Server.this.clients.remove(this);
+            for (DisconnectHandler dh : disconnectHandlers) {
+                dh.onDisconnect(this);
+            }
         }
 
         /**
@@ -153,7 +160,7 @@
         }
 
         public void markMonitor() {
-            // todo
+            this.isMonitor = true;
         }
     }
 
@@ -167,7 +174,7 @@
          *
          * @return handle of the client whose message is currently being 
visited
          */
-        public ClientHandle getSender() {
+        public final ClientHandle getSender() {
             return currentSender;
         }
 
@@ -182,11 +189,12 @@
                 new Scheduler.Task() {
                     @Override
                     public void run(Scheduler.RunContext ctx) {
-                        logger.debug("client connected");
+                        acceptTask = null;
                         try {
                             SocketChannel cli = srv.accept();
+
                             if (cli != null) {
-
+                                logger.debug("client connected");
                                 cli.configureBlocking(false);
                                 ClientHandle clientHandle = new 
ClientHandle(cli);
                                 clients.add(clientHandle);
@@ -199,7 +207,7 @@
                     }
                 });
         b.selectAccept(srv);
-        b.schedule();
+        acceptTask = b.schedule();
     }
 
 
@@ -210,10 +218,10 @@
      * @param idleTimeout  time after a client will be disconnected if idle
      * @param requireFound allow unknown messages to be received without 
disconnecting the client in response
      */
-    public Server(SocketAddress[] addresses, RelativeTime idleTimeout, boolean 
requireFound) {
+    public Server(List<SocketAddress> addresses, RelativeTime idleTimeout, 
boolean requireFound) {
         this.idleTimeout = idleTimeout;
         this.requireFound = requireFound;
-        listenSockets = new ArrayList<ServerSocketChannel>(addresses.length);
+        listenSockets = new ArrayList<ServerSocketChannel>(addresses.size());
         try {
             for (SocketAddress addr : addresses) {
                 ServerSocketChannel socket = ServerSocketChannel.open();
@@ -228,7 +236,15 @@
         }
     }
 
+    public Server(RelativeTime idleTimeout, boolean requireFound) {
+        this.idleTimeout = idleTimeout;
+        this.requireFound = requireFound;
+    }
 
+    public void addAcceptSocket(ServerSocketChannel sock) {
+        doAccept(sock);
+    }
+
     /**
      * Pass messages that the runabout can handle to it.
      * There can only be one runabout per message type.
@@ -256,7 +272,15 @@
      * once only 'monitor' clients are left.
      */
     public void stopListening() {
+        shutdownRequested = true;
+        // todo: shut down if only monitor clients left
+    }
 
+    public void destroy() {
+        for (ClientHandle h : new ArrayList<ClientHandle>(clients)) {
+            h.disconnect();
+        }
+        acceptTask.cancel();
     }
 
 }

Modified: gnunet-java/src/org/gnunet/util/Service.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Service.java        2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/src/org/gnunet/util/Service.java        2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -21,32 +21,99 @@
 package org.gnunet.util;
 
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.Channel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.SelectableChannel;
+import java.util.LinkedList;
+
 /**
  * Server the entry point class for every gnunet-java component providing 
services
  * to other components.
  */
 public abstract class Service extends Program {
+    private static final Logger logger = LoggerFactory
+            .getLogger(Service.class);
+
     private Server s;
-    
-    public Service(String[] args) {
+    private String serviceName;
+    private RelativeTime idleTimeout;
+    private boolean requireFound;
+
+    private Cancelable sigpipeTask;
+    private SelectableChannel sigpipeChannel;
+
+    public Service(String serviceName, RelativeTime idleTimeout, boolean 
requireFound, String[] args) {
         super(args);
-        // now create the server:
-        // s = new Server()
+        this.serviceName = serviceName;
+        this.idleTimeout = idleTimeout;
+        this.requireFound = requireFound;
+    }
 
-        // todo: install signal handling pipe
-    }
     
     public final Server getServer() {
         return s;
     }
 
-    public final void stop() {
+    public void stop() {
 
     }
 
+    public void start() {
+        super.start();
+        String ip4AddrList = getConfiguration().getValueString(serviceName, 
"ACCEPT_FROM");
+        String ip6AddrList = getConfiguration().getValueString(serviceName, 
"ACCEPT_FROM6");
+        int port = (int) getConfiguration().getValueNumer(serviceName, "PORT");
+
+        LinkedList<SocketAddress> addrs = new LinkedList<SocketAddress>();
+
+        for (String ip4Addr : ip4AddrList.split("[;]")) {
+            InetAddress addr = Resolver.getInetAddressFromString(ip4Addr);
+            addrs.add(new InetSocketAddress(addr, port));
+        }
+
+        for (String ip6Addr : ip6AddrList.split("[;]")) {
+            InetAddress addr = Resolver.getInetAddressFromString(ip6Addr);
+            addrs.add(new InetSocketAddress(addr, port));
+        }
+
+        s = new Server(addrs, idleTimeout, requireFound);
+
+        String pipeName = System.getenv("GNUNET_OS_CONTROL_PIPE");
+        if (pipeName != null) {
+            logger.debug("service started with control pipe");
+            FileChannel f;
+            try {
+                f = (new FileInputStream(pipeName)).getChannel();
+            } catch (FileNotFoundException e) {
+                logger.error("could not open control pipe");
+            }
+
+            Scheduler.TaskConfiguration t = new 
Scheduler.TaskConfiguration(RelativeTime.FOREVER,
+                    new SigpipeTask());
+            sigpipeTask = t.schedule();
+        }
+    }
+
+    public class SigpipeTask implements Scheduler.Task {
+
+        @Override
+        public void run(Scheduler.RunContext ctx) {
+            Scheduler.TaskConfiguration t = new 
Scheduler.TaskConfiguration(RelativeTime.FOREVER,
+                    new SigpipeTask());
+            sigpipeTask = t.schedule();
+        }
+    }
+
     /**
      * Override to implement the behavior of the Program.
      */
     public abstract void run();
-
-}
+}
\ No newline at end of file

Modified: gnunet-java/test/org/gnunet/testing/TestingSetupTest.java
===================================================================
--- gnunet-java/test/org/gnunet/testing/TestingSetupTest.java   2012-06-27 
15:28:20 UTC (rev 22349)
+++ gnunet-java/test/org/gnunet/testing/TestingSetupTest.java   2012-06-27 
15:30:13 UTC (rev 22350)
@@ -40,7 +40,7 @@
     @Test(expected = TestingSetup.SetupException.class)
     public void test_no_service() {
         TestingSetup testing = new TestingSetup();
-        TestingSubsystem ts = testing.startSubsystem("foobar _ !!!");
+        testing.startSubsystem("foobar _ !!!");
     }
 
     @Test(timeout = 1000)

Added: gnunet-java/test/org/gnunet/util/ClientServerTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/ClientServerTest.java                      
        (rev 0)
+++ gnunet-java/test/org/gnunet/util/ClientServerTest.java      2012-06-27 
15:30:13 UTC (rev 22350)
@@ -0,0 +1,86 @@
+package org.gnunet.util;
+
+import org.gnunet.testing.TestingServer;
+import org.gnunet.testing.TestingSetup;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class ClientServerTest {
+    @Test(timeout = 1000)
+    public void test_testing_server() {
+        final TestingSetup setup = new TestingSetup();
+        Program.configureLogging("DEBUG", null);
+        final TestingServer srv = setup.createServer();
+
+        final Wrapper<Boolean> gotMessage = new Wrapper<Boolean>(false);
+
+        srv.server.setHandler(new Server.MessageRunabout() {
+            public void visit(TESTMessage tm) {
+                gotMessage.set(true);
+                srv.server.destroy();
+            }
+        });
+
+        Scheduler.run(new Scheduler.Task() {
+            @Override
+            public void run(Scheduler.RunContext ctx) {
+                final Client cli = srv.createClient();
+                cli.notifyTransmitReady(RelativeTime.FOREVER,true, 0, new 
MessageTransmitter() {
+                    @Override
+                    public void transmit(Connection.MessageSink sink) {
+                        System.out.println("ntr!");
+                        sink.send(new TESTMessage());
+                    }
+
+                    @Override
+                    public void handleError() {
+
+                    }
+                });
+                System.out.println("done");
+            }
+        });
+
+        Assert.assertTrue(gotMessage.get());
+    }
+
+
+    @Test(timeout = 1000)
+    public void test_premature_disconnect() {
+        final TestingSetup setup = new TestingSetup();
+        Program.configureLogging("DEBUG", null);
+        final TestingServer srv = setup.createServer();
+
+        srv.server.notifyDisconnect(new Server.DisconnectHandler() {
+            @Override
+            public void onDisconnect(Server.ClientHandle clientHandle) {
+                srv.server.destroy();
+            }
+        });
+
+        Scheduler.run(new Scheduler.Task() {
+            @Override
+            public void run(Scheduler.RunContext ctx) {
+                final Client cli = srv.createClient();
+                cli.notifyTransmitReady(RelativeTime.FOREVER,true, 0, new 
MessageTransmitter() {
+                    @Override
+                    public void transmit(Connection.MessageSink sink) {
+                        sink.send(new TESTMessage());
+                        cli.disconnect();
+                    }
+
+                    @Override
+                    public void handleError() {
+                        Assert.fail();
+                    }
+                });
+
+            }
+        });
+    }
+}

Modified: gnunet-java/test/org/gnunet/util/ResolverTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/ResolverTest.java  2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/test/org/gnunet/util/ResolverTest.java  2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -22,6 +22,7 @@
 
 import org.gnunet.testing.TestingSetup;
 import org.gnunet.testing.TestingSubsystem;
+import org.junit.Assert;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -89,6 +90,5 @@
 
         assertTrue(finished2.get());
     }
-
 }
 

Modified: gnunet-java/test/org/gnunet/util/ServerExample.java
===================================================================
--- gnunet-java/test/org/gnunet/util/ServerExample.java 2012-06-27 15:28:20 UTC 
(rev 22349)
+++ gnunet-java/test/org/gnunet/util/ServerExample.java 2012-06-27 15:30:13 UTC 
(rev 22350)
@@ -22,6 +22,8 @@
 
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.util.Arrays;
+import java.util.LinkedList;
 
 import static org.gnunet.util.Server.*;
 
@@ -37,7 +39,8 @@
         new Program(args) {
             @Override
             public void run() {
-                Server s = new Server(new SocketAddress[]{new 
InetSocketAddress("127.0.0.1", 3456)},
+
+                Server s = new Server(Arrays.asList(new SocketAddress[]{new 
InetSocketAddress("127.0.0.1", 3456)}),
                         RelativeTime.MINUTE,
                         false);
                 s.setHandler(new Server.MessageRunabout() {

Modified: gnunet-java/tools/build
===================================================================
--- gnunet-java/tools/build     2012-06-27 15:28:20 UTC (rev 22349)
+++ gnunet-java/tools/build     2012-06-27 15:30:13 UTC (rev 22350)
@@ -8,14 +8,7 @@
 BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
 
 # collect all source files
-if [ "$GNJ_NO_TESTS" = "true" ]
-then
-  echo "building without tests"
-  SOURCES=`find "$BASEDIR/src/" -name "*.java"`
-else
-  echo "building with tests"
-  SOURCES=`find "$BASEDIR/src/" "$BASEDIR/test/" -name "*.java"`
-fi
+SOURCES=`find "$BASEDIR/src/" "$BASEDIR/test/" -name "*.java"`
 
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]