gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r18973 - in gnunet-java: . src src/org/gnunet src/org/gnune


From: gnunet
Subject: [GNUnet-SVN] r18973 - in gnunet-java: . src src/org/gnunet src/org/gnunet/construct src/org/gnunet/construct/parsers src/org/gnunet/exceptions src/org/gnunet/service src/org/gnunet/util src/org/gnunet/util/datastructures src/org/grothoff test/org/gnunet test/org/gnunet/construct test/org/gnunet/services
Date: Wed, 4 Jan 2012 11:51:06 +0100

Author: dold
Date: 2012-01-04 11:51:06 +0100 (Wed, 04 Jan 2012)
New Revision: 18973

Added:
   gnunet-java/.classpath
   gnunet-java/.project
   gnunet-java/gnunet-java.eml
   gnunet-java/src/log4j.properties
   gnunet-java/src/org/gnunet/construct/Double.java
   gnunet-java/src/org/gnunet/construct/Message.java
   gnunet-java/src/org/gnunet/construct/MessageHeader.java
   gnunet-java/src/org/gnunet/construct/MessageId.java
   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/DoubleParser.java
   gnunet-java/src/org/gnunet/exceptions/ConfigurationException.java
   gnunet-java/src/org/gnunet/service/NetworkSizeEstimationService.java
   gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java
   gnunet-java/src/org/gnunet/util/RelativeTimeMessage.java
   gnunet-java/test/org/gnunet/construct/QueryMessage.java
   gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java
   gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java
   gnunet-java/test/org/gnunet/construct/SizeTestMessage.java
   gnunet-java/test/org/gnunet/construct/StringMessage.java
   gnunet-java/test/org/gnunet/construct/VarTestMessage.java
   gnunet-java/test/org/gnunet/services/
   gnunet-java/test/org/gnunet/services/ConfigUtil.java
   gnunet-java/test/org/gnunet/services/NetworkSizeEstimationServiceTest.java
   gnunet-java/test/org/gnunet/services/StatisticsServiceTest.java
   gnunet-java/test/org/gnunet/services/nse.conf
   gnunet-java/test/org/gnunet/services/statistics.conf
Removed:
   gnunet-java/src/org/gnunet/messages/
Modified:
   gnunet-java/ISSUES
   gnunet-java/gnunet-java.iml
   gnunet-java/src/org/gnunet/construct/Construct.java
   gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FillParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java
   gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java
   gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java
   gnunet-java/src/org/gnunet/construct/parsers/Parser.java
   gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java
   gnunet-java/src/org/gnunet/construct/parsers/StringParser.java
   gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
   gnunet-java/src/org/gnunet/exceptions/MessageFormatException.java
   gnunet-java/src/org/gnunet/service/StatisticsService.java
   gnunet-java/src/org/gnunet/util/Client.java
   gnunet-java/src/org/gnunet/util/Configuration.java
   gnunet-java/src/org/gnunet/util/MessageReceiver.java
   gnunet-java/src/org/gnunet/util/RelativeTime.java
   gnunet-java/src/org/gnunet/util/RunaboutMessageReceiver.java
   gnunet-java/src/org/gnunet/util/Scheduler.java
   gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java
   gnunet-java/src/org/grothoff/Runabout.java
   gnunet-java/test/org/gnunet/construct/ConstructTest.java
Log:
NSE client almost working

Added: gnunet-java/.classpath
===================================================================
--- gnunet-java/.classpath                              (rev 0)
+++ gnunet-java/.classpath      2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/1.6"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="test"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/lib"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/junit4"/>
+       <classpathentry kind="con" 
path="org.eclipse.jdt.USER_LIBRARY/junit-4.10"/>
+       <classpathentry kind="output" path="out/production/gnunet-java"/>
+</classpath>

Added: gnunet-java/.project
===================================================================
--- gnunet-java/.project                                (rev 0)
+++ gnunet-java/.project        2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>gnunet-java</name>
+       <comment/>
+       <projects/>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments/>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>

Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/ISSUES  2012-01-04 10:51:06 UTC (rev 18973)
@@ -29,8 +29,8 @@
 * signals:
   http://www.ibm.com/developerworks/java/library/i-signalhandling/
 
+* can multiple tasks wait for the same channel? (problem with nio api)
 
-
 * exception hierarchy in Construct
 
 
@@ -110,3 +110,18 @@
 * when do we issue a transmit but cancel it (except in shutdown)
 
 
+=====
+
+ * what about unifying the many types of callbacks?
+ * what about async versions of some api calls? (e.g. for usage in a repl)
+
+
+
+ * header redundant -> introduce NetworkMessage with header automatically 
prepended?
+
+ * support for minimum message size in construct?
+
+ * generic support for subscriptions
+
+ * buffering scheme / when is "enough space" in a buffer?
+  * where to put messages in a buffer? at the beginning? at (capacity - size)?
\ No newline at end of file

Added: gnunet-java/gnunet-java.eml
===================================================================
--- gnunet-java/gnunet-java.eml                         (rev 0)
+++ gnunet-java/gnunet-java.eml 2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component inherit-compiler-output="true">
+       <output-test url="file://$MODULE_DIR$/out/test/gnunet-java"/>
+       <contentEntry url="file://$MODULE_DIR$">
+               <testFolder url="file://$MODULE_DIR$/test"/>
+       </contentEntry>
+</component>

Modified: gnunet-java/gnunet-java.iml
===================================================================
--- gnunet-java/gnunet-java.iml 2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/gnunet-java.iml 2012-01-04 10:51:06 UTC (rev 18973)
@@ -1,14 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
-    </content>
-    <orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="lib" level="project" />
-    <orderEntry type="library" name="junit4" level="application" />
-  </component>
-</module>
+<module classpath="eclipse" classpath-dir="$MODULE_DIR$" type="JAVA_MODULE" 
version="4" />
 

Added: gnunet-java/src/log4j.properties
===================================================================
--- gnunet-java/src/log4j.properties                            (rev 0)
+++ gnunet-java/src/log4j.properties    2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,9 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=DEBUG, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-5p %c:\n%m%n
\ No newline at end of file

Modified: gnunet-java/src/org/gnunet/construct/Construct.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Construct.java 2012-01-04 10:42:58 UTC 
(rev 18972)
+++ gnunet-java/src/org/gnunet/construct/Construct.java 2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -1,26 +1,18 @@
 package org.gnunet.construct;
 
+import org.gnunet.construct.parsers.*;
+import org.gnunet.exceptions.InterfaceViolationException;
+import org.grothoff.Runabout;
+
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.gnunet.construct.parsers.ByteFillParser;
-import org.gnunet.construct.parsers.FieldParser;
-import org.gnunet.construct.parsers.FixedSizeArrayParser;
-import org.gnunet.construct.parsers.IntegerParser;
-import org.gnunet.construct.parsers.NestedParser;
-import org.gnunet.construct.parsers.Parser;
-import org.gnunet.construct.parsers.SequenceParser;
-import org.gnunet.construct.parsers.StringParser;
-import org.gnunet.construct.parsers.VariableSizeArrayParser;
-import org.gnunet.exceptions.InterfaceViolationException;
-import org.gnunet.messages.Message;
-import org.grothoff.Runabout;
-
 /**
  * A version of Python's construct library for Java.
  *
@@ -83,9 +75,19 @@
         SequenceParser parser = new SequenceParser();
         pg.c = c;
 
-        Field[] fs = c.getFields();
+        if (!Modifier.isPublic(c.getModifiers())) {
+            throw new InterfaceViolationException("Construct messages must be 
declared public");
+        }
+
+        Field[] fs = c.getDeclaredFields();
         for (Field f : fs) {
             Annotation[] as = f.getAnnotations();
+            if (Modifier.isStatic(f.getModifiers())) {
+                continue;
+            }
+            if (!Modifier.isPublic(f.getModifiers())) {
+                throw new InterfaceViolationException(String.format("field %s 
of Message %s not declared public", f, c));
+            }
             if (as.length == 0) {
                 continue;
             }
@@ -229,6 +231,13 @@
             parser = new FixedSizeArrayParser(elemNumber, parser, f);
         }
 
+        public void visit(Double d) {
+            if(!field.getType().equals(java.lang.Double.TYPE)) {
+                throw new InterfaceViolationException("@Double target must be 
a primitive 'double' field");
+            }
+            parser = new DoubleParser(field);
+        }
+
         public void visit(VariableSizeArray vsa) {
             Field f = field;
             Class old_c = c;

Added: gnunet-java/src/org/gnunet/construct/Double.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Double.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Double.java    2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -0,0 +1,11 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Double {
+}

Copied: gnunet-java/src/org/gnunet/construct/Message.java (from rev 18939, 
gnunet-java/src/org/gnunet/messages/Message.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/Message.java                           
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/Message.java   2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -0,0 +1,9 @@
+package org.gnunet.construct;
+
+/**
+ * Base interface for all messages (anything that 'Construct' can serialize or
+ * deserialize). Really just an annotation, but also for sanity checking by the
+ * compiler.
+ */
+public interface Message {
+}

Copied: gnunet-java/src/org/gnunet/construct/MessageHeader.java (from rev 
18939, gnunet-java/src/org/gnunet/messages/MessageHeader.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageHeader.java                     
        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/MessageHeader.java     2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,13 @@
+package org.gnunet.construct;
+
+public class MessageHeader implements Message {
+
+    @FrameSize
+    @UInt16
+    public int messageSize;
+
+    @UInt16
+    public int messageType;
+
+    public static final int SIZE = 4;
+}

Copied: gnunet-java/src/org/gnunet/construct/MessageId.java (from rev 18939, 
gnunet-java/src/org/gnunet/messages/MessageId.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageId.java                         
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/MessageId.java 2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -0,0 +1,18 @@
+package org.gnunet.construct;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Assigns an id to a a message.
+ * 
+ * @author Florian Dold
+ *
+ */
address@hidden(RetentionPolicy.SOURCE)
address@hidden(ElementType.TYPE)
+public @interface MessageId {
+    int value();
+}

Copied: gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java 
(from rev 18939, 
gnunet-java/src/org/gnunet/messages/MessageIdAnnotationProcessor.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java      
                        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java      
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,81 @@
+package org.gnunet.construct;
+
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Creates a resource file 'MsgMap.txt' in the package messages.
+ */
address@hidden({"org.gnunet.construct.MessageId"})
address@hidden(SourceVersion.RELEASE_6)
+public class MessageIdAnnotationProcessor extends AbstractProcessor {
+    HashMap<java.lang.Integer, String> msgmap = new HashMap<java.lang.Integer, 
String>();
+
+    @Override
+    public boolean process(Set<? extends TypeElement> typeElements, 
RoundEnvironment roundEnvironment) {
+        if (roundEnvironment.errorRaised()) {
+            return false;
+        }
+
+        if (roundEnvironment.processingOver()) {
+            Filer filer = processingEnv.getFiler();
+            FileObject outfile;
+            try {
+                outfile = filer.createResource(StandardLocation.SOURCE_OUTPUT, 
"org.gnunet.construct", "MsgMap.txt");
+            } catch (IOException e) {
+                
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Could not 
create MsgMap.txt");
+                return false;
+            }
+
+            try {
+                Writer w = outfile.openWriter();
+                for (Map.Entry<java.lang.Integer, String> e : 
msgmap.entrySet()) {
+                    w.write("" + e.getKey() + "=" + e.getValue() + "\n");
+                }
+
+                DateFormat fmt =  new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+                w.write("# generated " + fmt.format(new Date()));
+                w.close();
+            } catch (IOException e) {
+                
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Could not 
write MsgMap.txt");
+            }
+
+            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, 
"message map written to " + outfile.toUri());
+
+        } else {
+            for (Element e : roundEnvironment.getRootElements()) {
+                Annotation ann = e.getAnnotation(MessageId.class);
+                if (ann != null) {
+                    int id = ((MessageId) 
e.getAnnotation(MessageId.class)).value();
+                    String fqn = e.asType().toString();
+                    if (msgmap.containsKey(id)) {
+                        
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
+                                String.format("duplicate @MessageId(%s) in %s 
and %s found",
+                                        id, fqn, msgmap.get(id)));
+                        return false;
+                    } else {
+                        msgmap.put(id, fqn);
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+}

Copied: gnunet-java/src/org/gnunet/construct/MessageLoader.java (from rev 
18939, gnunet-java/src/org/gnunet/messages/MessageLoader.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageLoader.java                     
        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/MessageLoader.java     2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,87 @@
+/*
+ *
+ * This file is part of GNUnet.
+ * (C) 2011 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 2, 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.construct;
+
+
+import org.gnunet.exceptions.InternalLogicError;
+import org.gnunet.exceptions.MessageFormatException;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.*;
+import java.net.URL;
+import java.util.HashMap;
+
+public class MessageLoader {
+    private static HashMap<java.lang.Integer, String> msgmap;
+
+    public static void loadMessageMap() {
+        URL loc = MessageLoader.class.getResource("MsgMap.txt");
+        if (loc == null) {
+            throw new RuntimeException("could not load message map");
+        }
+        BufferedReader in;
+        try {
+            in = new BufferedReader(new InputStreamReader(loc.openStream()));
+        } catch (IOException e) {
+            throw new RuntimeException("could not open message map");
+        }
+        String line;
+        try {
+            while((line = in.readLine()) != null) {
+                if (line.length() > 0 && line.charAt(0) == '#') {
+                    // skip comment
+                    continue;
+                }
+                String[] m = line.split("=");
+                if (m.length != 2) {
+                    throw new RuntimeException("invalid message map format");
+                }
+                int id = java.lang.Integer.parseInt(m[0].trim());
+                String fqn = m[1].trim();
+                msgmap.put(id, fqn);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("could not read message map");
+        }
+    }
+
+    public static Message loadMessage(int type, byte[] data, int offset) {
+        String className = msgmap.get(type);
+        if (className == null) {
+            // todo: error message
+            throw new MessageFormatException("don't know how to translate 
message of type " + type);
+        }
+        
+        ClassLoader cl = MessageLoader.class.getClassLoader();
+        Class msgClass;
+        try {
+            msgClass = cl.loadClass(className);
+        } catch (ClassNotFoundException e) {
+            throw new InternalLogicError("message class not found in 
classpath");
+        }
+        
+        return Construct.parseAs(data, offset, msgClass);
+    }
+}

Copied: gnunet-java/src/org/gnunet/construct/MsgMap.txt (from rev 18939, 
gnunet-java/src/org/gnunet/messages/MsgMap.txt)
===================================================================
--- gnunet-java/src/org/gnunet/construct/MsgMap.txt                             
(rev 0)
+++ gnunet-java/src/org/gnunet/construct/MsgMap.txt     2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -0,0 +1,6 @@
+987=org.gnunet.construct.SizeTestMessage
+291=org.gnunet.construct.QueryMessage
+323=org.gnunet.service.NSE_Update
+321=org.gnunet.service.NSE_Start
+3210=org.gnunet.construct.SimpleTestMessage
+# generated 2012/01/03 01:07:59
\ No newline at end of file

Modified: gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java    
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java    
2012-01-04 10:51:06 UTC (rev 18973)
@@ -1,13 +1,13 @@
 package org.gnunet.construct.parsers;
 
+import org.gnunet.construct.Construct;
+import org.gnunet.construct.Construct.ReflectionUtil;
+import org.gnunet.construct.Message;
+
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.util.List;
 
-import org.gnunet.construct.Construct;
-import org.gnunet.construct.Construct.ReflectionUtil;
-import org.gnunet.messages.Message;
-
 /**
  * Parse an array that takes up all the available space.
  * 

Added: gnunet-java/src/org/gnunet/construct/parsers/DoubleParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/DoubleParser.java              
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/DoubleParser.java      
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,46 @@
+package org.gnunet.construct.parsers;
+
+
+import org.gnunet.construct.Message;
+import org.gnunet.exceptions.InternalLogicError;
+
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+
+public class DoubleParser extends FieldParser{
+    public DoubleParser(final Field f) {
+        super(f);
+    }
+
+    @Override
+    public int getSize(Message srcObj) {
+        return 8;
+    }
+
+    @Override
+    public int parse(byte[] srcData, int offset, int frameOffset, Message 
dstObj) {
+        double d = ByteBuffer.wrap(srcData, offset, 8).getDouble();
+        try {
+            field.setDouble(dstObj, d);
+        } catch (IllegalAccessException e) {
+            throw new InternalLogicError("cannot access field (should have 
been caught in Construct)");
+        }
+        return 8;
+    }
+
+    @Override
+    public int write(byte[] dstData, int offset, Message srcObj) {
+        double d;
+        try {
+            d = field.getDouble(srcObj);
+        } catch (IllegalAccessException e) {
+            throw new InternalLogicError("field does not exist (should be 
caught in Construct)");
+        }
+        ByteBuffer.wrap(dstData, offset, 8).putDouble(d);
+        return 8;
+    }
+
+    @Override
+    public void patchSizeFields(Message m, int frameSize) {
+    }
+}

Modified: gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java       
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/FieldParser.java       
2012-01-04 10:51:06 UTC (rev 18973)
@@ -2,8 +2,6 @@
 
 import java.lang.reflect.Field;
 
-import org.gnunet.messages.Message;
-
 /**
  * Convenience super class for all parsers that store their result in the 
field 
  * of an object.

Modified: gnunet-java/src/org/gnunet/construct/parsers/FillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FillParser.java        
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/FillParser.java        
2012-01-04 10:51:06 UTC (rev 18973)
@@ -4,9 +4,8 @@
 import java.lang.reflect.Field;
 import java.util.List;
 
-import org.gnunet.construct.Construct;
 import org.gnunet.construct.Construct.ReflectionUtil;
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 /**
  * Parse an array that takes up all the available space.

Modified: gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java      
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java      
2012-01-04 10:51:06 UTC (rev 18973)
@@ -3,7 +3,7 @@
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 public class FixedSizeArrayParser extends FieldParser {
 

Modified: gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java     
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java     
2012-01-04 10:51:06 UTC (rev 18973)
@@ -1,12 +1,11 @@
 package org.gnunet.construct.parsers;
 
+import org.gnunet.construct.Construct.ReflectionUtil;
+import org.gnunet.construct.Message;
+
 import java.lang.reflect.Field;
 import java.util.Arrays;
 
-import org.gnunet.construct.Construct;
-import org.gnunet.construct.Construct.ReflectionUtil;
-import org.gnunet.messages.Message;
-
 public class IntegerParser extends FieldParser {
 
     public static final boolean UNSIGNED = false;

Modified: gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java      
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java      
2012-01-04 10:51:06 UTC (rev 18973)
@@ -2,7 +2,7 @@
 
 import java.lang.reflect.Field;
 
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 
 public class NestedParser extends FieldParser {

Modified: gnunet-java/src/org/gnunet/construct/parsers/Parser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/Parser.java    2012-01-04 
10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/Parser.java    2012-01-04 
10:51:06 UTC (rev 18973)
@@ -1,6 +1,6 @@
 package org.gnunet.construct.parsers;
 
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 
 public interface Parser {

Modified: gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java    
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java    
2012-01-04 10:51:06 UTC (rev 18973)
@@ -1,10 +1,9 @@
 package org.gnunet.construct.parsers;
 
-import java.lang.reflect.Field;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 /**
  * A Sequence of Parsers that operate on the same object.

Modified: gnunet-java/src/org/gnunet/construct/parsers/StringParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/StringParser.java      
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/StringParser.java      
2012-01-04 10:51:06 UTC (rev 18973)
@@ -3,7 +3,7 @@
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Field;
 
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 public class StringParser extends FieldParser {
 

Modified: 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2012-01-04 10:51:06 UTC (rev 18973)
@@ -3,9 +3,8 @@
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 
-import org.gnunet.construct.Construct;
 import org.gnunet.construct.Construct.ReflectionUtil;
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 
 public class VariableSizeArrayParser extends FieldParser {
     private final FieldParser elemParser;

Added: gnunet-java/src/org/gnunet/exceptions/ConfigurationException.java
===================================================================
--- gnunet-java/src/org/gnunet/exceptions/ConfigurationException.java           
                (rev 0)
+++ gnunet-java/src/org/gnunet/exceptions/ConfigurationException.java   
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,8 @@
+package org.gnunet.exceptions;
+
+
+public class ConfigurationException extends RuntimeException {
+    public ConfigurationException(String string) {
+        super(string);
+    }
+}

Modified: gnunet-java/src/org/gnunet/exceptions/MessageFormatException.java
===================================================================
--- gnunet-java/src/org/gnunet/exceptions/MessageFormatException.java   
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/exceptions/MessageFormatException.java   
2012-01-04 10:51:06 UTC (rev 18973)
@@ -9,4 +9,7 @@
  */
 public class MessageFormatException extends RuntimeException {
 
+    public MessageFormatException(String s) {
+        super(s);
+    }
 }

Added: gnunet-java/src/org/gnunet/service/NetworkSizeEstimationService.java
===================================================================
--- gnunet-java/src/org/gnunet/service/NetworkSizeEstimationService.java        
                        (rev 0)
+++ gnunet-java/src/org/gnunet/service/NetworkSizeEstimationService.java        
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,110 @@
+package org.gnunet.service;
+
+
+import org.gnunet.construct.*;
+import org.gnunet.construct.Double;
+import org.gnunet.exceptions.MessageFormatException;
+import org.gnunet.util.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+
+
+
+public class NetworkSizeEstimationService {
+
+    @SuppressWarnings("InstanceVariableMayNotBeInitialized")
+    @MessageId(NSE_Start.MSG_ID)
+    public static class NSE_Start implements Message {
+        public static final int MSG_ID = 321;
+
+        @Nested
+        public MessageHeader header;
+    }
+
+    @SuppressWarnings("InstanceVariableMayNotBeInitialized")
+    @MessageId(NSE_Update.MSG_ID)
+    public static class NSE_Update implements Message {
+        public static final int MSG_ID = 323;
+
+        @Nested
+        public MessageHeader header;
+
+        @UInt32
+        public int reserved;
+
+        @Nested
+        public AbsoluteTimeMessage timestamp;
+
+        @Double
+        public double sizeEstimate;
+
+        @Double
+        public double stdDeviation;
+    }
+
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(NetworkSizeEstimationService.class);
+    
+    class NSE_Receiver implements MessageReceiver {
+
+        @Override
+        public void process(Message msg) {
+            if (!(msg instanceof NSE_Update)) {
+                throw new MessageFormatException("got unexcpected message");
+            }
+            System.out.println("got message back!");
+        }
+
+        @Override
+        public void handleTimeout() {
+            // can't happen
+            throw new RuntimeException("unreachable");
+        }
+    }
+    
+    class NSE_Transmitter implements MessageTransmitter {
+
+        @Override
+        public void transmit(Client.MessageSink sink) {
+            logger.debug("ready to transmit");
+            NSE_Start m = new NSE_Start();
+            m.header = new MessageHeader();
+            m.header.messageType = NSE_Start.MSG_ID;
+            m.header.messageSize = MessageHeader.SIZE;
+            sink.send(m);
+
+
+            client.receive(new NSE_Receiver(), RelativeTime.FOREVER);
+        }
+
+        @Override
+        public void handleTimeout() {
+            // can't happen
+            throw new RuntimeException("unreachable");
+        }
+    }
+
+    public class NSE_Subscription {
+
+    }
+
+    public interface NSE_Subscriber {
+
+    }
+
+    public NSE_Subscription subscribe(NSE_Subscriber s) {
+        return null;
+    }
+
+    Client client;
+    
+    public NetworkSizeEstimationService(Configuration cfg) {
+        logger.debug("hi");
+        client = new Client("nse", cfg);
+        client.notifyTransmitReady(MessageHeader.SIZE, RelativeTime.FOREVER, 
true, new NSE_Transmitter());
+    }
+}

Modified: gnunet-java/src/org/gnunet/service/StatisticsService.java
===================================================================
--- gnunet-java/src/org/gnunet/service/StatisticsService.java   2012-01-04 
10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/service/StatisticsService.java   2012-01-04 
10:51:06 UTC (rev 18973)
@@ -6,128 +6,12 @@
 
 package org.gnunet.service;
 
-import java.util.LinkedList;
-
-import org.gnunet.util.AbsoluteTime;
 import org.gnunet.util.Client;
 import org.gnunet.util.Configuration;
-import org.gnunet.util.RelativeTime;
 
 public class StatisticsService {
 
-    enum ActionType {
-        GET, SET, WATCH, UPDATE
+    public StatisticsService(Configuration cfg) {
+        Client client = new Client("statistics", cfg);
     }
-
-    interface Callback {
-
-    }
-
-    class GetHandle {
-        private StatisticsService sh;
-        private String subsystem;
-        private String name;
-        private Callback cont;
-        private Iterator proc;
-        private AbsoluteTime timeout;
-        private ActionType type;
-        private int msize;
-
-        void cancel() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    interface Iterator {
-        public int call(String subsystem, String name, int value,
-                boolean is_persistent);
-    }
-
-    private class WatchEntry {
-        String subssytem;
-        String name;
-        Iterator proc;
-
-        public WatchEntry(final String subssytem, final String name,
-                final Iterator proc) {
-            this.subssytem = subssytem;
-            this.name = name;
-            this.proc = proc;
-        }
-    }
-
-    private final Client client;
-    private final RelativeTime backoff;
-
-    private final String subsystem;
-    private final Configuration cfg;
-
-    LinkedList<WatchEntry> watches;
-
-    LinkedList<GetHandle> actions;
-
-    GetHandle currentAction;
-
-    Client.TransmitHandle th;
-
-    public StatisticsService(final String subsystem, final Configuration cfg) {
-        this.backoff = new RelativeTime(1);
-        this.subsystem = subsystem;
-        this.cfg = cfg;
-        this.client = new Client("statistics", cfg);
-        this.watches = new LinkedList<StatisticsService.WatchEntry>();
-        this.actions = new LinkedList<StatisticsService.GetHandle>();
-    }
-
-    public GetHandle get(final String subsystem, final String name,
-            final RelativeTime timeout, final Callback cb, final Iterator it) {
-        final GetHandle h = new GetHandle();
-        h.sh = this;
-        h.subsystem = subsystem;
-        h.name = name;
-        h.cont = cb;
-        h.proc = it;
-        h.type = ActionType.GET;
-        insertGetHandle(h);
-        return h;
-    }
-
-    private void insertGetHandle(final GetHandle h) {
-        actions.add(h);
-        if (h == actions.getFirst()) {
-            scheduleAction();
-        }
-    }
-
-    private void scheduleAction() {
-        if (currentAction != null) {
-            return;
-        }
-        // XXX: What about reconnect stuff?
-        currentAction = actions.removeFirst();
-        // XXX: what about destruction?
-        //this.th = client.notifyTransmitReady(currentAction.msize, /* 
XXX:dummy */
-        //        null, true, /* XXX:dummy */null);
-
-        // XXX totally incomplete
-    }
-
-    public void set(final String name, final int value,
-            final boolean make_persistent) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void update(final String name, final int delta,
-            final boolean make_persistent) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void watch(final String subsystem, final String name,
-            final Iterator cb) {
-        throw new UnsupportedOperationException();
-        /*
-         * WatchEntry w = new WatchEntry(subsystem, name, cb);
-         * this.watches.add(w); scheduleWatchRequest(w);
-         */
-    }
 }

Added: gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java                    
        (rev 0)
+++ gnunet-java/src/org/gnunet/util/AbsoluteTimeMessage.java    2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,7 @@
+package org.gnunet.util;
+
+import org.gnunet.construct.Message;
+
+
+public class AbsoluteTimeMessage implements Message {
+}

Modified: gnunet-java/src/org/gnunet/util/Client.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Client.java 2012-01-04 10:42:58 UTC (rev 
18972)
+++ gnunet-java/src/org/gnunet/util/Client.java 2012-01-04 10:51:06 UTC (rev 
18973)
@@ -20,16 +20,19 @@
 package org.gnunet.util;
 
 import org.gnunet.construct.Construct;
+import org.gnunet.exceptions.ConfigurationException;
 import org.gnunet.exceptions.InterfaceViolationException;
-import org.gnunet.messages.Message;
-import org.gnunet.messages.MessageHeader;
-import org.gnunet.messages.MessageLoader;
+import org.gnunet.construct.Message;
+import org.gnunet.construct.MessageHeader;
+import org.gnunet.construct.MessageLoader;
 import org.gnunet.util.Scheduler.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.io.IOError;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.SelectorProvider;
 
@@ -38,10 +41,24 @@
  * Represents a connection to a service.
  */
 public class Client {
-    
-    final int HEADER_SIZE=4; // XXX: this is the wrong place for this
+    private static final Logger logger = LoggerFactory
+            .getLogger(Client.class);
 
 
+
+    private static final int INITIAL_BUFFER_SIZE = 128;
+
+    private SocketChannel chan;
+    private boolean recvActive = false;
+    private ByteBuffer recvBuffer = ByteBuffer.allocate(INITIAL_BUFFER_SIZE);
+
+
+    private TransmitHelperTask currentTransmit = null;
+    private Scheduler.TaskIdentifier nextTransmitTimeout = null;
+    private ByteBuffer transmitBuffer = 
ByteBuffer.allocate(INITIAL_BUFFER_SIZE);
+
+    private MessageTransmitter nextTransmitter;
+
     public class TransmitHandle {
         /**
          * Cancel a request for notification.
@@ -51,8 +68,9 @@
         }
     }
 
-    public class MessageSink {
-
+    public interface MessageSink {
+        public int getRemaining();
+        public void send(Message m);
     }
 
     private class ReceiveHelperTask implements Task {
@@ -63,23 +81,24 @@
         private MessageHeader msgh;
 
         public ReceiveHelperTask(MessageReceiver receiver, RelativeTime 
timeout) {
-
             this.receiver = receiver;
             this.timeout = timeout;
             recvActive = true;
         }
 
         public void dispatchMessage() {
-            receiver.process(MessageLoader.loadMessage(msgh.type, 
recvBuffer.array(), 0));
+            receiver.process(MessageLoader.loadMessage(msgh.messageType, 
recvBuffer.array(), 0));
         }
 
         @Override
         public void run(Context ctx) {
+            logger.debug("receiving in helper");
             if (ctx.reasons.contains(Scheduler.Reason.TIMEOUT)) {
                 receiver.handleTimeout();
             } else if (ctx.reasons.contains(Scheduler.Reason.READ_READY)) {
                 try {
-                    chan.read(recvBuffer);
+                    int n = chan.read(recvBuffer);
+                    logger.debug(String.format("read %s bytes", n));
                 } catch (IOException e) {
                     throw new RuntimeException("read failed");
                 }
@@ -88,11 +107,10 @@
                         recvActive = false;
                         dispatchMessage();
                     } else {
-                        msgh = (MessageHeader) 
Construct.parseAs(recvBuffer.array(), 0, MessageHeader.class);
+                        msgh = Construct.parseAs(recvBuffer.array(), 0, 
MessageHeader.class);
                         headerProcessed = true;
-                        // XXX: is the message size with or without the header`
-                        if (msgh.size > HEADER_SIZE) {
-                            recvBuffer.limit(msgh.size);
+                        if (msgh.messageSize > MessageHeader.SIZE) {
+                            recvBuffer.limit(msgh.messageSize);
                             schedule();
                         } else {
                             recvActive = false;
@@ -102,7 +120,6 @@
                 } else {
                     schedule();
                 }
-
             } else {
                 // XXX: what to do here?
                 throw new RuntimeException("receive failed");
@@ -110,12 +127,14 @@
         }
 
         public void schedule() {
+            logger.debug("schedulin receive");
             Scheduler.addRead(timeout, chan, this);
         }
+
+
     }
 
-    private class TransmitHelperTask implements Task {
-
+    private class TransmitHelperTask implements Task, MessageSink {
         private MessageTransmitter transmitter;
 
         public TransmitHelperTask(MessageTransmitter transmitter) {
@@ -124,21 +143,72 @@
 
         @Override
         public void run(Context ctx) {
+            try {
+                logger.debug("transmitting over chan " + 
transmitBuffer.position());
+                logger.debug("limit is" + transmitBuffer.limit());
+                chan.write(transmitBuffer);
+
+            } catch (IOException e) {
+                throw new IOError(e);
+            }
+            if (transmitBuffer.remaining() == 0) {
+                logger.debug("done transmitting " + transmitBuffer.position());
+                if (nextTransmitTimeout == null) {
+                    currentTransmit = null;
+                } else {
+                    transmitBuffer.clear();
+                    nextTransmitter.transmit(this);
+                    transmitBuffer.flip();
+                    schedule();
+                }
+            } else {
+                schedule();
+            }
         }
+
+
+        public void schedule() {
+            Scheduler.addWrite(RelativeTime.FOREVER, chan, this);
+        }
+
+        @Override
+        public int getRemaining() {
+            logger.debug("remaining not implemented");
+            return 0;
+        }
+
+        @Override
+        public void send(Message m) {
+            byte[] b = Construct.toBinary(m);
+            logger.debug("msg size="+b.length);
+            transmitBuffer.put(Construct.toBinary(m));
+            logger.debug("sending message");
+        }
     }
 
 
-    private final int INITIAL_BUFFER_SIZE=128;
-    SocketChannel chan;
-    boolean recvActive=false;
-    ByteBuffer recvBuffer = ByteBuffer.allocateDirect(INITIAL_BUFFER_SIZE);
+    public class ConnectTask implements Task {
+        @Override
+        public void run(Context ctx) {
+            tryConnect();
+        }
 
+        public void tryConnect() {
+            try {
+                boolean connected = chan.finishConnect();
+                if (!connected) {
+                    logger.debug("still not finished");
+                    Scheduler.addDelayed(new RelativeTime(5), this);
+                } else {
+                    logger.debug("finished connect");
+                }
+            } catch (IOException e) {
+                throw new IOError(e);
+            }
+        }
+    }
 
-    boolean transmitActive=false;
-    Object transmitQueue;
-    ByteBuffer transmitBuffer;
 
-
     /**
      * Get a connection with a service.
      *
@@ -148,29 +218,36 @@
     public Client(String serviceName, Configuration cfg) {
         // XXX: catch exn
         int port = (int) cfg.getValueNumer(serviceName, "PORT");
-        if (port > 65535 || port <= 0) {
-            // XXX: throw something else
-            throw new RuntimeException("invalid port");
+        if (port > 0xFFFF || port <= 0) {
+            throw new ConfigurationException(String.format("'%s' is not a 
valid Port", port));
         }
         String hostname = cfg.getValueString(serviceName, "HOSTNAME");
         try {
             chan = SelectorProvider.provider().openSocketChannel();
             chan.configureBlocking(false);
         } catch (IOException e) {
-            throw new RuntimeException("fatal: non-blocking network IO 
unavailable");
+            // this is fatal, no retry necessary
+            throw new IOError(e);
         }
-
         try {
-            // XXX: do we really want to connect here? is connect nonblocking?
-            chan.connect(new InetSocketAddress(hostname, port));
+            boolean ret = chan.connect(new InetSocketAddress(hostname, port));
+            if (ret) {
+                logger.debug("connection established right now");
+            } else {
+                logger.debug("must wait for connect to finish");
+            }
         } catch (IOException e) {
-            // todo: correct exception handling
-            throw new RuntimeException("connect failed");
+            // todo: retry until connect possible
+            throw new IOError(e);
         }
+        ConnectTask ct = new ConnectTask();
+        ct.tryConnect();
     }
 
     /**
-     * Wait until the service is running.
+     * Call the specified Task after connecting to the service successfully.
+     * <p/>
+     * XXX: the name is very undescriptive
      *
      * @param service_name name of the service to wait for
      * @param cfg          configuration to use
@@ -189,33 +266,72 @@
      * Receive one message from the service.
      *
      * @param receiver MessageReceiver that is responsible for the received 
message
-     * @param timeout  how long to wait until timing out (timeout calls 
MessageReceiver.timeout)
+     * @param timeout  timeout after which MessageReceiver.timeout will be 
called
      */
     public void receive(MessageReceiver receiver, RelativeTime timeout) {
         if (recvActive) {
             throw new InterfaceViolationException("receive must not be called 
while receiving");
         }
-        recvBuffer.reset();
-        recvBuffer.limit(HEADER_SIZE);
+        logger.debug("receive requested");
+        recvBuffer.clear();
+        recvBuffer.limit(MessageHeader.SIZE);
         ReceiveHelperTask rh = new ReceiveHelperTask(receiver, timeout);
         rh.schedule();
     }
+    
+    public class TransmitTimeoutHelper implements Task {
 
+        private MessageTransmitter transmitter;
+        private int size;
+
+        public TransmitTimeoutHelper(MessageTransmitter transmitter, int size) 
{
+            this.transmitter = transmitter;
+            this.size = size;
+        }
+
+        @Override
+        public void run(Context ctx) {
+            transmitter.handleTimeout();
+        }
+    }
+
+
+
     public TransmitHandle notifyTransmitReady(int size, RelativeTime timeout,
                                               boolean autoRetry, 
MessageTransmitter transmitter) {
-        TransmitHelperTask task = new TransmitHelperTask(transmitter);
-        Scheduler.addWrite(timeout, chan, task);
-        return null;
+        if (nextTransmitTimeout != null) {
+            throw new InterfaceViolationException(
+                    "previous transmit request must have completed before 
calling notifyTransmitReady again");
+        }
+        if (size > transmitBuffer.capacity()) {
+            throw new RuntimeException("buffer size too small");
+        }
+        if (currentTransmit == null) {
+            // we can just begin transmitting
+            TransmitHelperTask task = new TransmitHelperTask(transmitter);
+            transmitBuffer.clear();
+            transmitter.transmit(task);
+            logger.debug("AFTER: " + transmitBuffer.position());
+            transmitBuffer.flip();
+            task.schedule();
+            currentTransmit = task;
+        } else {
+            TransmitTimeoutHelper h = new TransmitTimeoutHelper(transmitter, 
size);
+            nextTransmitTimeout = Scheduler.addDelayed(timeout, h);
+            nextTransmitter = transmitter;
+        }
+        return new TransmitHandle();
     }
 
-    public void transmitAndGetResponse(Message msg, RelativeTime timeout, 
MessageReceiver receiver,
-                                       boolean autoRetry) {
-
+    public void shutdown() {
+        logger.warn("client shutdown not yet implemented");
     }
 
 
-    public void transmit(Message m, RelativeTime timeout, boolean autoRetry, 
IOContinuation cont) {
-        // not implemented / wait for c api
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        shutdown();
     }
 
 }

Modified: gnunet-java/src/org/gnunet/util/Configuration.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Configuration.java  2012-01-04 10:42:58 UTC 
(rev 18972)
+++ gnunet-java/src/org/gnunet/util/Configuration.java  2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -59,6 +59,10 @@
      */
     public Configuration() {
     }
+    
+    public Configuration(String s) {
+        parse(s);
+    }
 
     public boolean appendValueFilename(final String section,
                                        final String option, final String 
value) {
@@ -173,6 +177,7 @@
      * @param section
      * @param option
      * @throws ParsingError
+     * @return
      */
     public String getValueString(final String section, final String option) {
         if (!sections.containsKey(section)) {
@@ -242,8 +247,8 @@
     /**
      * Start with defaults, the parse configuration file.
      */
-    public boolean load(final String filename) {
-        throw new UnsupportedOperationException();
+    public boolean load(String filename) {
+        throw new UnsupportedOperationException("not implemented");
     }
 
     /**
@@ -253,7 +258,7 @@
      * @param filename name of the configuration file
      * @throws ParsingError
      */
-    public void parse(final String filename) {
+    public void parse(String filename) {
         Scanner sc;
         try {
             sc = new Scanner(new File(filename)).useDelimiter(delim);

Modified: gnunet-java/src/org/gnunet/util/MessageReceiver.java
===================================================================
--- gnunet-java/src/org/gnunet/util/MessageReceiver.java        2012-01-04 
10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/util/MessageReceiver.java        2012-01-04 
10:51:06 UTC (rev 18973)
@@ -20,16 +20,14 @@
 
 package org.gnunet.util;
 
-import org.gnunet.messages.Message;
-import org.grothoff.Runabout;
-import org.grothoff.Runabout;
+import org.gnunet.construct.Message;
 
 /**
  * 
  * @author Florian Dold
  * 
  */
-interface MessageReceiver {
+public interface MessageReceiver {
 
     /**
      * Method to call when we receive a message from the service.

Modified: gnunet-java/src/org/gnunet/util/RelativeTime.java
===================================================================
--- gnunet-java/src/org/gnunet/util/RelativeTime.java   2012-01-04 10:42:58 UTC 
(rev 18972)
+++ gnunet-java/src/org/gnunet/util/RelativeTime.java   2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -20,7 +20,6 @@
 
 package org.gnunet.util;
 
-import org.gnunet.messages.RelativeTimeMessage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -160,6 +159,7 @@
         return AbsoluteTime.now().add(this);
     }
 
+
     public RelativeTimeMessage toNBO() {
         long rval = this.rel_value;
         assert rval >= 0;
@@ -168,4 +168,8 @@
         }
         return new RelativeTimeMessage(rval);
     }
+
+    public boolean equals(Object o) {
+        return (o instanceof RelativeTime) && ((RelativeTime) 
o).getMilliseconds() == getMilliseconds();
+    }
 }

Copied: gnunet-java/src/org/gnunet/util/RelativeTimeMessage.java (from rev 
18939, gnunet-java/src/org/gnunet/messages/RelativeTimeMessage.java)
===================================================================
--- gnunet-java/src/org/gnunet/util/RelativeTimeMessage.java                    
        (rev 0)
+++ gnunet-java/src/org/gnunet/util/RelativeTimeMessage.java    2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,27 @@
+package org.gnunet.util;
+
+import org.gnunet.construct.Message;
+import org.gnunet.construct.UInt8;
+
+public class RelativeTimeMessage implements Message {
+
+    /**
+     * Value__ still in Java-byte order, needs to be converted to Network byte
+     * order by the Construct class.
+     */
+    @UInt8
+    public long value__;
+
+    public RelativeTimeMessage(final long value) {
+        this.value__ = value;
+    }
+
+    public RelativeTimeMessage(final RelativeTime t) {
+        if (t.equals(RelativeTime.FOREVER)) {
+            this.value__ = -1;
+        } else {
+            this.value__ = t.getMilliseconds();
+        }
+    }
+
+}

Modified: gnunet-java/src/org/gnunet/util/RunaboutMessageReceiver.java
===================================================================
--- gnunet-java/src/org/gnunet/util/RunaboutMessageReceiver.java        
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/util/RunaboutMessageReceiver.java        
2012-01-04 10:51:06 UTC (rev 18973)
@@ -1,6 +1,6 @@
 package org.gnunet.util;
 
-import org.gnunet.messages.Message;
+import org.gnunet.construct.Message;
 import org.grothoff.Runabout;
 
 /**

Modified: gnunet-java/src/org/gnunet/util/Scheduler.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Scheduler.java      2012-01-04 10:42:58 UTC 
(rev 18972)
+++ gnunet-java/src/org/gnunet/util/Scheduler.java      2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -23,6 +23,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOError;
 import java.io.IOException;
 import java.nio.channels.*;
 import java.nio.channels.spi.SelectorProvider;
@@ -34,9 +35,13 @@
  * @author Florian Dold
  */
 public class Scheduler {
+    private static final Logger logger = LoggerFactory
+            .getLogger(Scheduler.class);
+
     public enum Priority {
-        IDLE, BACKGROUND, DEFAULT, HIGH, UI, URGENT, SHUTDOWN, _COUNT;
-        static public final Priority KEEP = null;
+        IDLE, BACKGROUND, DEFAULT, HIGH, UI, URGENT, SHUTDOWN;
+        private static final int size = Priority.values().length;
+        public static final Priority KEEP = null;
     }
 
     public enum Reason {
@@ -55,17 +60,28 @@
         public void run(Context ctx);
     }
 
+
+    public static HashMap<SelectableChannel, SubscriberSet> subscriptions = 
new HashMap<SelectableChannel, SubscriberSet>();
+
+    static class SubscriberSet {
+        HashSet<TimeoutTask> readers = new HashSet<TimeoutTask>();
+        HashSet<TimeoutTask> writers = new HashSet<TimeoutTask>();
+    }
+
+    /**
+     * A TaskIdentifier represents a Task that will execute or has already 
been executed.
+     */
     public static class TaskIdentifier {
-        private final Task task;
-        private final TaskIdentifier prereq;
-        private final Task.Context ctx = new Task.Context();
+        public final Task task;
+        private TaskIdentifier prereq;
+        Task.Context ctx = new Task.Context();
         boolean liveness;
         Priority priority;
 
-        TaskIdentifier(final Task t, final Priority priority,
-                       final boolean liveness, final TaskIdentifier prereq) {
+        TaskIdentifier(Task t, Priority priority,
+                       boolean liveness, TaskIdentifier prereq) {
             this.task = t;
-            this.priority = priority == null ? active_task.priority : priority;
+            this.priority = (priority == null) ? getCurrentPriority() : 
priority;
             this.liveness = liveness;
             this.prereq = prereq;
         }
@@ -77,13 +93,17 @@
         void run() {
             active_task = this;
             task.run(ctx);
+            active_task = null;
         }
     }
 
-    static class TimeoutTask extends TaskIdentifier implements
+
+    private static class TimeoutTask extends TaskIdentifier implements
             Comparable<TimeoutTask> {
         final AbsoluteTime timeout;
         boolean selected = false;
+        Set<SelectableChannel> ws;
+        Set<SelectableChannel> rs;
 
         TimeoutTask(final Task t, final Priority p, final boolean liveness,
                     final TaskIdentifier prereq, final RelativeTime delay) {
@@ -93,7 +113,6 @@
 
         @Override
         public void cancel() {
-            super.cancel(); // in case the delay is already over
             pending_timeout.remove(this);
         }
 
@@ -102,33 +121,82 @@
             return new Long(this.timeout.getMilliseconds()).compareTo(o.timeout
                     .getMilliseconds());
         }
+
+        public void registerSelect(SelectableChannel sc, int op) {
+            SelectionKey key = sc.keyFor(selector);
+            if (key == null) {
+                try {
+                    sc.register(selector, op, subscriptions.get(sc));
+                } catch (ClosedChannelException e) {
+                    throw new IOError(e);
+                }
+            } else {
+                key.interestOps(key.interestOps() | op);
+            }
+        }
+
+        public void register() {
+            for (SelectableChannel sc : rs) {
+                SubscriberSet ss = subscriptions.get(sc);
+                if (ss == null) {
+                    ss = new SubscriberSet();
+                    subscriptions.put(sc, ss);
+                    ss.readers = new HashSet<TimeoutTask>(1);
+                } else {
+                    assert !ss.readers.contains(this);
+                }
+                ss.readers.add(this);
+                registerSelect(sc, SelectionKey.OP_READ);
+            }
+            for (SelectableChannel sc : ws) {
+                SubscriberSet ss = subscriptions.get(sc);
+                if (ss == null) {
+                    ss = new SubscriberSet();
+                    subscriptions.put(sc, ss);
+                    ss.writers = new HashSet<TimeoutTask>(1);
+                } else {
+                    assert !ss.writers.contains(this);
+                }
+                ss.writers.add(this);
+                registerSelect(sc, SelectionKey.OP_WRITE);
+            }
+        }
+
+        public void deregister() {
+            for (SelectableChannel sc : rs) {
+                SubscriberSet ss = subscriptions.get(sc);
+                assert ss != null;
+                assert ss.readers.contains(this);
+                ss.readers.remove(this);
+            }
+            for (SelectableChannel sc : ws) {
+                SubscriberSet ss = subscriptions.get(sc);
+                assert ss != null;
+                assert ss.writers.contains(this);
+                ss.writers.remove(this);
+            }
+
+        }
     }
 
-    private static final Logger logger = LoggerFactory
-            .getLogger(Scheduler.class);
 
-    // tasks that are waiting for a delay to pass, will be moved to 'pending'
-    // eventually
+    // tasks that are waiting for an event, which are executed anyway after 
the timeout has occured
     private static Queue<TimeoutTask> pending_timeout = new 
PriorityQueue<TimeoutTask>();
     // tasks that may be waiting for an event
     private static List<TaskIdentifier> pending = new 
LinkedList<TaskIdentifier>();
 
     // only valid while a task is executing
-    private static TaskIdentifier active_task;
+    private static TaskIdentifier active_task = null;
 
-    static Priority current_priority;
-    static boolean current_liveness;
-
     // number of tasks in the ready queue
     private static int ready_count = 0;
-    // for every priority, there is a list of tasks that is definitely ready to
-    // run
-    private static ArrayList<LinkedList<TaskIdentifier>> ready = new 
ArrayList<LinkedList<TaskIdentifier>>(
-            Priority._COUNT.ordinal());
 
+    // for every priority, there is a list of tasks that is definitely ready 
to run
+    final private static ArrayList<LinkedList<TaskIdentifier>> ready = new 
ArrayList<LinkedList<TaskIdentifier>>(Priority.size);
+
     static {
-        for (int i = 0; i < ready.size(); ++i) {
-            ready.set(i, new LinkedList<TaskIdentifier>());
+        for (int i = 0; i < Priority.size; ++i) {
+            ready.add(new LinkedList<TaskIdentifier>());
         }
     }
 
@@ -150,6 +218,15 @@
         }
     };
 
+
+    private static Priority getCurrentPriority() {
+        return (active_task == null) ? Priority.DEFAULT : active_task.priority;
+    }
+
+    private static boolean getCurrentLiveness() {
+        return (active_task == null) || active_task.liveness;
+    }
+
     public static TaskIdentifier addAfter(final TaskIdentifier prereq,
                                           final Task t) {
         return addSelect(Priority.KEEP, prereq, RelativeTime.ZERO, null, null,
@@ -164,7 +241,7 @@
                                        final EnumSet<Reason> reason) {
         assert active_task == null || active_task.priority != null;
         final TaskIdentifier tid = new TaskIdentifier(task, Priority.KEEP,
-                current_liveness, null);
+                getCurrentLiveness(), null);
         queueReady(tid);
     }
 
@@ -186,48 +263,72 @@
                 task);
     }
 
-    // should register the channels with the selector
+
+    /**
+     * Schedule a new task to be run with a specified delay or when any of
+     * the specified file descriptor sets is ready.  The delay can be used
+     * as a timeout on the socket(s) being ready.  The task will be
+     * scheduled for execution once either the delay has expired or any of
+     * the socket operations is ready.  This is the most general
+     * function of the "add" family.  Note that the "prerequisite_task"
+     * must be satisfied in addition to any of the other conditions.  In
+     * other words, the task will be started when
+     * <code>
+     * (prerequisite-run)
+     * && (delay-ready
+     * || any-rs-ready
+     * || any-ws-ready
+     * || (shutdown-active && run-on-shutdown) )
+     * </code>
+     *
+     * @param prio              how important is this task?
+     * @param prerequisite_task run this task after the task with the given
+     *                          task identifier completes (and any of our other
+     *                          conditions, such as delay, read or 
write-readiness
+     *                          are satisfied).  Use GNUNET_SCHEDULER_NO_TASK 
to not have any dependency
+     *                          on completion of other tasks.
+     * @param delay             how long should we wait? Use 
GNUNET_TIME_UNIT_FOREVER_REL for "forever",
+     *                          which means that the task will only be run 
after we receive SIGTERM
+     * @param rs                set of file descriptors we want to read (can 
be NULL)
+     * @param ws                set of file descriptors we want to write (can 
be NULL)
+     * @param task              main function of the task
+     * @param task_cls          closure of task
+     * @return unique task identifier for the job
+     *         only valid until "task" is started!
+     */
     public static TaskIdentifier addSelect(Priority p,
                                            TaskIdentifier prereq, RelativeTime 
delay,
                                            Set<SelectableChannel> rs, 
Set<SelectableChannel> ws,
                                            Task t) {
-        if (rs != null) {
-            for (final SelectableChannel s : rs) {
-                try {
-                    s.register(selector, SelectionKey.OP_READ, null);
-                } catch (final ClosedChannelException e) {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
-                }
-            }
+        TimeoutTask timeoutTask = new TimeoutTask(t, p, getCurrentLiveness(), 
prereq, delay);
 
-        }
-        if (ws != null) {
-            for (final SelectableChannel s : ws) {
-                try {
-                    s.register(selector, SelectionKey.OP_WRITE, null);
-                } catch (final ClosedChannelException e) {
-                    // TODO Auto-generated catch block
-                    e.printStackTrace();
-                }
-            }
+        timeoutTask.rs = rs == null ? 
Collections.<SelectableChannel>emptySet() : new HashSet<SelectableChannel>(rs);
+        timeoutTask.ws = ws == null ? 
Collections.<SelectableChannel>emptySet() : new HashSet<SelectableChannel>(ws);
 
+        timeoutTask.register();
+
+
+        if (delay.equals(RelativeTime.FOREVER) || (delay.getMilliseconds() == 
0)) {
+            pending.add(timeoutTask);
+        } else {
+            pending_timeout.add(timeoutTask);
         }
 
-        return new TimeoutTask(t, p, active_task.liveness,
-                prereq, delay);
+        return timeoutTask;
 
     }
 
     public static TaskIdentifier addRead(RelativeTime timeout,
                                          SelectableChannel chan, Task t) {
+        logger.debug("scheduling read");
         return Scheduler.addSelect(Priority.KEEP, null, timeout,
-                Collections.singleton(chan), Collections.EMPTY_SET, t);
+                Collections.singleton(chan), 
Collections.<SelectableChannel>emptySet(), t);
     }
 
     public static TaskIdentifier addWrite(RelativeTime timeout,
                                           SelectableChannel chan, Task t) {
-        return Scheduler.addSelect(Priority.KEEP, null, timeout, 
Collections.EMPTY_SET,
+        logger.debug("scheduling write");
+        return Scheduler.addSelect(Priority.KEEP, null, timeout, 
Collections.<SelectableChannel>emptySet(),
                 Collections.singleton(chan), t);
     }
 
@@ -235,7 +336,9 @@
                                                  Task t) {
         return addSelect(prio, null, RelativeTime.ZERO, null, null, t);
     }
+    
 
+
     /**
      * Check if the system is still life. Trigger shutdown if we have tasks, 
but
      * none of them give us lifeness.
@@ -259,7 +362,9 @@
             }
         }
 
-        if (!pending.isEmpty() || pending_timeout.isEmpty()) {
+        // do we have only tasks pending which are not alive?
+        if (!pending.isEmpty() || !pending_timeout.isEmpty()) {
+            logger.debug("tasks pending but not alive -- shutdown");
             shutdown();
             return true;
         }
@@ -267,17 +372,20 @@
         return false;
     }
 
+
+    /**
+     * Queue a Task for execution.
+     *
+     * @param tid
+     */
     private static void queueReady(TaskIdentifier tid) {
         assert tid.priority != null;
         int idx = tid.priority.ordinal();
         ready.get(idx).add(tid);
         ready_count++;
-    }
 
-    private static void register(TimeoutTask t) {
-        // register with selector
-        throw new UnsupportedOperationException();
-
+        pending.remove(tid);
+        pending_timeout.remove(tid);
     }
 
     /**
@@ -286,76 +394,112 @@
      * similar signals) will cause "GNUNET_SCHEDULER_shutdown" to be run after
      * the active task is complete. As a result, SIGTERM causes all active 
tasks
      * to be scheduled with reason "GNUNET_SCHEDULER_REASON_SHUTDOWN". 
(However,
-     * tasks added afterwards will execute normally!). Note that any particular
-     * signal will only shut down one scheduler; applications should always 
only
-     * create a single scheduler.
+     * tasks added afterwards will execute normally!).
      *
      * @param task task to run immediately
-     * @throws IOException
      */
-    public static void run(Task task) throws IOException {
-        current_priority = Priority.DEFAULT;
-        current_liveness = true;
+    public static void run(Task task) {
 
         RelativeTime timeout = RelativeTime.FOREVER;
 
-        addContinuation(task, EnumSet.of(Reason.STARTUP));
+        if (task != null) {
+            addContinuation(task, EnumSet.of(Reason.STARTUP));
+        }
 
         while (checkLiveness()) {
 
-            if (ready_count > 0) {
-                timeout = RelativeTime.ZERO;
-            } else {
-                timeout = RelativeTime.FOREVER;
-            }
+            timeout = (ready_count > 0) ? RelativeTime.ZERO : 
RelativeTime.FOREVER;
 
             AbsoluteTime now = AbsoluteTime.now();
 
+            // check if any timeouts occured
             while (true) {
                 TimeoutTask t = pending_timeout.peek();
-
-                if (t == null || t.timeout.compareTo(now) < 0) {
+                // timeout tasks are stored in a heap, we just have to look at 
the first task
+                if (t == null || t.timeout.equals(AbsoluteTime.FOREVER) || 
t.timeout.compareTo(now) < 0) {
                     break;
                 } else {
+                    t.deregister();
+                    t.ctx.reasons = EnumSet.of(Reason.TIMEOUT);
+                    queueReady(t);
                     pending_timeout.remove(t);
-                    pending.add(t);
-                    register(t);
                 }
             }
 
-            selector.select(timeout.getMilliseconds());
+            try {
+                // selector.select(0) would block indefinitely
+                if (timeout.getMilliseconds() == 0) {
+                    selector.selectNow();
+                } else {
+                    logger.debug("starting to select with timeout");
+                    selector.select(timeout.getMilliseconds());
+                    logger.debug("receive with timeout ended");
+                }
+            } catch (IOException e) {
+                System.out.println("hi");
+                throw new IOError(e);
+            }
 
             for (SelectionKey sk : selector.selectedKeys()) {
-                sk.cancel();
-                TimeoutTask tid = (TimeoutTask) sk.attachment();
-                if (!tid.selected) {
-                    queueReady(tid);
-                } else {
-                    tid.selected = true;
+                Object obj = sk.attachment();
+                assert (obj instanceof SubscriberSet);
+                SubscriberSet ss = (SubscriberSet) obj;
+                
+                
+                HashSet<TimeoutTask> executableTasks = new 
HashSet<TimeoutTask>();
+
+                if ((sk.interestOps() & SelectionKey.OP_READ) != 0) {
+                    for (TimeoutTask tt : ss.readers) {
+                        executableTasks.add(tt);
+                        if (tt.ctx.reasons == null) {
+                            tt.ctx.reasons = EnumSet.of(Reason.READ_READY);
+                        } else {
+                            tt.ctx.reasons.add(Reason.READ_READY);
+                        }
+                    }
+
                 }
+                if ((sk.interestOps() & SelectionKey.OP_WRITE) != 0) {
+                    for (TimeoutTask tt : ss.writers) {
+                        executableTasks.add(tt);
+                        if (tt.ctx.reasons == null) {
+                            tt.ctx.reasons = EnumSet.of(Reason.WRITE_READY);
+                        } else {
+                            tt.ctx.reasons.add(Reason.WRITE_READY);
+                        }
+                    }
+                }
+
+                for (TimeoutTask tt : executableTasks) {
+                    // tasks must do this themselve to cancel subscriptions to 
other channels
+                    tt.deregister();
+                    queueReady(tt);
+                }
             }
 
             runReady();
         }
     }
 
-    /*-
+
+    /**
      * Execute tasks until there either
-     * - there are no ready tasks
-     * - there is a pending task (which may be of higher priority)
+     * <ul>
+     * <li>there are no ready tasks</li>
+     * <li>there is a pending task (which may be of higher priority)</li>
+     * </ul>
      */
     private static void runReady() {
         do {
             if (ready_count == 0) {
                 return;
             }
-
-            // in contrast to the c implementation, p<=0 right here
-            for (int p = Priority._COUNT.ordinal(); p <= 0; p--) {
-                TaskIdentifier tid = ready.get(p).pollFirst();
-                if (tid == null) {
-                    break;
-                } else {
+            // start executing from the highest priority down to 0
+            for (int p = Priority.size - 1; p >= 0; p--) {
+                // execute all tasks with priority p
+                LinkedList<TaskIdentifier> queue = ready.get(p);
+                while (!queue.isEmpty()) {
+                    TaskIdentifier tid = queue.removeFirst();
                     ready_count--;
                     tid.run();
                 }
@@ -371,32 +515,7 @@
      * scheduled AFTER this call may still be delayed arbitrarily.
      */
     public static void shutdown() {
-        throw new UnsupportedOperationException();
+        logger.warn("shutdown not yet implemented");
     }
 
-    /**
-     * Get information about the current load of this scheduler. Use this
-     * function to determine if an elective task should be added or simply
-     * dropped (if the decision should be made based on the number of tasks
-     * ready to run).
-     * <p/>
-     * * @param p priority-level to query, use KEEP to query the level of the
-     * current task, use COUNT to get the sum over all priority levels
-     *
-     * @return number of tasks pending right now
-     */
-    public int getLoad(Priority p) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Obtain the reason code for why the current task was started. Will return
-     * the same value as the GNUNET_SCHEDULER_TaskContext's reason field.
-     * <p/>
-     * * @return reason(s) why the current task is run
-     */
-    public EnumSet<Reason> getReason() {
-        return active_task.ctx.reasons;
-    }
-
 }

Modified: gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java
===================================================================
--- gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java     
2012-01-04 10:42:58 UTC (rev 18972)
+++ gnunet-java/src/org/gnunet/util/datastructures/BloomFilter.java     
2012-01-04 10:51:06 UTC (rev 18973)
@@ -355,11 +355,8 @@
         if (this.bitSetSize != other.bitSetSize) {
             return false;
         }
-        if (this.bitset != other.bitset
-                && (this.bitset == null || !this.bitset.equals(other.bitset))) 
{
-            return false;
-        }
-        return true;
+        return !(this.bitset != other.bitset
+                && (this.bitset == null || !this.bitset.equals(other.bitset)));
     }
 
     /**

Modified: gnunet-java/src/org/grothoff/Runabout.java
===================================================================
--- gnunet-java/src/org/grothoff/Runabout.java  2012-01-04 10:42:58 UTC (rev 
18972)
+++ gnunet-java/src/org/grothoff/Runabout.java  2012-01-04 10:51:06 UTC (rev 
18973)
@@ -242,6 +242,7 @@
                     if (co == null)
                         throw new RunaboutException("Could not create/load 
dynamic code!");
                     result.put(viC, co);
+
                 }
             }
             me = me.getSuperclass();
@@ -324,11 +325,10 @@
                         ret[i] = (byte) '/';
                 return ret;
             }
-            byte[] ret = utf;
             for (int i = len - 1; i >= 0; i--)
-                if (ret[i] == (byte) '.')
-                    ret[i] = (byte) '/';
-            return ret;
+                if (utf[i] == (byte) '.')
+                    utf[i] = (byte) '/';
+            return utf;
         } catch (UnsupportedEncodingException uee) {
             throw new RunaboutException("UTF8 encoding not supported!?: " + 
uee);
         }
@@ -370,7 +370,8 @@
             loader_ = new ClassLoader() {
                 public Class<?> loadClass(String name)
                     throws ClassNotFoundException {
-                    if (name == "Code")
+                    //noinspection StringEquality
+                    if (name == "Code") // == works here, as both strings are 
guaranteed to be interned
                         return defineClass(null, code, 0, code.length);
                     return super.loadClass(name);
                 }

Modified: gnunet-java/test/org/gnunet/construct/ConstructTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/ConstructTest.java    2012-01-04 
10:42:58 UTC (rev 18972)
+++ gnunet-java/test/org/gnunet/construct/ConstructTest.java    2012-01-04 
10:51:06 UTC (rev 18973)
@@ -1,17 +1,10 @@
 package org.gnunet.construct;
 
-import java.math.BigInteger;
-
-import org.gnunet.messages.MessageHeader;
-import org.gnunet.messages.QueryMessage;
-import org.gnunet.messages.SimpleTestMessage;
-import org.gnunet.messages.SimpleTestMessage2;
-import org.gnunet.messages.SizeTestMessage;
-import org.gnunet.messages.StringMessage;
-import org.gnunet.messages.VarTestMessage;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.math.BigInteger;
+
 public class ConstructTest {
 
 
@@ -94,7 +87,7 @@
     public void test_QueryMessage() {
         QueryMessage qm = new QueryMessage();
         qm.header = new MessageHeader();
-        qm.header.type = 0x42;
+        qm.header.messageType = 0x42;
         qm.query = 0x43;
         qm.varsize = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
                 14, 15 };
@@ -105,8 +98,8 @@
 
         QueryMessage qm2 = Construct.parseAs(a, 0, QueryMessage.class);
 
-        Assert.assertEquals(qm.header.size, qm2.header.size);
-        Assert.assertEquals(qm.header.type, qm2.header.type);
+        Assert.assertEquals(qm.header.messageSize, qm2.header.messageSize);
+        Assert.assertEquals(qm.header.messageType, qm2.header.messageType);
         Assert.assertEquals(qm.query, qm2.query);
 
         Assert.assertArrayEquals(qm.varsize, qm2.varsize);
@@ -135,8 +128,8 @@
     public void test_MessageHeader() {
         MessageHeader h1 = new MessageHeader();
 
-        h1.size = 42;
-        h1.type = 52;
+        h1.messageSize = 42;
+        h1.messageType = 52;
 
         byte[] a = Construct.toBinary(h1);
 
@@ -146,7 +139,7 @@
 
         Assert.assertArrayEquals(a, b);
 
-        Assert.assertEquals(h1.size, h2.size);
-        Assert.assertEquals(h1.type, h2.type);
+        Assert.assertEquals(h1.messageSize, h2.messageSize);
+        Assert.assertEquals(h1.messageType, h2.messageType);
     }
 }

Added: gnunet-java/test/org/gnunet/construct/QueryMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/QueryMessage.java                     
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/QueryMessage.java     2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,14 @@
+package org.gnunet.construct;
+
address@hidden(0x123)
+public class QueryMessage implements Message {
+
+    @Nested
+    public MessageHeader header;
+
+    @UInt8
+    public int query;
+
+    @ByteFill
+    public byte[] varsize;
+}

Added: gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java                
                (rev 0)
+++ gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java        
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,17 @@
+package org.gnunet.construct;
+
address@hidden(3210)
+public class SimpleTestMessage implements Message {
+
+    @UInt8
+    public short v1;
+
+    @UInt8
+    public short v2;
+
+    @Nested
+    public SimpleTestMessage2 mn;
+    
+    @FixedSizeArray(length=5)
+    public SimpleTestMessage2[] mns;
+}

Added: gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java               
                (rev 0)
+++ gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java       
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,9 @@
+package org.gnunet.construct;
+
+//@MessageId(321)
+public class SimpleTestMessage2 implements Message {
+
+    @UInt32
+    public long value;
+
+}

Added: gnunet-java/test/org/gnunet/construct/SizeTestMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SizeTestMessage.java                  
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/SizeTestMessage.java  2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,15 @@
+package org.gnunet.construct;
+
address@hidden(987)
+public class SizeTestMessage implements Message {
+
+    @FrameSize
+    @UInt16
+    public long totalSize;
+
+    @UInt16
+    public long someValue;
+    
+    @ByteFill
+    public byte[] rest;
+}

Added: gnunet-java/test/org/gnunet/construct/StringMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/StringMessage.java                    
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/StringMessage.java    2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,12 @@
+package org.gnunet.construct;
+
+public class StringMessage implements Message {
+    @UInt8
+    public int num;
+    
+    @ZeroTerminatedString
+    public String str;
+    
+    @UInt8
+    public int num2;
+}

Added: gnunet-java/test/org/gnunet/construct/VarTestMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/VarTestMessage.java                   
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/VarTestMessage.java   2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,9 @@
+package org.gnunet.construct;
+
+public class VarTestMessage implements Message {
+    @UInt16
+    public long length;
+    
+    @VariableSizeArray(lengthField="length")
+    public SimpleTestMessage2[] msgs;
+}

Added: gnunet-java/test/org/gnunet/services/ConfigUtil.java
===================================================================
--- gnunet-java/test/org/gnunet/services/ConfigUtil.java                        
        (rev 0)
+++ gnunet-java/test/org/gnunet/services/ConfigUtil.java        2012-01-04 
10:51:06 UTC (rev 18973)
@@ -0,0 +1,52 @@
+package org.gnunet.services;
+
+import java.io.*;
+import java.net.URL;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dold
+ * Date: 1/3/12
+ * Time: 12:17 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ConfigUtil {
+    static File copyConfigResource(String resName) {
+        URL res = StatisticsServiceTest.class.getResource("nse.conf");
+
+        File tmpFile;
+
+        try {
+            tmpFile = File.createTempFile("cfg", null);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+
+        FileOutputStream tmpFileStream;
+        try {
+            tmpFileStream = new FileOutputStream(tmpFile);
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("temp file deleted externally");
+        }
+
+
+        InputStream resStream;
+        try {
+            resStream = res.openStream();
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+
+        int b;
+        try {
+            while ((b=resStream.read()) != -1) {
+                tmpFileStream.write(b);
+            }
+            tmpFileStream.close();
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+
+        return tmpFile;
+    }
+}

Added: 
gnunet-java/test/org/gnunet/services/NetworkSizeEstimationServiceTest.java
===================================================================
--- gnunet-java/test/org/gnunet/services/NetworkSizeEstimationServiceTest.java  
                        (rev 0)
+++ gnunet-java/test/org/gnunet/services/NetworkSizeEstimationServiceTest.java  
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,37 @@
+package org.gnunet.services;
+
+
+import org.gnunet.service.NetworkSizeEstimationService;
+import org.gnunet.util.Configuration;
+import org.gnunet.util.Scheduler;
+import org.junit.Test;
+
+import java.io.File;
+
+public class NetworkSizeEstimationServiceTest {
+    @Test
+    public void test_1() {
+
+        File tmpFile = ConfigUtil.copyConfigResource("nse.conf");
+
+        /*
+        Process p;
+        try {
+            String[] cmd = {"gnunet-service-statistics", "-c", 
tmpFile.getAbsolutePath()};
+            p = Runtime.getRuntime().exec(cmd);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+        */
+
+        Configuration cfg = new Configuration(tmpFile.getAbsolutePath());
+
+        NetworkSizeEstimationService svc = new 
NetworkSizeEstimationService(cfg);
+
+        System.out.println("starting scheduler");
+
+        Scheduler.run(Scheduler.NO_TASK);
+
+        // p.destroy();
+    }
+}

Added: gnunet-java/test/org/gnunet/services/StatisticsServiceTest.java
===================================================================
--- gnunet-java/test/org/gnunet/services/StatisticsServiceTest.java             
                (rev 0)
+++ gnunet-java/test/org/gnunet/services/StatisticsServiceTest.java     
2012-01-04 10:51:06 UTC (rev 18973)
@@ -0,0 +1,38 @@
+package org.gnunet.services;
+
+
+import org.gnunet.service.StatisticsService;
+import org.gnunet.util.Configuration;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOError;
+import java.io.IOException;
+
+public class StatisticsServiceTest {
+
+
+
+    @Test
+    public void test_1() {
+
+        
+        File tmpFile = ConfigUtil.copyConfigResource("statistics.conf");
+
+        Process p;
+        try {
+            String[] cmd = {"gnunet-service-statistics", "-c", 
tmpFile.getAbsolutePath()};
+            p = Runtime.getRuntime().exec(cmd);
+        } catch (IOException e) {
+            throw new IOError(e);
+        }
+
+        Configuration cfg = new Configuration(tmpFile.getAbsolutePath());
+
+
+
+        StatisticsService s = new StatisticsService(cfg);
+
+        p.destroy();
+    }
+}

Added: gnunet-java/test/org/gnunet/services/nse.conf
===================================================================
--- gnunet-java/test/org/gnunet/services/nse.conf                               
(rev 0)
+++ gnunet-java/test/org/gnunet/services/nse.conf       2012-01-04 10:51:06 UTC 
(rev 18973)
@@ -0,0 +1,24 @@
+[nse]
+AUTOSTART = YES
+PORT = 2097
+HOSTNAME = localhost
+HOME = $SERVICEHOME
+CONFIG = $DEFAULTCONFIG
+BINARY = gnunet-service-nse
+ACCEPT_FROM = 127.0.0.1;
+ACCEPT_FROM6 = ::1;
+# UNIXPATH = /tmp/test-nse-service-nse.unix
+# UNIX_MATCH_UID = YES
+# UNIX_MATCH_GID = YES
+PROOFFILE = $SERVICEHOME/.nse-proof
+HISTOGRAM = $SERVICEHOME/nse-history.log
+
+# How 'slowly' should the proof-of-work be constructed (delay
+# between rounds); sane values between 0 and ~1000.
+WORKDELAY = 5 ms
+
+# Note: changing any of the values below will make this peer
+# completely incompatible with other peers!
+INTERVAL = 1 h
+# 26 is about 10 minutes on a modern i7 (single-core)
+WORKBITS = 26
\ No newline at end of file

Added: gnunet-java/test/org/gnunet/services/statistics.conf
===================================================================



reply via email to

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