gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r23513 - in gnunet-java: . bin src/org/gnunet/construct src


From: gnunet
Subject: [GNUnet-SVN] r23513 - in gnunet-java: . bin src/org/gnunet/construct src/org/gnunet/construct/parsers src/org/gnunet/core src/org/gnunet/dht src/org/gnunet/hello src/org/gnunet/mesh src/org/gnunet/nse src/org/gnunet/peerinfo src/org/gnunet/requests src/org/gnunet/statistics src/org/gnunet/testing src/org/gnunet/transport src/org/gnunet/util src/org/gnunet/util/getopt src/org/grothoff test/org test/org/gnunet test/org/gnunet/construct test/org/gnunet/core test/org/gnunet/dht test/org/gnunet/nse test/org/gnunet/statistics test/org/gnunet/testing test/org/gnunet/util test/org/gnunet/util/getopt tools
Date: Thu, 30 Aug 2012 01:27:31 +0200

Author: dold
Date: 2012-08-30 01:27:31 +0200 (Thu, 30 Aug 2012)
New Revision: 23513

Added:
   gnunet-java/src/org/gnunet/construct/FixedSizeIntegerArray.java
   gnunet-java/src/org/gnunet/construct/ProtocolViolationException.java
   gnunet-java/src/org/gnunet/construct/parsers/FixedSizeIntegerArrayParser.java
   gnunet-java/src/org/gnunet/construct/parsers/package-info.java
   gnunet-java/src/org/gnunet/hello/HelloMessage.java
   gnunet-java/src/org/gnunet/hello/package-info.java
   gnunet-java/src/org/gnunet/mesh/ConnectHandler.java
   gnunet-java/src/org/gnunet/mesh/DisconnectHandler.java
   gnunet-java/src/org/gnunet/mesh/package-info.java
   gnunet-java/src/org/gnunet/peerinfo/package-info.java
   gnunet-java/src/org/gnunet/requests/package-info.java
   gnunet-java/src/org/gnunet/testing/package-info.java
   gnunet-java/src/org/gnunet/transport/package-info.java
   gnunet-java/src/org/gnunet/util/TestMessage.java
   gnunet-java/src/org/gnunet/util/getopt/Argument.java
   gnunet-java/src/org/gnunet/util/getopt/ArgumentAction.java
   gnunet-java/test/org/gnunet/construct/FillParserTest.java
   gnunet-java/test/org/gnunet/construct/FixedSizeTest.java
   gnunet-java/test/org/gnunet/construct/FrameSizeTest.java
   gnunet-java/test/org/gnunet/construct/SendMessageTest.java
   gnunet-java/test/org/gnunet/construct/StringTest.java
   gnunet-java/test/org/gnunet/construct/StringTuple.java
   gnunet-java/test/org/gnunet/construct/VariableSizeArrayTest.java
   gnunet-java/test/org/gnunet/nse/
   gnunet-java/test/org/gnunet/util/MeshTest.java
   gnunet-java/test/org/gnunet/util/StringsTest.java
Removed:
   gnunet-java/src/org/gnunet/construct/ByteFill.java
   gnunet-java/src/org/gnunet/construct/Constructable.java
   gnunet-java/src/org/gnunet/construct/FixedSizeByteArray.java
   gnunet-java/src/org/gnunet/construct/ProtocolViolation.java
   gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java
   gnunet-java/src/org/gnunet/construct/parsers/FixedSizeByteArrayParser.java
   gnunet-java/src/org/gnunet/util/HelloMessage.java
   gnunet-java/src/org/gnunet/util/TESTMessage.java
   gnunet-java/src/org/gnunet/util/getopt/Option.java
   gnunet-java/src/org/gnunet/util/getopt/OptionAction.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/VarTestMessage.java
   gnunet-java/test/org/nse/
Modified:
   gnunet-java/ISSUES
   gnunet-java/bin/gnunet-dht
   gnunet-java/src/org/gnunet/construct/Construct.java
   gnunet-java/src/org/gnunet/construct/Double.java
   gnunet-java/src/org/gnunet/construct/FixedSizeArray.java
   gnunet-java/src/org/gnunet/construct/Int16.java
   gnunet-java/src/org/gnunet/construct/Int32.java
   gnunet-java/src/org/gnunet/construct/Int64.java
   gnunet-java/src/org/gnunet/construct/Int8.java
   gnunet-java/src/org/gnunet/construct/IntegerFill.java
   gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java
   gnunet-java/src/org/gnunet/construct/MessageLoader.java
   gnunet-java/src/org/gnunet/construct/MessageUnion.java
   gnunet-java/src/org/gnunet/construct/MsgMap.txt
   gnunet-java/src/org/gnunet/construct/ReflectUtil.java
   gnunet-java/src/org/gnunet/construct/UInt16.java
   gnunet-java/src/org/gnunet/construct/UInt32.java
   gnunet-java/src/org/gnunet/construct/UInt64.java
   gnunet-java/src/org/gnunet/construct/UInt8.java
   gnunet-java/src/org/gnunet/construct/Union.java
   gnunet-java/src/org/gnunet/construct/UnionCase.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/IntegerFillParser.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/SequenceParser.java
   gnunet-java/src/org/gnunet/construct/parsers/StringParser.java
   gnunet-java/src/org/gnunet/construct/parsers/UnionParser.java
   gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
   
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeIntegerArrayParser.java
   gnunet-java/src/org/gnunet/core/ConnectNotifyMessage.java
   gnunet-java/src/org/gnunet/core/NotifyInboundTrafficMessage.java
   gnunet-java/src/org/gnunet/core/NotifyOutboundTrafficMessage.java
   gnunet-java/src/org/gnunet/dht/ClientGetMessage.java
   gnunet-java/src/org/gnunet/dht/ClientPutMessage.java
   gnunet-java/src/org/gnunet/dht/ClientResultMessage.java
   gnunet-java/src/org/gnunet/dht/DistributedHashTable.java
   gnunet-java/src/org/gnunet/dht/MonitorGetRespMessage.java
   gnunet-java/src/org/gnunet/dht/MonitorPutMessage.java
   gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java
   gnunet-java/src/org/gnunet/mesh/Mesh.java
   gnunet-java/src/org/gnunet/mesh/TunnelCreateMessage.java
   gnunet-java/src/org/gnunet/nse/NetworkSizeEstimation.java
   gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java
   gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java
   gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java
   gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java
   gnunet-java/src/org/gnunet/requests/Request.java
   gnunet-java/src/org/gnunet/statistics/Statistics.java
   gnunet-java/src/org/gnunet/testing/TestingServer.java
   gnunet-java/src/org/gnunet/testing/TestingSetup.java
   gnunet-java/src/org/gnunet/testing/TestingSubsystem.java
   gnunet-java/src/org/gnunet/transport/Transport.java
   gnunet-java/src/org/gnunet/util/AbsoluteTime.java
   gnunet-java/src/org/gnunet/util/Client.java
   gnunet-java/src/org/gnunet/util/Configuration.java
   gnunet-java/src/org/gnunet/util/Connection.java
   gnunet-java/src/org/gnunet/util/Continuation.java
   gnunet-java/src/org/gnunet/util/HashCode.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/RunaboutUtil.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/src/org/gnunet/util/Strings.java
   gnunet-java/src/org/gnunet/util/UnknownMessageBody.java
   gnunet-java/src/org/gnunet/util/getopt/Parser.java
   gnunet-java/src/org/grothoff/Runabout.java
   gnunet-java/src/org/grothoff/package-info.java
   gnunet-java/test/org/gnunet/construct/ByteFillMessage.java
   gnunet-java/test/org/gnunet/construct/ConstructTest.java
   gnunet-java/test/org/gnunet/construct/QueryMessage.java
   gnunet-java/test/org/gnunet/core/CoreTest.java
   gnunet-java/test/org/gnunet/dht/DHTTest.java
   gnunet-java/test/org/gnunet/nse/NSETest.java
   gnunet-java/test/org/gnunet/statistics/StatisticsTest.java
   gnunet-java/test/org/gnunet/testing/TestingSetupTest.java
   gnunet-java/test/org/gnunet/util/ClientServerTest.java
   gnunet-java/test/org/gnunet/util/FilePipeExample.java
   gnunet-java/test/org/gnunet/util/ResolverTest.java
   gnunet-java/test/org/gnunet/util/ServerExample.java
   gnunet-java/test/org/gnunet/util/getopt/GetoptTest.java
   gnunet-java/tools/build
   gnunet-java/tools/coverage
Log:
many bug fixes, server/service working, signal pipe working

Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/ISSUES  2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,248 +1,106 @@
 
-* I'm currently confused about the statistics API bug (from C), and how 
shutdown/disconnect is/should be handled.
-* gnunet vs GNUnet, gnunet-java project name
-* I'm currently trying to increase the robustness of the service APIs,
-  discuss behavior in some cases
-* packaging requirements
+in gnunet-java-ext there is a working example of a service and a corresponding 
client program, that actually work ;)
+ * simple greeting server, client gives name and server returns greeting
+ * illustrates using program/service, using the configuration, creating 
messages
+ * works with os control pipe / arm
 
+arm-4477 WARNING Configuration file `(null)' for service `greeting' not valid: 
option missing
 
-====================================================================
+even when not using the signal pipe, does arm really kill processes?
+ * arm does never seem to send a sigkill if process does not respond
+ * sometimes arm command hangs!
 
-* IzPack is ~15MB, do we really want to have it in the svn repo?
-No, env var.
+ $ gnunet-arm -c config/greeting.conf -k greeting -LDEBUG
+ Aug 29 19:25:22-808046 arm-api-5971 INFO Stopping service `greeting' within 
60000 ms
+ Service `greeting' was already not running.
 
-* the Runabout can now be an anonymous inner class
- * implementation overhead: for public subclasses only constant overhead in 
the Runabout constructor
- * for private/anonymous inner classes: 10-20% overhead, measured over 100M 
calls
- * only issue left: visit methods have to be public, but this is a non issue.
 
-* review the RequestQueue mechanism
+Aug 29 18:21:19-505909 arm-4751 ERROR Failed to start service `greeting'
+Service `greeting' has been started.
 
-* Statistics:
- * currently watches can't be canceled on the service level, only on the api 
level, is this intentional?
-=> fine for now
+logging with arm: what gets piped to where
+ * seems like service stdout->/dev/null, service stderr->arm stderr
 
-* DHT:
- * getStart timeout does not really make sense (why timeout for transmission 
to the service,
-   but not for retrieval of answers?)
-   Is this just a documentation error?
-=> fine to NOT have the timeout argument in the Java API
+Construct: has gotten very complex, i'm currently trying to trace a particular 
bug
+ * UPDATE: bug is gone!
+ * unit tests for construct have gotten better, still not good enough
+ * FrameSize
+ * recursive messages
+  * indirect recursion (over unions) (see core.SendMessage) works
+  * direct recursion has problems (see test/org.gnunet.construct.FrameSizeTest)
 
-* core:
- * what happens if during a transmission the service disconnects? should we 
retry?
-=> "no"
+Question: Is all this too complicated? Should I invest the time to fix things 
as they are now intended, or should
+we simplify?
 
-* with the changes in ARM there is no way to restart gnunet with arm if some 
client is misbehaving
-=> SVN UP
+* found some problems with timeouts in client/connection.
+ * should i write unit-tests for this timing-stuff?
+ * UPDATE: should be fixed now!
 
-* I'm often getting
-  May 09 09:21:49-194786 util-11121 WARNING `socket' failed at 
connection.c:892 with error: Too many open files
-=> SVN UP
+* program/service in general:
+ * how to handle the return value of main?
+ * java has no return value for main
+ * we must use System.exit(n) instead
+ * how about a (Program/Service).exit(n) that does cleanup and then calls 
System.exit(n)?
 
+* configuration: what is $DEFAULTCONFIG? and CONFIG=?
 
-==================
+mesh:
+ * we can't use multipe instances of org.gnunet.mesh.Mesh to test the API
+  * the local peer can't be the peer on the other end!
+  * the C-api has practically no coverage on mesh_api.c
+  * see below for a suggestion!
+ * LOCAL_TUNNEL_CREATE was used for two things, creating tunnels and being 
notified about incoming tunnels
 
-#!bin/sh
-java -jar $GNUNET_JAVA_PREFIX/lib/gnunet.jar
+* extending org.gnunet.testing so that multiple peers can be started and 
communicate with each other!
+ * the C-testing-api allows to create multiple peers, but they don't seem to 
be able to communicate with each
+   other!
+ * => the peers should somehow exchange their hellos / use a shared directory 
for the hellos
 
+ testbed vs testing: is this correct?
+  * testbed for large-scale testing across many "real" nodes
+  * testing for testcases on one host
 
-==================
+* test coverage approaching a better state, any feedback?
 
-#!/bin/sh
-if test -z $GNUNET_JAVA_PREFIX
-then
-  GNUNET_JAVA_PREFIX=%INSTALL_PREFIX%
-fi
-java -jar $GNUNET_JAVA_PREFIX/lib/gnunet.jar
+* I think there should be some documentation in addition to the source code 
and the tutorial
+ * what would be the preferred format for such documentation? latex?
+ * (considering that they perhaps should end up on a website / should be 
browsable)
+ * examples:
+  * how do unions work in construct?
+  * other stuff in construct
+  * how does annotation processing work?
+  * project layout - what goes where
+   * as there is no standard java project layout
 
 
+rationale for putting org.gnunet.testing in the src/-tree, not in test/:
+ * when developing an extension for gnunet-java, the developers may want to 
access the testing functionality from
+   the jar, so it should be included there!
+ * the code itself is tested, we want coverage etc.
 
-===========================================================
+* is there an effort to document what hostkeys files are etc.?
 
-* @UNIXONLY@ PORT = 2089 in src/util/resolver.conf.on
- * what's the purpose? we also need this line to be enabled on JAVAPORT
+continuous integration: using Jenkins (=Hudson, forked away from Oracle)
+ * easier to configure than buildbot
+ * support for JUnit out-of-the-box
+ * support for cobertura via plugin
 
-* something I didn't think through from the beginning:
-  how should unknown message types be handled by message handlers?
- * sometimes we want to see the message (e.g. in server), sometimes it is an 
error
- * alternative 1: signal an error to the message handler, somehow pass the 
original message
- * alternative 2: pass a special UnknownMessage to the message handler, filter 
it for higher-level
-   APIs and signal an error.
+build system: still maintaining bash scripts, trying out gradle
+ * faster builds, build scripts far easier to read/write
+ * no integration with cobertura :(
+ * gradle has excellent Ant integration => Coverage (bash wrapper not very 
usable)
+ * can generate project files for eclipse/intellij
 
+what's next?
+ * some actual stuff built with gnunet-java?
 
-* the recvDone is kind of clunky (see test/org.gnunet.util.ServerExample)
+* general question: when should an api use per-connection receive, and 
per-service-receive?
 
-* finally core/statistics/dht/resolver/... have unit tests!
-  (and coverage works again, but i can't access the cobertura via ssh yet)
- * currently most test rely on a running gnunet, and use the default 
configuration
- * alternative approach:
-  * configuration is copied from resource (may be in a jar!) to a temp file, 
then passed on the command
-    line to gunet-service-*
-  * useful to test behavior on disconnects
-  * problem: java sucks at managing processes, processes stay alive if we 
abort a test
- * dht get: can we assume that "our" peer immediately stores the value?
+does this make sense / do we need it:
+ * support in the scheduler for communicating asynchronously with other 
processes via stdin/stdout/stderr
+  * currently only used in testing, uses blocking i/o
 
-* naming: when do we use destroy, when do we use disconnect, or is this 
arbitrary?
-  start-stop, create-destroy, connect-disconnect; constructor: fine, 
destructor: see C API
+* stream is implemented as a library, not as a service
+ * why?
+ * should GNUnet-java also implement it?
 
-* implications of using exceptions in callbacks
- * esp. when the exception is non-fatal, i.e. the exception is caught, 
handled, and the program continues
- * java exceptions have no restarts, may leave gnunet-java in inconsistent 
state; FINALLY!
-
-* how to test callbacks? we do not only need to test for the right values, but 
also check that callback has actually
-  been called.
- * first approach: thow a TestSuccess exception, discarded (see above)
- * current approach: build a list of assertions, check assertions after 
scheduler is done.
-  * each assertion stores whether it already succeeded and a message
-
-
-* finalziers: used to destroy object. lead to heisenbug/double disconnect. now 
policy: check if object
-  has been disposed of properly, otherwise log a warning.
- * cannot guarantee cleanup anyway
-   (java behavior: run finalizers iff unreachabla during gc, may never happen, 
finalizers on jvm shutdown deprecated)
-
-
-* regarding peerinfo
-  * i don't fully understand how HELLOs work.
-
-* what are the next important services to implement? (probably mesh, peerinfo, 
transport)
-
-
-* i'm currently considering to use the google guava library
- * Apache License 2.0
- * con: large (1.8MB jar)
-  * but: unused class files could be stripped from the jar, e.g. using ProGuard
- * would replace the apache commons io library
- * contains collections used throughout gnunet
-  * bloomfilter
-  * multimap, alleviates the boilerplate code when dealing with hashmaps of 
lists
- * methods to deal with "signed" primitives
- * dealing with files (e.g. copying)
- * redirecting i/o streams from/to files (when issuing external commands)
- * hashing utilities
- * tables (mapping from key pair to value), would replace nested Maps in e.g. 
Configurations
- * ...
-
-
-
-
-* long-term todos:
- * refactor the Construct implementation, implement the "nicer" syntax
- * refactor the getopt implementation
-
-
-
-
-============================================================
-
-* tests now run on the cobertura account :)
- * see https://gnunet.org/cobertura/
- * gnunet needs to compiled with --disable-nls to work on the server
- * cronjob added
- * could/should we report the success of JUnit tests?
-  * (as somehow my bugs only seem to show when running on another system ;)
-
-* gnunet-java now can now start/restart services for testing with the testing 
wrapper executable
- * i duplicated the code for GNUNET_TESTING_service_run_restartable
-  * now passes the Peer to main, which can start/stop it
-  * probably also should pass the config file name (not only the handle)
-   * how about a GNUNET_TESTING_peer_get_config_path?
- * what about windows?
-
-* server/service:
- * needed for testing the server: getting an unused port with java
- * how do we test the signal pipeline?
-  * probably with runin arm in a testing peer, but then we would also have to 
talk to arm
-
-
-the following notes are old:
-* we are still not able to test "temporary destruction"
- * because every time a new port may be generated
- * we need a way to kill a service and run it with the same config
- * now implemented!
-* review if everything in Makefile.am is correct
- * what is *_DEPENDENCIES vs *_LDADD?
-* how do we get a handle to stdin (in a non-hacky way) that can be selected on 
by scheduler?
-* c-getopt question: GNUNET_GETOPT_run returns index of first non-option.
-  so options and non-options may not be mixed?
-* i have to manually write the config file, why isn't there a way to get the
-  file name, not just the ConfigurationHandle?
-* could we get a confirmation that a service *really* is dead?
- * or is this guaranteed if TESTING_service_run returns?
- * otherwise there is no way to reliably test behavior on interrupted 
connection
-* TESTING_service_run does not indicate that the service could not be run!
- * just logs an error
- * currently we check availability of data on stderr.
-
-
-PEERINFO_GET vs PEERINFO_GET_ALL
- * if we have PEERINFO_GET_ALL, why is the peer-field in ListPeerMessage(with 
type=PEERINFO_GET) empty?
-
-
-* are peerinfo requests queued?
- * i remember discussing peerinfo as a compilicated example for a general 
message queueing implementation. why?
- * if we have to queue: how about a "choke/release" for the outgoing message 
queue?
-  * otherwise we don't know which requests belongs to which response
-* 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
-
----------------------------------------------------------------
-
-* reference count / receive_done behavior is a bit strange / confusing
- * clients are disconnected only when refcnt==0 *and* shutdown is requested?
- * behavior on receive done: when success=1 but refcnt=0, why don't we 
disconnect the client?
-
-   /**
-    * Was processing if incoming messages suspended while
-    * we were still processing data already received?
-    * This is a counter saying how often processing was
-    * suspended (once per handler invoked).
-    */
-
-I don't understand that comment!
-
-
-
-* im currently confused about the different layers of GNUnet / I don't get the 
big picture
- * e.g. transport's distance vector plugin vs mesh
- * peerinfo / mesh
- * assuming a large network, doesn't a client have to store a large amout of 
information?
-
-* how to test MESH?
- * maybe talk to Harsha about testbed? :)
-
-* interesting things happen with JUnit
- * failure of one test causes timeout in another
-
-* review org.gnunet.testing
-
-cp a x ; cp b x
-is not the same as
-cp b x ; cp a x
-if x does not exist prior to copying

Modified: gnunet-java/bin/gnunet-dht
===================================================================
--- gnunet-java/bin/gnunet-dht  2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/bin/gnunet-dht  2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,11 +1,11 @@
 #!/bin/sh
 
-DIR=`dirname $0`
 
 if [ "%GNJ_INSTALLED" = "true" ];
 then
     export CLASSPATH="%INSTALL_PATH/share/java/*"
 else
+    DIR=`dirname $0`
     export CLASSPATH="$DIR/../build/:$DIR/../lib/*"
 fi
 

Deleted: gnunet-java/src/org/gnunet/construct/ByteFill.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/ByteFill.java  2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/ByteFill.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -1,39 +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.construct;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Fills a byte array with the remaining data in the current frame.
- * Annotation target must be of type "byte[]"
- *
- * Deprecated, you should use @IntegerFill(false, 8), or @FillWith @UInt8 once 
it is available.
- * 
- * @author Florian Dold
- */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
-public @interface ByteFill {
-}

Modified: gnunet-java/src/org/gnunet/construct/Construct.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Construct.java 2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Construct.java 2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -50,7 +50,7 @@
 
 
 /**
- * Parse and write the binary representation of java classes, as defined by 
org.gnunet.construct.*-Annotations
+ * Parse and write the binary representation of java classes, as defined by 
org.gnunet.construct.*-annotations
  * on their members.
  *
  * @author Christian Grothoff
@@ -62,10 +62,19 @@
             .getLogger(Construct.class);
 
 
-    private static HashMap<Class<? extends Message>, Parser> parserCache = new 
HashMap<Class<? extends Message>,
+    private static Map<Class<? extends Message>, Parser> parserCache = new 
HashMap<Class<? extends Message>,
             Parser>(100);
 
+
     /**
+     * The class Construct is not intended to be instantiated, this its 
constructor is private.
+     */
+    private Construct() {
+
+    }
+
+
+    /**
      * Given a byte buffer with a message, parse it into an object of type c. 
The
      * fields of the class are expected to be annotated with annotations from
      * the construct package.
@@ -82,6 +91,15 @@
         return m;
     }
 
+    /**
+     * Given a byte array with a message, parse it into an object of type c. 
The
+     * fields of the class are expected to be annotated with annotations from
+     * the construct package.
+     *
+     * @param srcBuf buffer with the serialized binary data
+     * @param c      desired object type to return
+     * @return instance of the desired object type
+     */
     public static <T extends Message> T parseAs(byte[] srcBuf, Class<T> c) {
         return parseAs(ByteBuffer.wrap(srcBuf), c);
     }
@@ -248,8 +266,7 @@
             Field nestedField = field;
 
             if (n.newFrame()) {
-                ParserGenerator pg = new ParserGenerator();
-                Parser p = getParser((Class<Message>) nestedField.getType(), 
pg);
+                Parser p = getParser((Class<Message>) nestedField.getType());
 
                 parser = new NestedParser(p, n.optional(), nestedField, true);
 
@@ -269,11 +286,6 @@
             }
         }
 
-        public void visit(ByteFill bf) {
-            parser = new ByteFillParser(field);
-        }
-
-
         public void visit(FixedSizeArray fsa) {
             Field f = field;
             int elemNumber = fsa.length();
@@ -284,14 +296,13 @@
             parser = new FixedSizeArrayParser(elemNumber, parser, f);
         }
 
-        public void visit(FixedSizeByteArray fsba) {
+
+        public void visit(FixedSizeIntegerArray fsa) {
             Field f = field;
-            int elemNumber = fsba.length();
-
-            parser = new FixedSizeByteArrayParser(elemNumber, f);
+            int elemNumber = fsa.length();
+            parser = new FixedSizeIntegerArrayParser(elemNumber, fsa.signed(), 
fsa.bitSize() / 8, f);
         }
 
-
         public void visit(Double d) {
             if (!field.getType().equals(java.lang.Double.TYPE)) {
                 throw new AssertionError("@Double target must be a primitive 
'double' field");
@@ -322,6 +333,10 @@
             Parser p = getParser((Class<? extends Message>) field.getType()
                     .getComponentType());
 
+            if 
(!Message.class.isAssignableFrom(field.getType().getComponentType())) {
+                throw new AssertionError("VariableSizeArray only valid on 
arrays of messages.");
+            }
+
             try {
                 parser = new VariableSizeArrayParser(p, c.getField(vsa
                         .lengthField()), field);
@@ -412,10 +427,10 @@
     }
 
     /**
-     * Compute the size of a serialized message.
+     * Compute the exact size of a serialized message.
      *
      * @param m object to serialize
-     * @return number of bytes required, -1 on error
+     * @return number of bytes required to store the message in binary form
      */
     public static int getSize(Message m) {
         if (m == null) {
@@ -425,6 +440,13 @@
         return p.getSize(m);
     }
 
+
+    /**
+     * Return the binary representation of the message m
+     *
+     * @param m the message to serialize
+     * @return a byte array containing the serialized message
+     */
     public static byte[] toBinary(Message m) {
         byte[] a = new byte[getSize(m)];
         ByteBuffer buf = ByteBuffer.wrap(a);
@@ -432,6 +454,13 @@
         return a;
     }
 
+    /**
+     * Fill in all fields of a message that are inferable from existing 
information.
+     *
+     * Examples: The size field for variable size arrays, the type of unions, 
...
+     *
+     * @param m the message that should be patched
+     */
     public static void patch(Message m) {
         Parser p = getParser(m.getClass());
         p.patch(m, p.getSize(m), null, m);

Deleted: gnunet-java/src/org/gnunet/construct/Constructable.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Constructable.java     2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Constructable.java     2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,28 +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.construct;
-
-/**
- * Implemented by classes that know how to serialize/deserialize themselves.
- */
-public interface Constructable {
-    // todo
-}

Modified: gnunet-java/src/org/gnunet/construct/Double.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Double.java    2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Double.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -25,6 +25,9 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+/**
+ * A number stored in the IEEE 754 double-precision binary floating-point 
format.
+ */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface Double {

Modified: gnunet-java/src/org/gnunet/construct/FixedSizeArray.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FixedSizeArray.java    2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/FixedSizeArray.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -29,7 +29,6 @@
  * An array of messages with static size.
  * 
  * @author Florian Dold
- *
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)

Deleted: gnunet-java/src/org/gnunet/construct/FixedSizeByteArray.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FixedSizeByteArray.java        
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/FixedSizeByteArray.java        
2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,39 +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.construct;
-
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * An array of bytes with static size.
- *
- * @author Florian Dold
- *
- */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
-public @interface FixedSizeByteArray {
-    int length();
-}
\ No newline at end of file

Added: gnunet-java/src/org/gnunet/construct/FixedSizeIntegerArray.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/FixedSizeIntegerArray.java             
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/FixedSizeIntegerArray.java     
2012-08-29 23:27:31 UTC (rev 23513)
@@ -0,0 +1,21 @@
+package org.gnunet.construct;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * An array of integers with static size.
+ *
+ * @author Florian Dold
+ */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface FixedSizeIntegerArray {
+    int length();
+    int bitSize();
+    boolean signed();
+}

Modified: gnunet-java/src/org/gnunet/construct/Int16.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int16.java     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Int16.java     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,7 +26,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Synonym for Integer(byteSize=2, signed=true)
+ * Signed 16-bit integer value.
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/Int32.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int32.java     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Int32.java     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,7 +26,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Synonym for Integer(byteSize=4, signed=true)
+ * Signed 32-bit integer value.
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/Int64.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int64.java     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Int64.java     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,9 +26,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Synonym for Integer(byteSize=8, signed=true)
- * 
- * @author Florian Dold
+ * Signed 64-bit integer value.
  *
  */
 

Modified: gnunet-java/src/org/gnunet/construct/Int8.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Int8.java      2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Int8.java      2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -27,7 +27,7 @@
 
 
 /**
- * Synonym for Integer(byteSize=1, signed=true)
+ * Signed 8-bit integer value.
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/IntegerFill.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/IntegerFill.java       2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/IntegerFill.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -25,6 +25,10 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+/**
+ * Fills the rest of the message with integers of the specified kind. The 
annotation may only be present on the
+ * last serialized field of message.
+ */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.FIELD)
 public @interface IntegerFill {

Modified: gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java      
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/MessageIdAnnotationProcessor.java      
2012-08-29 23:27:31 UTC (rev 23513)
@@ -42,7 +42,7 @@
 
 
 /**
- * Creates a resource file 'MsgMap.txt' in the package 'org.gnunet.construct'.
+ * Creates a resource file 'MsgMap.txt' in the package 'org.gnunet.construct' 
of the source tree.
  */
 @SupportedAnnotationTypes("org.gnunet.construct.UnionCase")
 @SupportedSourceVersion(SourceVersion.RELEASE_6)

Modified: gnunet-java/src/org/gnunet/construct/MessageLoader.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageLoader.java     2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/MessageLoader.java     2012-08-29 
23:27:31 UTC (rev 23513)
@@ -37,21 +37,26 @@
 
 
 /**
- * Load message maps
+ * Load message maps, which contain the information the parse/write unions.
  */
 public class MessageLoader {
     private static final Logger logger = LoggerFactory
             .getLogger(MessageLoader.class);
 
 
-
-
+    /**
+     * Thrown when a trying to serialize an object that is not registered as a 
union type.
+     */
     public static class UnknownUnionException extends RuntimeException {
         public UnknownUnionException(String msg) {
             super(msg);
         }
     }
 
+
+    /**
+     * Thrown when parsing a union whose ID is not known.
+     */
     public static class UnknownUnionIdException extends RuntimeException {
 
     }
@@ -86,19 +91,22 @@
     }
 
     public static void loadMessageMap(URL loc) {
-        if (loc == null)
+        if (loc == null) {
             throw new RuntimeException("could not load message map");
+        }
         BufferedReader in = null;
         try {
             in = new BufferedReader(new InputStreamReader(loc.openStream()));
             String line;
             while ((line = in.readLine()) != null) {
                 // skip empty lines and comments
-                if (line.isEmpty() || line.charAt(0) == '#')
+                if (line.isEmpty() || line.charAt(0) == '#') {
                     continue;
+                }
                 String[] m = line.split("=");
-                if (m.length != 2)
+                if (m.length != 2) {
                     throw new RuntimeException("invalid message map format 
(separation by '=')");
+                }
                 String[] left = m[0].split("[|]");
                 if (left.length != 2) {
                     logger.debug(m[0]);
@@ -134,8 +142,9 @@
 
     private static void maybeClose(Closeable in) {
         try {
-            if (in != null)
+            if (in != null) {
                 in.close();
+            }
         } catch (IOException e) {
             throw new RuntimeException("error closing stream: " + 
e.getMessage());
         }
@@ -164,7 +173,7 @@
 
         Class<? extends MessageUnion> cls = map.get(tag);
         if (cls == null) {
-            throw new ProtocolViolation("don't know how to translate message 
of type " + tag);
+            throw new ProtocolViolationException("don't know how to translate 
message of type " + tag);
         }
 
         return cls;
@@ -173,10 +182,12 @@
 
     public static int getUnionTag(Class<? extends MessageUnion> 
unionInterface, Class<? extends MessageUnion> unionCase) {
         Map<Class<? extends MessageUnion>, Integer> map = 
tagmap.get(unionInterface);
-        if (map == null)
+        if (map == null) {
             throw new AssertionError(String.format("%s is not a known union 
type", unionInterface));
-        if (!map.containsKey(unionCase))
+        }
+        if (!map.containsKey(unionCase)) {
             throw new AssertionError(String.format("%s is not a known instance 
of %s", unionCase, unionInterface));
+        }
         return map.get(unionCase);
     }
 }

Modified: gnunet-java/src/org/gnunet/construct/MessageUnion.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/MessageUnion.java      2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/MessageUnion.java      2012-08-29 
23:27:31 UTC (rev 23513)
@@ -21,7 +21,7 @@
 package org.gnunet.construct;
 
 /**
- * Marker interface for Message Unions
+ * Marker interface for message unions
  */
 public interface MessageUnion extends Message {
 }

Modified: gnunet-java/src/org/gnunet/construct/MsgMap.txt
===================================================================
--- gnunet-java/src/org/gnunet/construct/MsgMap.txt     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/MsgMap.txt     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -1,9 +1,12 @@
 org.gnunet.util.Resolver$Address|0=org.gnunet.util.Resolver$TextualAddress
 org.gnunet.util.Resolver$Address|1=org.gnunet.util.Resolver$NumericAddress
 org.gnunet.util.GnunetMessage$Body|68=org.gnunet.core.DisconnectNotifyMessage
-org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TESTMessage
+org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TestMessage
+org.gnunet.util.GnunetMessage$Body|274=org.gnunet.mesh.TunnelDestroyMessage
+org.gnunet.util.GnunetMessage$Body|273=org.gnunet.mesh.TunnelCreateMessage
 
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|272=org.gnunet.mesh.ClientConnectMessage
 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|5=org.gnunet.util.Resolver$ResolverResponse
@@ -22,8 +25,8 @@
 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|149=org.gnunet.dht.MonitorGetMessage
 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
 
org.gnunet.util.GnunetMessage$Body|171=org.gnunet.statistics.GetResponseEndMessage
@@ -32,4 +35,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/06/27 15:23:37
+# generated 2012/08/22 15:06:49

Deleted: gnunet-java/src/org/gnunet/construct/ProtocolViolation.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/ProtocolViolation.java 2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/ProtocolViolation.java 2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,35 +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.construct;
-
-
-/**
- * Thrown when a received message is invalid
- * 
- * @author Florian Dold
- *
- */
-public class ProtocolViolation extends RuntimeException {
-
-    public ProtocolViolation(String s) {
-        super(s);
-    }
-}

Copied: gnunet-java/src/org/gnunet/construct/ProtocolViolationException.java 
(from rev 23244, gnunet-java/src/org/gnunet/construct/ProtocolViolation.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/ProtocolViolationException.java        
                        (rev 0)
+++ gnunet-java/src/org/gnunet/construct/ProtocolViolationException.java        
2012-08-29 23:27:31 UTC (rev 23513)
@@ -0,0 +1,35 @@
+/*
+ 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.construct;
+
+
+/**
+ * Thrown when a received message is invalid.
+ * 
+ * @author Florian Dold
+ *
+ */
+public class ProtocolViolationException extends RuntimeException {
+
+    public ProtocolViolationException(String s) {
+        super(s);
+    }
+}

Modified: gnunet-java/src/org/gnunet/construct/ReflectUtil.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/ReflectUtil.java       2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/ReflectUtil.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -58,11 +58,11 @@
         } else if (t.equals(Integer.TYPE)) {
             Array.setInt(arr, i, (int) v);
         } else if (t.equals(Short.TYPE)) {
-            Array.setInt(arr, i, (short) v);
+            Array.setShort(arr, i, (short) v);
         } else if (t.equals(Byte.TYPE)) {
-            Array.setInt(arr, i, (byte) v);
+            Array.setByte(arr, i, (byte) v);
         } else if (t.equals(Character.TYPE)) {
-            Array.setInt(arr, i, (char) v);
+            Array.setChar(arr, i, (char) v);
         }
     }
 
@@ -71,8 +71,7 @@
     }
 
     /**
-     * assign an enum value to each numeric type we want to serialize in
-     * order do switch statements on field types
+     * An enumeration of all built-in type that can store integers.
      */
     public enum NumFieldType {
         BIGNUM, BYTE_PRIM, SHORT_PRIM, INT_PRIM, LONG_PRIM, CHAR_PRIM
@@ -252,6 +251,7 @@
         for (int i = 0; i < path.size() - 1; ++i) {
             try {
                 obj = path.get(i).get(obj);
+
             } catch (IllegalArgumentException e) {
                 throw new RuntimeException(e);
             } catch (IllegalAccessException e) {

Modified: gnunet-java/src/org/gnunet/construct/UInt16.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt16.java    2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/UInt16.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -27,7 +27,7 @@
 
 
 /**
- * Synonym for Integer(byteSize=2, signed=false)
+ * Unsigned 16-bit integer value
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/UInt32.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt32.java    2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/UInt32.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,7 +26,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Synonym for Integer(byteSize=4, signed=false)
+ * Unsigned 32-bit integer value
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/UInt64.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt64.java    2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/UInt64.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,7 +26,7 @@
 import java.lang.annotation.Target;
 
 /**
- * Synonym for Integer(byteSize=8, signed=false)
+ * Unsigned 64-bit integer value
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/UInt8.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UInt8.java     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/UInt8.java     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -28,7 +28,7 @@
 
 
 /**
- * Synonym for Integer(byteSize=1, signed=false)
+ * Unsigned 8-bit integer value.
  * 
  * @author Florian Dold
  *

Modified: gnunet-java/src/org/gnunet/construct/Union.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/Union.java     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/Union.java     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,6 +26,9 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+/**
+ * A field that stores a union, whose cases are discriminated by the field 
specified with address@hidden tag}.
+ */
 @Target(ElementType.FIELD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Union {

Modified: gnunet-java/src/org/gnunet/construct/UnionCase.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/UnionCase.java 2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/construct/UnionCase.java 2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,6 +26,12 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+/**
+ * Annotation for messages that are a case of a union, with a distinct value 
to discriminate the case.
+ *
+ * Classes annotated by address@hidden UnionCase} should implement
+ * the marker interface for their respective union type.
+ */
 @Retention(RetentionPolicy.SOURCE)
 @Target(ElementType.TYPE)
 public @interface UnionCase {

Deleted: gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java    
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/ByteFillParser.java    
2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,100 +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.construct.parsers;
-
-import org.gnunet.construct.Message;
-import org.gnunet.construct.ReflectUtil;
-import org.gnunet.construct.ProtocolViolation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.nio.ByteBuffer;
-import java.util.List;
-
-/**
- * Parse a byte array that takes up all the remaining space in its frame.
- * A 0-element array takes up no space.
- * 'null' is an invalid value for a field of this type.
- * 
- * @author Florian Dold
- * 
- */
-public class ByteFillParser implements Parser {
-    private static final Logger logger = LoggerFactory
-            .getLogger(ByteFillParser.class);
-    
-    private final Field targetField;
-
-
-    public ByteFillParser(Field field) {
-        targetField = field;
-    }
-
-    @Override
-    public int getSize(Message src) {
-        return Array.getLength(ReflectUtil.justGet(src, targetField));
-    }
-
-
-    @Override
-    public int parse(ByteBuffer srcBuf, int frameOffset, Message frameObj, 
Message dst, List<Field> frameSizePath) {
-        int frameSize = ReflectUtil.justGetInt(frameObj, frameSizePath);
-        int remaining = frameOffset + frameSize - srcBuf.position();
-
-        if (remaining < 0) {
-            throw new ProtocolViolation("negative size remaining for variable 
size message");
-        }
-
-        if (remaining == 0) {
-            ReflectUtil.justSet(dst, targetField, new byte[0]);
-            return 0;
-        }
-
-        byte[] a = new byte[remaining];
-
-        srcBuf.get(a);
-
-        ReflectUtil.justSet(dst, targetField, a);
-
-        return frameOffset;
-    }
-
-    @Override
-    public int write(ByteBuffer dstBuf, Message src) {
-        byte[] a = (byte[]) ReflectUtil.justGet(src, targetField);
-        dstBuf.put(a);
-        return a.length;
-    }
-
-    @Override
-    public void patch(Message message, int frameSize, List<Field> 
frameSizePath, Message frameObject) {
-        // the size field is contained in the frameObject
-        ReflectUtil.justSetInt(frameObject, frameSizePath, frameSize);
-    }
-
-    @Override
-    public int getStaticSize() {
-        // not known!
-        return 0;
-    }
-}

Modified: gnunet-java/src/org/gnunet/construct/parsers/FillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FillParser.java        
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/FillParser.java        
2012-08-29 23:27:31 UTC (rev 23513)
@@ -62,10 +62,15 @@
     public int parse(ByteBuffer srcBuf, int frameOffset,
                      Message frameObj, final Message dstObj, List<Field> 
frameSizePath) {
 
+
+
         final int frameSize = ReflectUtil.justGetInt(dstObj, frameSizePath);
         int remaining = frameOffset + frameSize - srcBuf.position();
         int size = 0;
 
+        Class<?> elemType = targetField.getType().getComponentType();
+
+
         ArrayList<Message> list = new ArrayList<Message>(10);
 
         while (remaining > 0) {
@@ -74,10 +79,13 @@
             int s = elemParser.parse(srcBuf, frameOffset, frameObj, next, 
null);
             size += s;
             remaining -= s;
+            list.add(next);
         }
 
+        Object arr = Array.newInstance(elemType, list.size());
+
         try {
-            targetField.set(dstObj, list.toArray());
+            targetField.set(dstObj, list.toArray((Object[]) arr));
         } catch (IllegalAccessException e) {
             throw new AssertionError("cannot access field");
         }

Modified: gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java      
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java      
2012-08-29 23:27:31 UTC (rev 23513)
@@ -82,6 +82,9 @@
                      final Message srcObj) {
         int size = 0;
         final Object arr = ReflectUtil.justGet(srcObj, targetField);
+        if (Array.getLength(arr) != elemNumber) {
+            throw new AssertionError("wrong number of elements");
+        }
         for (int i = 0; i < Array.getLength(arr); ++i) {
             size += elemParser.write(dstBuf, (Message) Array.get(arr, i));
         }

Deleted: 
gnunet-java/src/org/gnunet/construct/parsers/FixedSizeByteArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/FixedSizeByteArrayParser.java  
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/FixedSizeByteArrayParser.java  
2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,71 +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.construct.parsers;
-
-import org.gnunet.construct.Message;
-import org.gnunet.construct.ReflectUtil;
-
-import java.lang.reflect.Field;
-import java.nio.ByteBuffer;
-import java.util.List;
-
-public class FixedSizeByteArrayParser implements Parser {
-    private final int elemNumber;
-    private final Field targetField;
-
-    public FixedSizeByteArrayParser(int elemNumber, Field f) {
-        this.elemNumber = elemNumber;
-        this.targetField = f;
-    }
-
-    @Override
-    public int getSize(Message srcObj) {
-        return elemNumber;
-    }
-
-    @Override
-    public int parse(ByteBuffer srcBuf, int frameStart, Message frameObj, 
Message dstObj, List<Field> frameSizePath) {
-        byte[] data = new byte[elemNumber];
-        srcBuf.get(data);
-        ReflectUtil.justSet(dstObj, targetField, data);
-        return elemNumber;
-    }
-
-    @Override
-    public int write(ByteBuffer dstBuf, Message srcObj) {
-        byte[] data = (byte[]) ReflectUtil.justGet(srcObj, targetField);
-        if (data.length != elemNumber) {
-            throw new AssertionError("fixed size array has wrong size");
-        }
-        dstBuf.put(data);
-        return elemNumber;
-    }
-
-    @Override
-    public void patch(Message m, int frameSize, List<Field> frameSizePath, 
Message frameObj) {
-        // nothing to do
-    }
-
-    @Override
-    public int getStaticSize() {
-        return elemNumber;
-    }
-}

Copied: 
gnunet-java/src/org/gnunet/construct/parsers/FixedSizeIntegerArrayParser.java 
(from rev 23244, 
gnunet-java/src/org/gnunet/construct/parsers/FixedSizeArrayParser.java)
===================================================================
--- 
gnunet-java/src/org/gnunet/construct/parsers/FixedSizeIntegerArrayParser.java   
                            (rev 0)
+++ 
gnunet-java/src/org/gnunet/construct/parsers/FixedSizeIntegerArrayParser.java   
    2012-08-29 23:27:31 UTC (rev 23513)
@@ -0,0 +1,99 @@
+/*
+ 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.construct.parsers;
+
+import org.gnunet.construct.Message;
+import org.gnunet.construct.ReflectUtil;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+public class FixedSizeIntegerArrayParser implements Parser {
+
+    private final int byteSize;
+    private final boolean signed;
+
+    private final Field targetField;
+
+    private final int elemNumber;
+
+    public FixedSizeIntegerArrayParser(final int elemNumber, boolean signed, 
int byteSize, final Field f) {
+        targetField = f;
+        this.elemNumber = elemNumber;
+        this.signed = signed;
+        this.byteSize = byteSize;
+    }
+
+    @Override
+    public int getSize(final Message srcObj) {
+        return byteSize * elemNumber;
+    }
+
+    @Override
+    public int parse(ByteBuffer srcBuf, int frameOffset,
+                     Message frameObj, final Message dstObj, List<Field> 
frameSizePath) {
+        int size = 0;
+
+        @SuppressWarnings("unchecked")
+        final Class<Message> arrayElementType = (Class<Message>) 
targetField.getType().getComponentType();
+
+        if (!arrayElementType.isPrimitive()) {
+            throw new AssertionError("IntegerFillParser is expected to be of 
primitive type, not " + arrayElementType);
+        }
+
+        final Object arr = 
Array.newInstance(targetField.getType().getComponentType(), elemNumber);
+        ReflectUtil.justSet(dstObj, targetField, arr);
+
+        for (int i = 0; i < elemNumber; ++i) {
+            long v = IntegerUtil.readLong(srcBuf, signed, byteSize);
+            ReflectUtil.justSetArray(arr, i, v);
+        }
+
+        return size;
+    }
+
+    @Override
+    public int write(final ByteBuffer dstBuf,
+                     final Message srcObj) {
+        int size = 0;
+        final Object arr = ReflectUtil.justGet(srcObj, targetField);
+        if (Array.getLength(arr) != elemNumber) {
+            throw new AssertionError("wrong number of elements");
+        }
+        for (int i = 0; i < Array.getLength(arr); ++i) {
+            IntegerUtil.writeLong(Array.getLong(arr, i), dstBuf, signed, 
byteSize);
+            size += byteSize;
+        }
+        return size;
+    }
+
+    @Override
+    public void patch(Message m, int frameSize, List<Field> frameSizePath, 
Message frameObj) {
+        // nothing to patch!
+    }
+
+    @Override
+    public int getStaticSize() {
+        return elemNumber * byteSize;
+    }
+}

Modified: gnunet-java/src/org/gnunet/construct/parsers/IntegerFillParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/IntegerFillParser.java 
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/IntegerFillParser.java 
2012-08-29 23:27:31 UTC (rev 23513)
@@ -58,9 +58,25 @@
         final int frameSize = ReflectUtil.justGetInt(frameObj, frameSizePath);
         int remaining = frameStart + frameSize - srcBuf.position();
 
-        throw new UnsupportedOperationException("not yet implemented");
+        int elemNumber = remaining / byteSize;
 
-        // return getSize(dstObj);
+        @SuppressWarnings("unchecked")
+        final Class<Message> arrayElementType = (Class<Message>) 
targetField.getType().getComponentType();
+
+        if (!arrayElementType.isPrimitive()) {
+            throw new AssertionError("IntegerFillParser is expected to be of 
primitive type, not " + arrayElementType);
+        }
+
+        final Object arr = Array.newInstance(arrayElementType, elemNumber);
+        ReflectUtil.justSet(dstObj, targetField, arr);
+
+
+        for (int i = 0; i < elemNumber; ++i) {
+            long v = IntegerUtil.readLong(srcBuf, signed, byteSize);
+            ReflectUtil.justSetArray(arr, i, v);
+        }
+
+        return remaining;
     }
 
     @Override

Modified: gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java     
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/IntegerParser.java     
2012-08-29 23:27:31 UTC (rev 23513)
@@ -80,7 +80,12 @@
 
     @Override
     public void patch(Message m, int frameSize, List<Field> frameSizePath, 
Message frameObj) {
-        // nothing to do
+        // todo: optimize this!
+        /*
+        if (frameSizePath != null) {
+            ReflectUtil.justSetInt(frameObj, frameSizePath, frameSize);
+        }
+        */
     }
 
     @Override

Modified: gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java      
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/NestedParser.java      
2012-08-29 23:27:31 UTC (rev 23513)
@@ -21,8 +21,8 @@
 package org.gnunet.construct.parsers;
 
 import org.gnunet.construct.Message;
+import org.gnunet.construct.ProtocolViolationException;
 import org.gnunet.construct.ReflectUtil;
-import org.gnunet.construct.ProtocolViolation;
 
 import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
@@ -62,11 +62,11 @@
         if (optional) {
             int remaining = frameOffset + ReflectUtil.justGetInt(frameObj, 
frameSizePath) - srcBuf.position();
             if (remaining < 0) {
-                throw new ProtocolViolation("remaining size negative");
+                throw new ProtocolViolationException("remaining size 
negative");
             }
             if (remaining == 0) {
                 if (!optional) {
-                    throw new ProtocolViolation("not optional");
+                    throw new ProtocolViolationException("not optional");
                 }
                 ReflectUtil.justSet(dstObj, targetField, null);
                 return 0;
@@ -89,7 +89,7 @@
         Message nestedMessage = (Message) ReflectUtil.justGet(m, targetField);
 
         if (newFrame) {
-            nestedParser.patch(nestedMessage, 
nestedParser.getSize(nestedMessage), null, m);
+            nestedParser.patch(nestedMessage, 
nestedParser.getSize(nestedMessage), null, nestedMessage);
         } else {
             nestedParser.patch(nestedMessage, frameSize, frameSizePath, 
frameObj);
         }

Modified: gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java    
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/SequenceParser.java    
2012-08-29 23:27:31 UTC (rev 23513)
@@ -21,6 +21,7 @@
 package org.gnunet.construct.parsers;
 
 import org.gnunet.construct.Message;
+import org.gnunet.construct.ReflectUtil;
 
 import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
@@ -58,7 +59,6 @@
                      Message frameObj, final Message dst, List<Field> 
frameSizePath) {
         int size = 0;
         for (final Parser p : childParsers) {
-            List<Field> path;
             size += p.parse(srcBuf, frameOffset, frameObj, dst,
                     frameSizePath == null ? myFrameSizePath : frameSizePath);
         }
@@ -76,6 +76,11 @@
 
     @Override
     public void patch(Message m, int frameSize, List<Field> frameSizePath, 
Message frameObj) {
+        // todo: this should be optimized / only be done by the topmost 
sequence parse => introduce a boolean parameter
+        if (myFrameSizePath != null) {
+            ReflectUtil.justSetInt(frameObj, myFrameSizePath, frameSize);
+        }
+
         for (final Parser p : childParsers) {
             p.patch(m, frameSize, frameSizePath == null ? myFrameSizePath : 
frameSizePath, frameObj);
         }

Modified: gnunet-java/src/org/gnunet/construct/parsers/StringParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/StringParser.java      
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/StringParser.java      
2012-08-29 23:27:31 UTC (rev 23513)
@@ -21,7 +21,7 @@
 package org.gnunet.construct.parsers;
 
 import org.gnunet.construct.Message;
-import org.gnunet.construct.ProtocolViolation;
+import org.gnunet.construct.ProtocolViolationException;
 import org.gnunet.construct.ReflectUtil;
 
 import java.io.UnsupportedEncodingException;
@@ -63,12 +63,20 @@
     public int parse(final ByteBuffer srcBuf, int frameOffset, Message 
frameObj, final Message dstObj, List<Field>
             frameSizePath) {
 
-        if (srcBuf.get(srcBuf.position()) == 0) {
-            if (!optional) {
-                throw new ProtocolViolation("no data received for non-optional 
string");
+        if (optional) {
+            if (frameSizePath == null) {
+                throw new AssertionError("optional string with no length field 
in the message!");
             }
-            ReflectUtil.justSet(dstObj, targetField, null);
-            return 1;
+            final int frameSize = ReflectUtil.justGetInt(dstObj, 
frameSizePath);
+            int remaining = frameOffset + frameSize - srcBuf.position();
+
+            if (remaining == 0) {
+                if (!optional) {
+                    throw new ProtocolViolationException("no data received for 
non-optional string");
+                }
+                ReflectUtil.justSet(dstObj, targetField, null);
+                return 0;
+            }
         }
 
         int length = 0;
@@ -125,7 +133,9 @@
 
     @Override
     public void patch(Message m, int frameSize, List<Field> frameSizePath, 
Message frameObj) {
-        // nothing to patch
+        if (frameSizePath != null) {
+            ReflectUtil.justSetInt(frameObj, frameSizePath, frameSize);
+        }
     }
 
     @Override

Modified: gnunet-java/src/org/gnunet/construct/parsers/UnionParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/UnionParser.java       
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/UnionParser.java       
2012-08-29 23:27:31 UTC (rev 23513)
@@ -21,7 +21,7 @@
 package org.gnunet.construct.parsers;
 
 import org.gnunet.construct.*;
-import org.gnunet.construct.ProtocolViolation;
+import org.gnunet.construct.ProtocolViolationException;
 
 import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
@@ -66,7 +66,7 @@
             int remaining = frameOffset + ReflectUtil.justGetInt(frameObj, 
frameSizePath) - srcBuf.position();
             if (remaining <= 0) {
                 if (!optional) {
-                    throw new ProtocolViolation("not optional");
+                    throw new ProtocolViolationException("not optional");
                 }
                 ReflectUtil.justSet(dstObj, targetField, null);
                 return 0;

Modified: 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/construct/parsers/VariableSizeArrayParser.java   
2012-08-29 23:27:31 UTC (rev 23513)
@@ -70,7 +70,7 @@
         for (int i = 0; i < elemNumber; ++i) {
             Message elemObj;
 
-            elemObj = (Message) ReflectUtil.justInstantiate(arrayElementType);
+            elemObj = ReflectUtil.justInstantiate(arrayElementType);
 
 
             Array.set(arr, i, elemObj);

Modified: 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeIntegerArrayParser.java
===================================================================
--- 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeIntegerArrayParser.java
    2012-08-29 22:46:41 UTC (rev 23512)
+++ 
gnunet-java/src/org/gnunet/construct/parsers/VariableSizeIntegerArrayParser.java
    2012-08-29 23:27:31 UTC (rev 23513)
@@ -45,7 +45,6 @@
 
     @Override
     public int getSize(final Message src) {
-        int size = 0;
         final Object arr = ReflectUtil.justGet(src, targetField);
 
         if (arr == null) {

Copied: gnunet-java/src/org/gnunet/construct/parsers/package-info.java (from 
rev 23244, gnunet-java/src/org/gnunet/construct/package-info.java)
===================================================================
--- gnunet-java/src/org/gnunet/construct/parsers/package-info.java              
                (rev 0)
+++ gnunet-java/src/org/gnunet/construct/parsers/package-info.java      
2012-08-29 23:27:31 UTC (rev 23513)
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+
+/**
+ * The actual parsers for reading and writing annotated messages.
+ */
+package org.gnunet.construct.parsers;

Modified: gnunet-java/src/org/gnunet/core/ConnectNotifyMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/core/ConnectNotifyMessage.java   2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/core/ConnectNotifyMessage.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -20,10 +20,7 @@
 
 package org.gnunet.core;
 
-import org.gnunet.construct.ByteFill;
-import org.gnunet.construct.NestedMessage;
-import org.gnunet.construct.UInt32;
-import org.gnunet.construct.UnionCase;
+import org.gnunet.construct.*;
 import org.gnunet.util.GnunetMessage;
 import org.gnunet.util.PeerIdentity;
 
@@ -47,7 +44,7 @@
     public PeerIdentity peer;
 
 
-    @ByteFill
+    @FillWith @UInt8
     public byte[] atsInfo;
 
 

Modified: gnunet-java/src/org/gnunet/core/NotifyInboundTrafficMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/core/NotifyInboundTrafficMessage.java    
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/core/NotifyInboundTrafficMessage.java    
2012-08-29 23:27:31 UTC (rev 23513)
@@ -53,6 +53,6 @@
      * Not typed as GnunetMessage.Body because the message type may not be 
known by this
      * peer.
      */
-    @ByteFill
+    @FillWith @UInt8
     public byte[] payloadBody;
 }

Modified: gnunet-java/src/org/gnunet/core/NotifyOutboundTrafficMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/core/NotifyOutboundTrafficMessage.java   
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/core/NotifyOutboundTrafficMessage.java   
2012-08-29 23:27:31 UTC (rev 23513)
@@ -52,7 +52,7 @@
      * Not typed as GnunetMessage.Body because the message type may not be 
known by this
      * peer.
      */
-    @ByteFill
+    @FillWith @UInt8
     public byte[] payloadBody;
 
 }

Modified: gnunet-java/src/org/gnunet/dht/ClientGetMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/ClientGetMessage.java        2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/dht/ClientGetMessage.java        2012-08-29 
23:27:31 UTC (rev 23513)
@@ -46,6 +46,6 @@
     public HashCode key;
     @UInt64
     public long uniqueId;
-    @ByteFill
+    @FillWith @UInt8
     public byte[] xquery;
 }

Modified: gnunet-java/src/org/gnunet/dht/ClientPutMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/ClientPutMessage.java        2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/dht/ClientPutMessage.java        2012-08-29 
23:27:31 UTC (rev 23513)
@@ -49,6 +49,6 @@
     public AbsoluteTimeMessage expiration;
     @NestedMessage
     public HashCode hash;
-    @ByteFill
+    @FillWith @UInt8
     public byte[] data;
 }

Modified: gnunet-java/src/org/gnunet/dht/ClientResultMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/ClientResultMessage.java     2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/dht/ClientResultMessage.java     2012-08-29 
23:27:31 UTC (rev 23513)
@@ -51,6 +51,6 @@
     public PeerIdentity[] putPath;
     @VariableSizeArray(lengthField = "getPathLength")
     public PeerIdentity[] getPath;
-    @ByteFill
+    @FillWith @UInt8
     public byte[] data;
 }

Modified: gnunet-java/src/org/gnunet/dht/DistributedHashTable.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/DistributedHashTable.java    2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/dht/DistributedHashTable.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -23,8 +23,8 @@
 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;
+import org.gnunet.util.getopt.Argument;
+import org.gnunet.util.getopt.ArgumentAction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -345,45 +345,45 @@
 
     public static void main(String[] args) {
         new Program(args) {
-            @Option(action = OptionAction.SET,
+            @Argument(action = ArgumentAction.SET,
                     shortname = "p",
                     longname = "put",
                     description = "set a value in the DHT; default is get")
             boolean modePut = false;
 
-            @Option(action = OptionAction.SET,
+            @Argument(action = ArgumentAction.SET,
                     shortname = "m",
                     longname = "monitor",
                     description = "monitor requests going to the local DHT")
             boolean monitor = false;
 
 
-            @Option(action = OptionAction.STORE_STRING,
+            @Argument(action = ArgumentAction.STORE_STRING,
                     shortname = "d",
                     longname = "data",
                     description = "data (only used with --put)")
             String data = null;
 
-            @Option(action = OptionAction.STORE_STRING,
+            @Argument(action = ArgumentAction.STORE_STRING,
                     shortname = "k",
                     longname = "key",
                     description = "key used for the operation")
             String key = null;
 
-            @Option(action = OptionAction.STORE_STRING,
+            @Argument(action = ArgumentAction.STORE_STRING,
                     shortname = "t",
                     longname = "type",
                     description = "type of data used in this operation")
             String type = null;
 
-            @Option(action = OptionAction.STORE_STRING,
+            @Argument(action = ArgumentAction.STORE_STRING,
                     shortname = "e",
                     longname = "expire",
                     description = "expiration (ony use with --put)")
             String expiration = null;
 
 
-            @Option(action = OptionAction.STORE_NUMBER,
+            @Argument(action = ArgumentAction.STORE_NUMBER,
                     shortname = "r",
                     longname = "replication",
                     description = "desired replication (only used with --put)")

Modified: gnunet-java/src/org/gnunet/dht/MonitorGetRespMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/MonitorGetRespMessage.java   2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/dht/MonitorGetRespMessage.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -67,6 +67,6 @@
     @VariableSizeArray(lengthField = "get_path_length")
     public PeerIdentity[] getPath;
 
-    @ByteFill
+    @FillWith @UInt8
     public byte[] data;
 }

Modified: gnunet-java/src/org/gnunet/dht/MonitorPutMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/dht/MonitorPutMessage.java       2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/dht/MonitorPutMessage.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -77,6 +77,6 @@
     @VariableSizeArray(lengthField = "put_path_length")
     public PeerIdentity[] putPath;
 
-    @ByteFill
+    @FillWith @UInt8
     public byte[] data;
 }

Copied: gnunet-java/src/org/gnunet/hello/HelloMessage.java (from rev 23244, 
gnunet-java/src/org/gnunet/util/HelloMessage.java)
===================================================================
--- gnunet-java/src/org/gnunet/hello/HelloMessage.java                          
(rev 0)
+++ gnunet-java/src/org/gnunet/hello/HelloMessage.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -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.hello;
+
+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;
+
+    @FillWith @UInt8
+    public byte[] addresses;
+}

Added: gnunet-java/src/org/gnunet/hello/package-info.java
===================================================================
--- gnunet-java/src/org/gnunet/hello/package-info.java                          
(rev 0)
+++ gnunet-java/src/org/gnunet/hello/package-info.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+
+/**
+ * Management of hello-messages from peers.
+ */
+package org.gnunet.hello;

Modified: gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java   2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/mesh/ClientConnectMessage.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,9 +1,6 @@
 package org.gnunet.mesh;
 
-import org.gnunet.construct.FixedSizeArray;
-import org.gnunet.construct.UInt16;
-import org.gnunet.construct.UnionCase;
-import org.gnunet.construct.VariableSizeArray;
+import org.gnunet.construct.*;
 import org.gnunet.util.GnunetMessage;
 
 /**
@@ -14,11 +11,11 @@
 @UnionCase(272)
 public class ClientConnectMessage implements GnunetMessage.Body {
     @UInt16
-    public int applications;
+    public int applications_length;
     @UInt16
-    public int types;
-    @VariableSizeArray(lengthField = "applications")
+    public int types_length;
+    @VariableSizeIntegerArray(lengthField = "applications_length", signed = 
false, bitSize = 16)
     public int[] apps_list;
-    @VariableSizeArray(lengthField = "types")
+    @VariableSizeIntegerArray(lengthField = "types_length", signed = false, 
bitSize = 16)
     public int[] types_list;
 }

Added: gnunet-java/src/org/gnunet/mesh/ConnectHandler.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/ConnectHandler.java                         
(rev 0)
+++ gnunet-java/src/org/gnunet/mesh/ConnectHandler.java 2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -0,0 +1,9 @@
+package org.gnunet.mesh;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class ConnectHandler {
+}

Added: gnunet-java/src/org/gnunet/mesh/DisconnectHandler.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/DisconnectHandler.java                      
        (rev 0)
+++ gnunet-java/src/org/gnunet/mesh/DisconnectHandler.java      2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,9 @@
+package org.gnunet.mesh;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public interface DisconnectHandler {
+}

Modified: gnunet-java/src/org/gnunet/mesh/Mesh.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/Mesh.java   2012-08-29 22:46:41 UTC (rev 
23512)
+++ gnunet-java/src/org/gnunet/mesh/Mesh.java   2012-08-29 23:27:31 UTC (rev 
23513)
@@ -25,36 +25,122 @@
 import org.gnunet.util.*;
 import org.grothoff.Runabout;
 
-import java.util.List;
-
 /**
+ *
+ *
  * @author Florian Dold
  */
 public class Mesh {
     private RequestQueue requestQueue;
     private TunnelEndHandler tunnelEndHandler;
     private Runabout messageReceiver;
-    private List<Integer> applications;
+    private int[] applications;
     private InboundTunnelHandler inboundTunnelHandler;
 
 
-    public static class RootTunnel {
-        int tunnel_id;
+    private int nextTunnelId = 0x80000000;
+
+
+    public class RootTunnel extends Tunnel {
         public void addPeer(PeerIdentity peerIdentity) {
 
         }
+        /**
+         * Request that the given peer isn't added to this tunnel in calls to
+         * connect_by_* calls, (due to misbehaviour, bad performance, ...).
+         *
+         * @param peerIdentity peer identity of the peer which should be 
blacklisted
+         *                  for the tunnel.
+         */
         public void blacklist(PeerIdentity peerIdentity) {
 
         }
-        public void destroy() {
-            // ...
+        /**
+         * Request that the given peer isn't blacklisted anymore from this 
tunnel,
+         * and therefore can be added in future calls to connect*.
+         * The peer must have been previously blacklisted for this tunnel.
+         *
+         * @param peerIdentity peer identity of the peer which shouldn't be 
blacklisted
+         *                  for the tunnel anymore.
+         */
+        public void unblacklist(PeerIdentity peerIdentity) {
+
         }
+        /**
+         * Request that the mesh should try to connect to a peer supporting 
the given
+         * message type.
+         *
+         * @param appType application type that must be supported by the peer
+         *                 (MESH should discover peer in proximity handling 
this type)
+         */
+        public void requestConnectByType (int appType) {
+
+        }
+
+        /**
+         * Request that the mesh should try to connect to a peer matching the
+         * description given in the service string.
+         *
+         * @param description string describing the destination node 
requirements
+         */
+        public void requestConnectByType (String description) {
+
+        }
+
+        /**
+         * Request that a peer should be added to the tunnel.  The connect 
handler
+         * will be called when the peer connects
+         *
+         * @param peer peer to add
+         */
+        public void requestConnectAdd (PeerIdentity peer) {
+
+        }
+
+        /**
+         * Request that a peer should be removed from the tunnel.  The existing
+         * disconnect handler will be called ONCE if we were connected.
+         *
+         * @param peer peer to remove
+         */
+        public void requestConnectDel (PeerIdentity peer) {
+
+        }
+
+        private void registerWithService() {
+            requestQueue.add(new TunnelCreateRequest(this));
+        }
     }
 
-    public static class Tunnel extends RootTunnel {
-        public Cancelable notifyTransmitReady(PeerIdentity target) {
+    public class Tunnel {
+        int tunnel_id;
+
+        /**
+         * Ask the mesh to call "notify" once it is ready to transmit the
+         * given number of bytes to the specified tunnel or target.
+         * Only one call can be active at any time, to issue another request,
+         * wait for the callback or cancel the current request.
+         *
+         * @param maxdelay how long can the message wait?
+         * @param target destination for the message
+         *               NULL for multicast to all tunnel targets
+         * @param notify_size how many bytes of buffer space does notify want?
+         * @param transmitter handler to call when buffer space is available;
+         *        will be called with NULL on timeout or if the overall queue
+         *        for this peer is larger than queue_size and this is currently
+         *        the message with the lowest priority
+         * @return non-NULL if the notify callback was queued,
+         *         NULL if we can not even queue the request (insufficient
+         *         memory); if NULL is returned, "notify" will NOT be called.
+         */
+        public Cancelable notifyTransmitReady(RelativeTime maxdelay, 
PeerIdentity target, int notify_size, MessageTransmitter transmitter) {
             return null;
         }
+
+        public void destroy() {
+            // ...
+        }
+
     }
 
 
@@ -62,11 +148,32 @@
 
         @Override
         public void transmit(Connection.MessageSink sink) {
-            //To change body of implemented methods use File | Settings | File 
Templates.
+            ClientConnectMessage ccm = new ClientConnectMessage();
+            ccm.applications_length = applications.length;
+            ccm.apps_list = applications;
+            int[] types = 
RunaboutUtil.getRunaboutMessageTypes(messageReceiver);
+            ccm.types_list = types;
+            ccm.types_length = types.length;
+            sink.send(ccm);
         }
     }
 
+    public class TunnelCreateRequest extends Request {
+        public RootTunnel tunnel;
 
+        public TunnelCreateRequest(RootTunnel rootTunnel) {
+            tunnel = rootTunnel;
+        }
+
+        @Override
+        public void transmit(Connection.MessageSink sink) {
+            TunnelCreateMessage tcm = new TunnelCreateMessage();
+            tcm.tunnel_id = tunnel.tunnel_id;
+            sink.send(tcm);
+        }
+    }
+
+
     private class MeshMessageReceiver extends RunaboutMessageReceiver {
 
         @Override
@@ -76,7 +183,7 @@
 
 
     public Mesh(Configuration cfg, InboundTunnelHandler inboundTunnelHandler,
-                TunnelEndHandler tunnelEndHandler, Runabout messageReceiver, 
List<Integer> applications) {
+                TunnelEndHandler tunnelEndHandler, Runabout messageReceiver, 
int... applications) {
         this.tunnelEndHandler = tunnelEndHandler;
         this.messageReceiver = messageReceiver;
         this.applications = applications;
@@ -86,24 +193,45 @@
         requestQueue = new RequestQueue(client, new MeshMessageReceiver());
 
         requestQueue.add(new ClientConnectRequest());
-
     }
 
     /**
      * Create a new tunnel (we're initiator and will be allowed to add/remove 
peers
      * and to broadcast).
+     *
+     * @param connectHandler function to call when peers are actually connected
+     * @param disconnectHandler function to call when peers are disconnected
      */
-    public RootTunnel createTunnel(/* ... */) {
-        return null;
+    public RootTunnel createTunnel(ConnectHandler connectHandler, 
DisconnectHandler disconnectHandler) {
+        RootTunnel tunnel = new RootTunnel();
+        tunnel.tunnel_id = nextTunnelId++;
+        tunnel.registerWithService();
+        return tunnel;
     }
 
+
     /**
+     * Announce to ther peer the availability of services described by the 
regex,
+     * in order to be reachable to other peers via connect_by_string.
+     *
+     * Note that the first 8 characters are considered to be part of a prefix,
+     * (for instance 'gnunet://'). If you put a variable part in there (*, +. 
()),
+     * all matching strings will be stored in the DHT.
+     *
+     * @param regex string with the regular expression describing local 
services.
+     */
+    public void announceRegex(String regex) {
+
+    }
+
+
+    /**
      * Disconnect from the mesh service. All tunnels will be destroyed. All 
tunnel
      * disconnect callbacks will be called on any still connected peers, 
notifying
      * about their disconnection. The registered inbound tunnel cleaner will be
      * called should any inbound tunnels still exist.
      */
     public void disconnect() {
-
+        requestQueue.destroy();
     }
 }

Modified: gnunet-java/src/org/gnunet/mesh/TunnelCreateMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/TunnelCreateMessage.java    2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/mesh/TunnelCreateMessage.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,16 +1,28 @@
 package org.gnunet.mesh;
 
+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 used to
+ * a) request the service to create a new tunnel with the given tunnel id
+ * b) notify the client of a newly created tunnel
  *
+ * todo: this is bad design, split into two messages in the C code!
+ *
  * @author Florian Dold
  */
 @UnionCase(273)
 public class TunnelCreateMessage implements GnunetMessage.Body {
     @UInt32
     public int tunnel_id;
+
+    /**
+     * Only present if sent from server to client (purpose b)
+     */
+    @NestedMessage(optional = true)
+    public PeerIdentity otherEnd;
 }

Added: gnunet-java/src/org/gnunet/mesh/package-info.java
===================================================================
--- gnunet-java/src/org/gnunet/mesh/package-info.java                           
(rev 0)
+++ gnunet-java/src/org/gnunet/mesh/package-info.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+
+/**
+ * Create tunnels for packet-based communication to distant peers.
+ */
+package org.gnunet.mesh;

Modified: gnunet-java/src/org/gnunet/nse/NetworkSizeEstimation.java
===================================================================
--- gnunet-java/src/org/gnunet/nse/NetworkSizeEstimation.java   2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/nse/NetworkSizeEstimation.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -23,10 +23,10 @@
 
 import org.gnunet.construct.Double;
 import org.gnunet.construct.*;
-import org.gnunet.construct.ProtocolViolation;
+import org.gnunet.construct.ProtocolViolationException;
 import org.gnunet.util.*;
-import org.gnunet.util.getopt.Option;
-import org.gnunet.util.getopt.OptionAction;
+import org.gnunet.util.getopt.Argument;
+import org.gnunet.util.getopt.ArgumentAction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,7 +72,7 @@
         @Override
         public void process(GnunetMessage.Body msg) {
             if (!(msg instanceof UpdateMessage)) {
-                throw new ProtocolViolation("got unexcpected message");
+                throw new ProtocolViolationException("got unexcpected 
message");
             }
             UpdateMessage uMsg = (UpdateMessage) msg;
 
@@ -169,7 +169,7 @@
 
     public static void main(String[] args) {
         new Program(args) {
-            @Option(action = OptionAction.SET,
+            @Argument(action = ArgumentAction.SET,
                     shortname = "w",
                     longname = "continuous",
                     description = "don't exit after the first estimation 
response")

Modified: gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java        2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/peerinfo/InfoMessage.java        2012-08-29 
23:27:31 UTC (rev 23513)
@@ -23,7 +23,7 @@
 import org.gnunet.construct.NestedMessage;
 import org.gnunet.construct.UInt32;
 import org.gnunet.construct.UnionCase;
-import org.gnunet.util.HelloMessage;
+import org.gnunet.hello.HelloMessage;
 import org.gnunet.util.GnunetMessage;
 import org.gnunet.util.PeerIdentity;
 

Modified: gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java   2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/peerinfo/PeerInfo.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -21,7 +21,7 @@
 package org.gnunet.peerinfo;
 
 
-import org.gnunet.util.HelloMessage;
+import org.gnunet.hello.HelloMessage;
 import org.gnunet.requests.Request;
 import org.gnunet.requests.RequestQueue;
 import org.gnunet.util.*;

Modified: gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java      2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/peerinfo/PeerProcessor.java      2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,6 +1,6 @@
 package org.gnunet.peerinfo;
 
-import org.gnunet.util.HelloMessage;
+import org.gnunet.hello.HelloMessage;
 import org.gnunet.util.PeerIdentity;
 
 /**

Modified: gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java  
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/peerinfo/RsaPublicKeyBinaryEncoded.java  
2012-08-29 23:27:31 UTC (rev 23513)
@@ -20,7 +20,7 @@
 
 package org.gnunet.peerinfo;
 
-import org.gnunet.construct.FixedSizeByteArray;
+import org.gnunet.construct.FixedSizeIntegerArray;
 import org.gnunet.construct.Message;
 import org.gnunet.construct.UInt16;
 import org.gnunet.construct.UInt8;
@@ -45,7 +45,7 @@
     /**
      * The key itself, contains n followed by e.
      */
-    @FixedSizeByteArray(length = 
RsaPublicKeyBinaryEncoded.GNUNET_CRYPTO_RSA_KEY_LENGTH)
+    @FixedSizeIntegerArray(length = 
RsaPublicKeyBinaryEncoded.GNUNET_CRYPTO_RSA_KEY_LENGTH, signed = false, bitSize 
= 8)
     public byte[] key;
 
     /**

Added: gnunet-java/src/org/gnunet/peerinfo/package-info.java
===================================================================
--- gnunet-java/src/org/gnunet/peerinfo/package-info.java                       
        (rev 0)
+++ gnunet-java/src/org/gnunet/peerinfo/package-info.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+
+/**
+ * Access to information about known hosts.
+ */
+package org.gnunet.peerinfo;

Modified: gnunet-java/src/org/gnunet/requests/Request.java
===================================================================
--- gnunet-java/src/org/gnunet/requests/Request.java    2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/requests/Request.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -15,7 +15,7 @@
     /**
      * Called whenever the request could not be transmitted due to timeout.
      *
-     * @return
+     * @return true if the request should be queued again
      */
     public boolean onTransmitTimeout() {
         // per default, just drop the message on timeout!
@@ -55,7 +55,7 @@
      * Called to determine after how long the request should time out.
      * Per default, the deadline is FOREVER.
      *
-     * @return
+     * @return the deadline for this request
      */
     public AbsoluteTime getDeadline() {
         return deadline;

Added: gnunet-java/src/org/gnunet/requests/package-info.java
===================================================================
--- gnunet-java/src/org/gnunet/requests/package-info.java                       
        (rev 0)
+++ gnunet-java/src/org/gnunet/requests/package-info.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+
+/**
+ * General mechanism for queueing requests to a service.
+ */
+package org.gnunet.requests;

Modified: gnunet-java/src/org/gnunet/statistics/Statistics.java
===================================================================
--- gnunet-java/src/org/gnunet/statistics/Statistics.java       2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/statistics/Statistics.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -29,8 +29,8 @@
 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;
+import org.gnunet.util.getopt.Argument;
+import org.gnunet.util.getopt.ArgumentAction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -190,7 +190,7 @@
         }
 
         public void transmit(Connection.MessageSink sink) {
-            sink.send(new TESTMessage());
+            sink.send(new TestMessage());
             // todo: disconnect when not receiving the TEST message back after 
timeout
         }
     }
@@ -208,7 +208,7 @@
             }
         }
 
-        public void visit(TESTMessage m) {
+        public void visit(TestMessage m) {
             client.disconnect();
         }
 
@@ -331,28 +331,28 @@
      */
     public static void main(String[] args) {
         new Program(args) {
-            @Option(
+            @Argument(
                     shortname = "x",
                     longname = "set",
-                    action = OptionAction.SET,
+                    action = ArgumentAction.SET,
                     description = "set a value")
             boolean test;
-            @Option(
+            @Argument(
                     shortname = "w",
                     longname = "watch",
-                    action = OptionAction.SET,
+                    action = ArgumentAction.SET,
                     description = "set a value")
             boolean watch;
-            @Option(
+            @Argument(
                     shortname = "n",
                     longname = "name",
-                    action = OptionAction.STORE_STRING,
+                    action = ArgumentAction.STORE_STRING,
                     description = "statistics name")
             String statisticsName = "";
-            @Option(
+            @Argument(
                     shortname = "s",
                     longname = "subsystem",
-                    action = OptionAction.STORE_STRING,
+                    action = ArgumentAction.STORE_STRING,
                     description = "subsystem name")
             String subsystemName = "";
 

Modified: gnunet-java/src/org/gnunet/testing/TestingServer.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/TestingServer.java       2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/testing/TestingServer.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -20,7 +20,7 @@
     public final Server server;
     private final ServerSocketChannel srvChan;
 
-    TestingServer() {
+    public TestingServer() {
         this(RelativeTime.FOREVER, true);
     }
 

Modified: gnunet-java/src/org/gnunet/testing/TestingSetup.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/TestingSetup.java        2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/testing/TestingSetup.java        2012-08-29 
23:27:31 UTC (rev 23513)
@@ -29,44 +29,23 @@
  *
  * @author Florian Dold
  */
-public class TestingSetup {
+public final class TestingSetup {
 
+    private TestingSetup() {
+
+    }
+
     public static class SetupException extends RuntimeException {
-        public SetupException(String msg, Throwable cause) {
-            super(msg, cause);
+        public SetupException(Exception e) {
+            super(e);
         }
-
         public SetupException(String msg) {
             super(msg);
         }
 
-        public SetupException(Throwable cause) {
-            super(cause);
-        }
     }
 
-    /**
-     * Start a subsystem for testing. Note that subsystems started with this 
function
-     * are independent of each other.
-     *
-     * After the JVM exits, the subsystem will be shut down.
-     *
-     * @param name name of the Subsystem
-     * @return
-     */
-    public TestingSubsystem startSubsystem(String name) {
-        return new TestingSubsystem(name);
-    }
-
-    public TestingServer createServer() {
-        return new TestingServer();
-    }
-
-    public TestingServer createServer(RelativeTime idleTimeout, boolean 
requireFound) {
-        return new TestingServer(idleTimeout, requireFound);
-    }
-
-    public TestingSetup() {
+    public static void setup() {
         String log = System.getenv("GNJ_LOGLEVEL");
         if (log != null) {
             Program.configureLogging(log, null);

Modified: gnunet-java/src/org/gnunet/testing/TestingSubsystem.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/TestingSubsystem.java    2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/testing/TestingSubsystem.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -30,7 +30,9 @@
 import java.io.OutputStreamWriter;
 
 /**
-* @author Florian Dold
+ * Handle to a GNUnet subsystem that has been started for testing purposes.
+ *
+ * @author Florian Dold
 */
 public class TestingSubsystem {
     private static final Logger logger = LoggerFactory
@@ -46,7 +48,7 @@
         return cfg;
     }
 
-    TestingSubsystem(String service) {
+    public TestingSubsystem(String service) {
         try {
             p = Runtime.getRuntime().exec(new 
String[]{"gnunet-testing-run-service", "-s", service});
         } catch (IOException e) {

Added: gnunet-java/src/org/gnunet/testing/package-info.java
===================================================================
--- gnunet-java/src/org/gnunet/testing/package-info.java                        
        (rev 0)
+++ gnunet-java/src/org/gnunet/testing/package-info.java        2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,27 @@
+/*
+ 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.
+ */
+
+
+/**
+ * Various utilities for testing.
+ *
+ * This is in the main source code location, as the testing package itself has 
unit tests.
+ */
+package org.gnunet.testing;

Modified: gnunet-java/src/org/gnunet/transport/Transport.java
===================================================================
--- gnunet-java/src/org/gnunet/transport/Transport.java 2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/transport/Transport.java 2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,7 +26,7 @@
 import org.gnunet.util.RelativeTime;
 
 /**
- * low-level peer-to-peer I/O API
+ * A connection to the transport service.
  *
  * @author Florian Dold
  */

Added: gnunet-java/src/org/gnunet/transport/package-info.java
===================================================================
--- gnunet-java/src/org/gnunet/transport/package-info.java                      
        (rev 0)
+++ gnunet-java/src/org/gnunet/transport/package-info.java      2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,25 @@
+/*
+ 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.
+ */
+
+
+/**
+ * Low-level peer-to-peer I/O API.
+ */
+package org.gnunet.transport;

Modified: gnunet-java/src/org/gnunet/util/AbsoluteTime.java
===================================================================
--- gnunet-java/src/org/gnunet/util/AbsoluteTime.java   2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/AbsoluteTime.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -32,6 +32,9 @@
     private static final Logger logger = LoggerFactory
             .getLogger(AbsoluteTime.class);
 
+    /**
+     * Constant for 'the beginning of time' in our frame.
+     */
     public final static AbsoluteTime ZERO = new AbsoluteTime(0);
     public final static AbsoluteTime FOREVER = new 
AbsoluteTime(Long.MAX_VALUE);
 
@@ -95,16 +98,25 @@
     }
 
 
+    /**
+     * address@hidden
+     */
     @Override
     public boolean equals(Object other) {
         return other instanceof AbsoluteTime && compareTo((AbsoluteTime) 
other) == 0;
     }
 
+    /**
+     * address@hidden
+     */
     @Override
     public int hashCode() {
         return (int) this.abs_value;
     }
 
+    /**
+     * address@hidden
+     */
     @Override
     public int compareTo(AbsoluteTime other) {
         if (this.abs_value < other.abs_value) {
@@ -115,7 +127,10 @@
         }
         return 0;
     }
-    
+
+    /**
+     * address@hidden
+     */
     @Override
     public String toString() {
         if (this.isForever()) {
@@ -132,8 +147,12 @@
     public boolean isDue() {
         return this.abs_value < now().abs_value;
     }
-    
-    
+
+    /**
+     * Does this AbsoluteTime value represent forever?
+     *
+     * @return this==FOREVER
+     */
     public boolean isForever() {
         return this.abs_value == Long.MAX_VALUE;
     }
@@ -220,10 +239,22 @@
         return new AbsoluteTime(abs_value - duration.getMilliseconds());
     }
 
+    /**
+     * Get a serializable message corresponding to this AbsoluteTime.
+     *
+     * @return a serializable message corresponding to this AbsoluteTime
+     */
     public AbsoluteTimeMessage asMessage() {
         return new AbsoluteTimeMessage(this);
     }
 
+    /**
+     * Get the AbsoluteTime from a AbsoluteTimeMessage.
+     *
+     * @param m serializable representation of an AbsoluteTime
+     *
+     * @return the real AbsoluteTime associated with m
+     */
     public static AbsoluteTime fromNetwork(AbsoluteTimeMessage m) {
         return m.value__ < 0 ? AbsoluteTime.FOREVER : new 
AbsoluteTime(m.value__);
     }

Modified: gnunet-java/src/org/gnunet/util/Client.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Client.java 2012-08-29 22:46:41 UTC (rev 
23512)
+++ gnunet-java/src/org/gnunet/util/Client.java 2012-08-29 23:27:31 UTC (rev 
23513)
@@ -22,6 +22,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * A connection to a gnunet service.
  *
@@ -69,6 +70,12 @@
     private boolean notifyTransmitReadyDelayed;
 
     /**
+     * When notifyTransmitReadyDelayed is true, this can be used to cancel the 
task
+     * waiting for the connection to be established.
+     */
+    private Cancelable delayedNotifyTransmitHandle;
+
+    /**
      * Create a connection to a service.
      *
      * @param serviceName name of the service
@@ -111,16 +118,6 @@
         return connection.receive(timeout, receiver);
     }
 
-
-    private static class DelayedTransmitHandle implements Cancelable {
-        Cancelable realTransmitHandle;
-        Cancelable timeoutHandle;
-        @Override
-        public void cancel() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
     /**
      * Ask the client to call us once it is able to send a message.
      *
@@ -132,39 +129,103 @@
      *                    if the caller does not care about temporary 
connection errors,
      *                    for example because the protocol is stateless
      * @param size        size of the message we want to transmit, can be an 
upper bound
-     address@hidden transmitter the MessageTransmitter object to call once the 
client is ready to transmit or
+     * @param transmitter the MessageTransmitter object to call once the 
client is ready to transmit or
      *                    when the timeout is over. Guaranteed to be called 
*after* notifyTransmitReady has returned.  @return a handle that can be used to 
cancel the transmit request
+     *
+     * @return a handle to cancel the notification
      */
     public Cancelable notifyTransmitReady(final RelativeTime timeout,
                                           final boolean autoRetry, int size, 
final MessageTransmitter transmitter) {
+        if (notifyTransmitReadyDelayed) {
+            throw new AssertionError("notifyTransmitReady called twice!");
+        }
         if (connection.isConnected()) {
             return connection.notifyTransmitReady(0, timeout, transmitter);
         } else {
             notifyTransmitReadyDelayed = true;
-            final DelayedTransmitHandle delayedTransmitHandle = new 
DelayedTransmitHandle();
-            delayedTransmitHandle.timeoutHandle = 
Scheduler.addDelayed(connectBackoff, new Scheduler.Task() {
+            final AbsoluteTime deadline = timeout.toAbsolute();
+            delayedNotifyTransmitHandle = 
connection.notifyConnected(connectBackoff, new Continuation() {
                 @Override
-                public void run(Scheduler.RunContext ctx) {
-                    if (connection == null) {
-                        return;
-                    }
-                    if (connection.isConnected()) {
+                public void cont(boolean success) {
+                    delayedNotifyTransmitHandle = null;
+                    if (success) {
                         notifyTransmitReadyDelayed = false;
-                        connection.notifyTransmitReady(0, timeout, 
transmitter);
+                        delayedNotifyTransmitHandle = 
connection.notifyTransmitReady(0, timeout, new MessageTransmitter() {
+                            @Override
+                            public void transmit(Connection.MessageSink sink) {
+                                delayedNotifyTransmitHandle = null;
+                                transmitter.transmit(sink);
+                            }
+
+                            @Override
+                            public void handleError() {
+                                delayedNotifyTransmitHandle = null;
+                                transmitter.handleError();
+                            }
+                        });
                     } else {
-                        logger.debug("still not connected, retrying in {}ms", 
connectBackoff.getMilliseconds());
-                        reconnect();
-                        connectBackoff = 
RelativeTime.min(connectBackoff.multiply(2), MAX_BACKOFF);
-                        Scheduler.addDelayed(connectBackoff, this);
+                        if (deadline.isDue()) {
+                            transmitter.handleError();
+                        } else {
+                            RelativeTime timeout = deadline.getRemaining();
+                            connectBackoff = RelativeTime.min(timeout, 
RelativeTime.min(connectBackoff.multiply(2), MAX_BACKOFF));
+                            reconnect();
+                            delayedNotifyTransmitHandle = 
connection.notifyConnected(connectBackoff, this);
+                        }
                     }
                 }
             });
-            return delayedTransmitHandle;
+            return new Cancelable() {
+                @Override
+                public void cancel() {
+                    if (delayedNotifyTransmitHandle != null) {
+                        delayedNotifyTransmitHandle.cancel();
+                    }
+                }
+            };
         }
     }
 
+    /**
+     * Convenience method for sending messages.
+     *
+     * @param timeout when should we give up sending the message, and call 
cont.cont(false)
+     * @param message the message to send
+     * @param cont called when the message has been sent successfully or on 
error
+     * @return a handle to cancel sending the message
+     */
+    public Cancelable transmitWhenReady(final RelativeTime timeout, final 
GnunetMessage.Body message, final Continuation cont) {
+        return notifyTransmitReady(timeout, false, 0, new MessageTransmitter() 
{
+            @Override
+            public void transmit(Connection.MessageSink sink) {
+                sink.send(message);
+                if (cont != null) {
+                    cont.cont(true);
+                }
+            }
 
-    public void reconnect() {
+            @Override
+            public void handleError() {
+                if (cont != null) {
+                    cont.cont(false);
+                }
+            }
+        });
+    }
+
+    /**
+     * Convenience method for sending messages. Timeout defaults to FOREVER.
+     *
+     * @param message the message to send
+     * @param cont called when the message has been sent successfully or on 
error
+     * @return a handle to cancel sending the message
+     */
+    public Cancelable transmitWhenReady(final GnunetMessage.Body message, 
final Continuation cont) {
+        return transmitWhenReady(RelativeTime.FOREVER, message, cont);
+    }
+
+
+    public final void reconnect() {
         if (connection != null) {
             connection.disconnect();
         }

Modified: gnunet-java/src/org/gnunet/util/Configuration.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Configuration.java  2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Configuration.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -348,7 +348,11 @@
         }
         for (File dir : dirs) {
             if (dir.exists() && dir.isDirectory()) {
-                for (File f : dir.listFiles()) {
+                File[] files = dir.listFiles();
+                if (files == null) {
+                    continue;
+                }
+                for (File f : files) {
                     parse(f.getAbsolutePath());
                 }
             }

Modified: gnunet-java/src/org/gnunet/util/Connection.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Connection.java     2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Connection.java     2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -22,7 +22,7 @@
 
 import org.gnunet.construct.Construct;
 import org.gnunet.construct.MessageLoader;
-import org.gnunet.construct.ProtocolViolation;
+import org.gnunet.construct.ProtocolViolationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,7 +33,6 @@
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.SelectorProvider;
-import java.util.Deque;
 import java.util.LinkedList;
 
 /**
@@ -95,7 +94,17 @@
     private ByteBuffer transmitBuffer = 
ByteBuffer.allocate(GnunetMessage.Header.SIZE);
     private boolean disconnected = false;
 
+    /**
+     * Timeout task for the connect notify.
+     */
+    private Scheduler.TaskConfiguration notifyConnectedTimeout;
 
+    /**
+     * Continuation to call when connected
+     */
+    private Continuation notifyConnectedContinuation;
+
+
     private class AddressProbe {
         Cancelable connectTask;
         SocketChannel channel;
@@ -150,7 +159,7 @@
 
             try {
                 MessageLoader.getUnionClass(GnunetMessage.Body.class, 
msgh.messageType);
-            } catch (ProtocolViolation e) {
+            } catch (ProtocolViolationException e) {
                 found = false;
             }
 
@@ -187,7 +196,7 @@
                             return;
                         }
                     }
-                    logger.debug(String.format("read %s bytes", n));
+                    logger.debug(String.format("read %s bytes from %s", n, 
connectionChannel.socket().toString()));
                 } catch (IOException e) {
                     logger.error("read failed:", e);
                     try {
@@ -263,10 +272,6 @@
             notifyTimeoutTask = tc.schedule();
         }
 
-        public boolean notifyDone() {
-            return notifyTimeoutTask == null;
-        }
-
         public void cancel() {
             if (transmitTask != null) {
                 transmitTask.cancel();
@@ -283,7 +288,7 @@
             this.transmitTask = null;
             try {
                 int n = connectionChannel.write(transmitBuffer);
-                logger.debug("connectionChannel has written " + n + " bytes");
+                logger.debug("connectionChannel has written " + n + " bytes to 
" + connectionChannel.socket().toString());
             } catch (IOException e) {
                 throw new IOError(e);
             }
@@ -372,7 +377,6 @@
 
     class ConnectionResolveHandler implements Resolver.AddressCallback {
         private final int port;
-        private Deque<InetAddress> addressList;
 
         public ConnectionResolveHandler(int port) {
             this.port = port;
@@ -425,7 +429,7 @@
     }
 
     private void finishConnect(SocketChannel channel) {
-        boolean connected = false;
+        boolean connected;
         try {
             connected = channel.finishConnect();
             connectionChannel = channel;
@@ -439,6 +443,7 @@
             logger.debug("finishConnect() was not successful: {}", (Object) e);
             return;
         }
+
         if (connected) {
             if (currentTransmitHelper != null) {
                 currentTransmitHelper.start();
@@ -446,6 +451,16 @@
             if (currentReceiveHelper != null && !currentReceiveHelper.working) 
{
                 currentReceiveHelper.schedule();
             }
+            Continuation c = notifyConnectedContinuation;
+            notifyConnectedContinuation = null;
+            if (notifyConnectedTimeout != null) {
+                notifyConnectedTimeout.cancel();
+                notifyConnectedTimeout = null;
+            }
+            if (c != null) {
+                c.cont(true);
+            }
+
         } else {
             logger.error("socket reported OP_CONNECT but is not connected");
         }
@@ -477,10 +492,10 @@
     /**
      * Receive one message from the network.
      *
-     * @param timeout  deadline after which MessageReceiver.onError will be 
called
+     * @param timeout  deadline after which receiver.onError() will be called
      * @param receiver MessageReceiver that is responsible for the received 
message
      */
-    public ReceiveHandle receive(RelativeTime timeout, MessageReceiver 
receiver) {
+    public ReceiveHandle receive(RelativeTime timeout, final MessageReceiver 
receiver) {
         if (currentReceiveHelper != null) {
             throw new AssertionError("receive must not be called while 
receiving");
         }
@@ -494,6 +509,8 @@
         final ReceiveHelper rh = new ReceiveHelper(receiver, timeout);
         currentReceiveHelper = rh;
 
+        // we can only schedule the receive helper if we are sure the 
connection is made, otherwise
+        // select will misbehave!
         if (connectionChannel.isConnected()) {
             currentReceiveHelper.schedule();
         }
@@ -507,7 +524,7 @@
     }
 
     /**
-     * Call notify once the we are ready to transmit data.
+     * Call the transmitter once the we are ready to transmit data.
      *
      * @param size        number of bytes to send
      * @param timeout     after how long should we give up (and call 
transmitter.transmit(null))
@@ -550,7 +567,34 @@
         };
     }
 
+
     /**
+     * Call cont after establishing the connection or when the timeout has 
occured.
+     *
+     * @param timeout timeout
+     * @param cont continuation to call
+     * @return
+     */
+    /* package-protected */ Cancelable notifyConnected(RelativeTime timeout, 
final Continuation cont) {
+        if (notifyConnectedTimeout != null) {
+            throw new AssertionError();
+        }
+        this.notifyConnectedContinuation = cont;
+        this.notifyConnectedTimeout = Scheduler.addDelayed(timeout, new 
Scheduler.Task() {
+            @Override
+            public void run(Scheduler.RunContext ctx) {
+                Continuation c = notifyConnectedContinuation;
+                notifyConnectedContinuation = null;
+                Connection.this.notifyConnectedTimeout = null;
+                if (c != null) {
+                    c.cont(false);
+                }
+            }
+        });
+        return this.notifyConnectedTimeout;
+    }
+
+    /**
      * Disconnect. There must not be any pending transmit/receive requests.
      * Any buffered data scheduled for writing is discarded.
      */
@@ -567,13 +611,15 @@
         }
 
         if (nextTransmitHelper != null) {
-            logger.error("disconnect called, but there is a 
notifyTransmitReady pending");
+            // todo: do we want the error/warning logging or not?
+            //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");
+            // todo: same here, want or not?
+            // logger.error("disconnect called, but there is a receive 
pending");
             currentReceiveHelper.cancel();
             currentReceiveHelper = null;
         }

Modified: gnunet-java/src/org/gnunet/util/Continuation.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Continuation.java   2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Continuation.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -21,5 +21,5 @@
 package org.gnunet.util;
 
 public interface Continuation {
-    public void cont(boolean success);
+    void cont(boolean success);
 }

Modified: gnunet-java/src/org/gnunet/util/HashCode.java
===================================================================
--- gnunet-java/src/org/gnunet/util/HashCode.java       2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/HashCode.java       2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -21,11 +21,12 @@
 package org.gnunet.util;
 
 
-import org.gnunet.construct.FixedSizeByteArray;
+import org.gnunet.construct.FixedSizeIntegerArray;
 import org.gnunet.construct.Message;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 
 
 /**
@@ -33,7 +34,7 @@
  */
 public class HashCode implements Message {
 
-    @FixedSizeByteArray(length = 64)
+    @FixedSizeIntegerArray(length = 64, signed = false, bitSize = 8)
     public byte[] data; // should be immutable, final, can't be due to 
construct
 
 
@@ -45,7 +46,7 @@
         if (hash.length != 64) {
             throw new AssertionError("HashCode has to have length 64");
         }
-        data = hash;
+        data = Arrays.copyOf(hash, hash.length);
     }
 
     /**

Deleted: gnunet-java/src/org/gnunet/util/HelloMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/util/HelloMessage.java   2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/HelloMessage.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -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.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-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/PeerIdentity.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -21,7 +21,7 @@
 package org.gnunet.util;
 
 
-import org.gnunet.construct.FixedSizeByteArray;
+import org.gnunet.construct.FixedSizeIntegerArray;
 import org.gnunet.construct.Message;
 
 import java.util.Arrays;
@@ -32,7 +32,7 @@
  */
 public class PeerIdentity implements Message {
 
-    @FixedSizeByteArray(length = 64)
+    @FixedSizeIntegerArray(length = 64, signed = false, bitSize = 8)
     public byte[] data;
 
     static final String HEXES = "0123456789ABCDEF";

Modified: gnunet-java/src/org/gnunet/util/Program.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Program.java        2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Program.java        2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -21,8 +21,8 @@
 package org.gnunet.util;
 
 import org.apache.log4j.*;
-import org.gnunet.util.getopt.Option;
-import org.gnunet.util.getopt.OptionAction;
+import org.gnunet.util.getopt.Argument;
+import org.gnunet.util.getopt.ArgumentAction;
 import org.gnunet.util.getopt.Parser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -33,6 +33,8 @@
 /**
  * Program is the entry point class for everything that uses gnunet services 
or APIs.
  *
+ * Also specifies the default command line arguments using the 
org.gnunet.util.getopt annotations.
+ *
  * @see Service
  */
 public abstract class Program {
@@ -42,33 +44,33 @@
 
     protected final Configuration cfg = new Configuration();
 
-    @Option(shortname = "c", longname = "config",
+    @Argument(shortname = "c", longname = "config",
             description = "Path of the configuration file",
             argumentName = "FILENAME",
-            action = OptionAction.STORE_STRING)
+            action = ArgumentAction.STORE_STRING)
     public String cfgFileName;
 
-    @Option(shortname = "h", longname = "help",
+    @Argument(shortname = "h", longname = "help",
             description = "print this help message",
-            action = OptionAction.SET)
+            action = ArgumentAction.SET)
     public boolean printHelp;
 
-    @Option(shortname = "v", longname = "version",
+    @Argument(shortname = "v", longname = "version",
             description = "print version",
-            action = OptionAction.SET)
+            action = ArgumentAction.SET)
     public boolean showVersion;
 
 
-    @Option(shortname = "L", longname = "log",
+    @Argument(shortname = "L", longname = "log",
             description = "configure logging to use LOGLEVEL",
             argumentName = "LOGLEVEL",
-            action = OptionAction.STORE_STRING)
+            action = ArgumentAction.STORE_STRING)
     public String logLevel;
 
-    @Option(shortname = "l", longname = "logfile",
+    @Argument(shortname = "l", longname = "logfile",
             description = "configure logging to write logs to LOGFILE",
             argumentName = "LOGFILE",
-            action = OptionAction.STORE_STRING)
+            action = ArgumentAction.STORE_STRING)
     public String logFile;
 
 
@@ -79,7 +81,7 @@
 
     /**
      * A program with the desired environment for a gnunet utility.
-     * While executing the scheduler is guaranteed to run, command arguments 
are parsed,
+     * While executing, the scheduler is guaranteed to run, command arguments 
are parsed,
      * the default configuration is loaded and the DNS Resolver is initialized.
      *
      * @param args array of command line arguments to parse. used to 
automatically load additional settings
@@ -94,6 +96,12 @@
          */
     }
 
+    /**
+     * Configure logging with the given log level and log file.
+     *
+     * @param logLevel one of DEBUG,INFO,WARN,ERROR,OFF
+     * @param logFile logfile, absolute or relative to the current working 
directory
+     */
     public static void configureLogging(String logLevel, String logFile) {
         org.apache.log4j.Logger rootLogger = LogManager.getRootLogger();
 
@@ -155,7 +163,7 @@
     /**
      * Start the Program as the initial task of the Scheduler.
      */
-    public void start() {
+    public final void start() {
         Parser optParser = new Parser(this);
         unprocessedArgs = optParser.parse(args);
 
@@ -177,13 +185,23 @@
         } else {
             Scheduler.run(new Scheduler.Task() {
                 public void run(Scheduler.RunContext c) {
-                    Program.this.run();
+                    Program.this.runHook();
                 }
             });
         }
     }
 
     /**
+     * Overridden by specializations of Program, like Service.
+     *
+     * Allows for start() to be final.
+     */
+    /* package-private */
+    void runHook() {
+        run();
+    }
+
+    /**
      * Override to implement the behavior of the Program.
      */
     public abstract void run();

Modified: gnunet-java/src/org/gnunet/util/Resolver.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Resolver.java       2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Resolver.java       2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -22,14 +22,12 @@
 
 import com.google.common.net.InetAddresses;
 import org.gnunet.construct.*;
-import org.gnunet.construct.ProtocolViolation;
-import org.gnunet.util.getopt.Option;
-import org.gnunet.util.getopt.OptionAction;
+import org.gnunet.construct.ProtocolViolationException;
+import org.gnunet.util.getopt.Argument;
+import org.gnunet.util.getopt.ArgumentAction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.net.Inet4Address;
-import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.LinkedList;
@@ -85,7 +83,7 @@
 
     @UnionCase(GetMessage.DIRECTION_GET_NAME)
     public static class NumericAddress implements Address {
-        @ByteFill
+        @FillWith @UInt8
         public byte[] addr;
     }
 
@@ -98,7 +96,7 @@
 
 
     public static class ResponseBody implements Message {
-        @ByteFill
+        @FillWith @UInt8
         public byte[] addr;
     }
 
@@ -292,13 +290,13 @@
                                 if (len == 4 || len == 16) {
                                     in_addr = 
InetAddress.getByAddress(gmsg.responseBody.addr);
                                 } else {
-                                    throw new ProtocolViolation("malformed 
address message");
+                                    throw new 
ProtocolViolationException("malformed address message");
                                 }
 
                                 rh.cb.onAddress(in_addr);
                                 rh.receiveTask = 
client.receive(deadline.getRemaining(), this);
                             } catch (UnknownHostException e) {
-                                throw new ProtocolViolation("malformed 
address");
+                                throw new 
ProtocolViolationException("malformed address");
                             }
                         } else {
                             resolveActive = false;
@@ -360,9 +358,9 @@
 
     public static void main(final String[] argv) {
         new Program(argv) {
-            @Option(shortname = "r", longname = "reverse",
+            @Argument(shortname = "r", longname = "reverse",
                     description = "do reverse dns lookup",
-                    action = OptionAction.SET)
+                    action = ArgumentAction.SET)
             boolean isReverse;
 
             @Override

Modified: gnunet-java/src/org/gnunet/util/RunaboutUtil.java
===================================================================
--- gnunet-java/src/org/gnunet/util/RunaboutUtil.java   2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/RunaboutUtil.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -44,7 +44,6 @@
     }
 
     @SuppressWarnings("unchecked")
-    // todo: where to put this?
     public static int[] getRunaboutMessageTypes(Runabout r) {
         ArrayList<Class> visitees = getRunaboutVisitees(r);
         int[] msgtypes = new int[visitees.size()];

Modified: gnunet-java/src/org/gnunet/util/Scheduler.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Scheduler.java      2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Scheduler.java      2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -391,8 +391,9 @@
 
     private static void addSubscriberTask(Collection<TaskConfiguration> 
executableTasks,
                                           TaskConfiguration[] subscribers, int 
eventType) {
-        if (subscribers[eventType] == null)
+        if (subscribers[eventType] == null) {
             return;
+        }
         executableTasks.add(subscribers[eventType]);
         subscribers[eventType].ctx.reasons.add(eventToReason[eventType]);
     }
@@ -570,8 +571,10 @@
 
             ByteBuffer buffer = ByteBuffer.allocate(256);
 
+            boolean quit = false;
+
             try {
-                while (true) {
+                while (!quit) {
                     buffer.clear();
 
                     fileChannel.read(buffer);
@@ -581,17 +584,25 @@
                     pipe.sink().write(buffer);
                 }
             } catch (IOException e) {
-                throw new IOError(e);
+                quit = true;
             }
 
         }
     }
 
-
-    public static FilePipe createFilePipe(File file) {
+    public static FilePipe openFilePipe(File file) {
         FilePipeThread fpt = new FilePipeThread(file);
         fpt.setDaemon(true);
         fpt.start();
         return new FilePipe(fpt);
     }
+
+    public static class AsyncProcess {
+        // getIn, getOut, getErr
+
+    }
+
+    public static AsyncProcess openAsyncProcess(/*...*/) {
+        throw new UnsupportedOperationException("not implemented yet");
+    }
 }

Modified: gnunet-java/src/org/gnunet/util/Server.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Server.java 2012-08-29 22:46:41 UTC (rev 
23512)
+++ gnunet-java/src/org/gnunet/util/Server.java 2012-08-29 23:27:31 UTC (rev 
23513)
@@ -20,6 +20,7 @@
 
 package org.gnunet.util;
 
+import org.gnunet.construct.Construct;
 import org.grothoff.Runabout;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,47 +30,138 @@
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
+/**
+ * A server allows to wait for incoming connections from clients and 
respectively communicate with those clients.
+ */
 public class Server {
     private static final Logger logger = LoggerFactory
             .getLogger(Server.class);
 
+    /**
+     * Default idle timeout for new clients.
+     */
     private final RelativeTime idleTimeout;
+
+    /**
+     * If true, disconnect a client when it sends a message we do not expect 
to receive. Otherwise, the unexpected
+     * message will just be discarded.
+     */
     private final boolean requireFound;
-    private List<ServerSocketChannel> listenSockets;
-    private List<ClientHandle> clients = new LinkedList<ClientHandle>();
 
-    private MessageRunabout receivedMessagehandler;
+    /**
+     * The sockets this server accepts new connections on.
+     */
+    private List<ServerSocketChannel> listenSockets = new 
ArrayList<ServerSocketChannel>();
+
+    /**
+     * The list of all clients connected to this server.
+     */
+    private List<ClientHandle> clientHandles = new LinkedList<ClientHandle>();
+
+    /**
+     * The runabout that receives received messages, as well as information 
about the sender of the last
+     * received message.
+     */
+    private MessageRunabout receivedMessageHandler;
+
+    /**
+     * Whenever a client is disconnected all disconnect handlers are informed.
+     */
     private List<DisconnectHandler> disconnectHandlers = new 
LinkedList<DisconnectHandler>();
-    private ArrayList<Class> expectedMessages;
 
-    private boolean shutdownRequested;
+    /**
+     * Classes of the messages we expect to receive. If a received message is 
not in this list, the client
+     * will be disconnected, otherwise the message is just ignored.
+     */
+    private List<Class> expectedMessages = Collections.emptyList();
+
+    /**
+     * If true, shut down as soon as all non-monitor clients have finished, 
and do not allow new connections
+     * to be made to this server.
+     */
+    private boolean inSoftShutdown;
+
+    /**
+     * Task that is executed as soon as a connection is ready to be accepted.
+     */
     private Cancelable acceptTask;
 
+    /**
+     * True if we are destroyed, or in the process of being destroyed with no 
way back.
+     */
+    private boolean destroyed;
+
+
+    /**
+     * Interface implemented by disconnect handlers, whose onDisconnect method 
is called whenever a client
+     * is disconnected from the server.
+     */
     public interface DisconnectHandler {
+        /**
+         * Called whenever a client is disconnected from the server.
+         *
+         * @param clientHandle the handle for the client that was disconnected
+         */
         void onDisconnect(ClientHandle clientHandle);
     }
 
-
+    /**
+     * A handle to a (remote) client connected to this server.
+     * <p/>
+     * Every client handle keeps a reference count..
+     * Whenever a part of the programs saves a client handle for further 
interaction with it, keep() should be called.
+     * This prevents the server from disconnecting the client when it is idle.
+     * Once this interaction is over, drop() will decrement the reference 
count and eventually disconnect the client
+     * after being idle for long enough.
+     */
     public class ClientHandle {
-        private RelativeTime clientTimeout;
+        /**
+         * The underlying connection to the client-
+         */
         private Connection connection;
 
+        /**
+         * When do we disconnect the client after it has been idle?
+         */
+        private RelativeTime clientTimeout;
+
+        /**
+         * When referenceCount==0, the server is allowed to drop the client 
after a timeout.
+         */
         private int referenceCount = 0;
-        private Connection.ReceiveHandle currentReceive;
 
+        /**
+         * Handle for canceling the receive process of this client, null if no 
receive is currently going on.
+         */
+        private Cancelable currentReceive;
+
+        /**
+         * Set to true if the connection to this client should not prevent the 
server from shutting down.
+         */
         private boolean isMonitor;
 
-        private ClientHandle(SocketChannel accept) {
-            connection = new Connection(accept);
+        /**
+         * Iff true, disconnect the client as soon as possible.
+         * Disconnecting may sometimes not be possible immediately, for 
example when the reference count is not zero.
+         */
+        private boolean disconnectRequested;
+
+        /**
+         * Create a client handle.
+         *
+         * @param sock
+         */
+        private ClientHandle(SocketChannel sock) {
+            connection = new Connection(sock);
             clientTimeout = idleTimeout;
             // start receiving
             receiveDone(true);
         }
 
-
         /**
          * Notify us when the server has enough space to transmit
          * a message of the given size to the given client.
@@ -81,36 +173,63 @@
          * @return a handle to cancel the notification
          */
         public Cancelable notifyTransmitReady(int size, RelativeTime timeout, 
MessageTransmitter transmitter) {
-            return connection.notifyTransmitReady(0, timeout, transmitter);
+            return connection.notifyTransmitReady(size, timeout, transmitter);
         }
 
         /**
+         * Convenience method for sending messages.
+         *
+         * @param timeout when should we give up sending the message, and call 
cont.cont(false)
+         * @param message the message to send
+         * @param cont called when the message has been sent successfully or 
on error
+         * @return a handle to cancel sending the message
+         */
+        public Cancelable transmitWhenReady(final RelativeTime timeout, final 
GnunetMessage.Body message, final Continuation cont) {
+            return notifyTransmitReady(0, timeout, new MessageTransmitter() {
+                @Override
+                public void transmit(Connection.MessageSink sink) {
+                    sink.send(message);
+                    if (cont != null) {
+                        cont.cont(true);
+                    }
+                }
+
+                @Override
+                public void handleError() {
+                    if (cont != null) {
+                        cont.cont(false);
+                    }
+                }
+            });
+        }
+
+        /**
          * Resume receiving from this client, we are done processing the
-         * current request.  This function must be called from within each
+         * current request. This function must be called from within each
          * message handler (or its respective continuations).
          * <p/>
          * The server does not automatically continue to receive messages to
          * support flow control.
          *
-         * @param keepClient false if connection to the client should be closed
+         * @param stayConnected false if connection to the client should be 
closed
          */
-        public void receiveDone(boolean keepClient) {
-            if (keepClient) {
+        public void receiveDone(boolean stayConnected) {
+            if (stayConnected) {
                 currentReceive = connection.receive(RelativeTime.FOREVER, new 
MessageReceiver() {
                     @Override
                     public void process(GnunetMessage.Body msg) {
-                        if (msg instanceof UnknownMessageBody) {
+                        if ((msg instanceof UnknownMessageBody) || 
!expectedMessages.contains(msg.getClass())) {
                             if (requireFound) {
                                 logger.info("disconnecting client sending 
unknown message");
                                 disconnect();
                             }
                             // otherwise, just ignore it
                         }
-                        if (receivedMessagehandler == null) {
+                        if (receivedMessageHandler == null) {
                             throw new AssertionError("received message, but no 
handler installed");
                         }
-                        receivedMessagehandler.setSender(ClientHandle.this);
-                        receivedMessagehandler.visitAppropriate(msg);
+                        receivedMessageHandler.setSender(ClientHandle.this);
+                        receivedMessageHandler.visitAppropriate(msg);
                     }
 
                     @Override
@@ -120,7 +239,12 @@
                     }
                 });
             } else {
-                disconnect();
+                if (referenceCount > 0) {
+                    this.disconnectRequested = true;
+                } else {
+                    System.out.println("disconnecting " + this.isMonitor);
+                    disconnect();
+                }
             }
 
         }
@@ -129,48 +253,86 @@
          * Change the idle timeout of this particular client.
          */
         public void setTimeout(RelativeTime newTimeout) {
+            this.clientTimeout = newTimeout;
         }
 
+        /**
+         * Ask the server to disconnect from the given client.
+         * <p/>
+         * The client will be disconnected from the server, no matter what the 
current reference count is.
+         */
         public void disconnect() {
             connection.disconnect();
-            Server.this.clients.remove(this);
+            // if we are in the process of destruction, to not remove, the 
destruction function will do this,
+            // removing the client handle while in destruction would yield a 
concurrent modification exception
+            if (!destroyed) {
+                Server.this.clientHandles.remove(this);
+            }
             for (DisconnectHandler dh : disconnectHandlers) {
                 dh.onDisconnect(this);
             }
+            Server.this.testForSoftShutdown();
         }
 
         /**
-         * Disable the warning the server issues if a message is not 
acknowledged
-         * in a timely fashion.  Use this call if a client is intentionally 
delayed
-         * for a while.  Only applies to the current message.
+         * Prevent the client from being disconnected.
+         * For every keep, there should be an additional matching drop.
          */
-        public void disableReceiveDoneWarning() {
-            // todo
-        }
-
         public void keep() {
             referenceCount++;
         }
 
+
+        /**
+         * Allow to disconnect this client, if not prevented by previous calls 
to keep.
+         * <p/>
+         * A call to drop should be executed for every call to keep.
+         * After drop() has been executed for every matching keep(), the next 
call to drop()
+         * allows the server to disconnect the client after a timeout.
+         */
         public void drop() {
+            assert referenceCount > 0;
             referenceCount--;
-            if (referenceCount == 0 && shutdownRequested) {
+            if (referenceCount == 0 && disconnectRequested) {
                 disconnect();
             }
         }
 
+
+        /**
+         * Set the 'monitor' flag on this client. Clients which have been
+         * marked as 'monitors' won't prevent the server from shutting down
+         * once 'GNUNET_SERVER_stop_listening' has been invoked.  The idea is
+         * that for "normal" clients we likely want to allow them to process
+         * their requests; however, monitor-clients are likely to 'never'
+         * disconnect during shutdown and thus will not be considered when
+         * determining if the server should continue to exist after
+         * 'GNUNET_SERVER_destroy' has been called.
+         */
         public void markMonitor() {
             this.isMonitor = true;
         }
+
+        public boolean isMonitor() {
+            return isMonitor;
+        }
     }
 
 
-    abstract static class MessageRunabout extends Runabout {
+    /**
+     * All handlers for receiving messages from clients have to inherit this 
class.
+     * <p/>
+     * MessageRunabout is a standard runabout with the added possibility of 
getting the sender of the message.
+     * This is necessary as the runabout's visit methods can have only one 
parameter.
+     */
+    public abstract static class MessageRunabout extends Runabout {
         private ClientHandle currentSender;
 
         /**
          * Allows implementors of MessageRunabout to get the Client that sent 
the message
          * currently visited.
+         * <p/>
+         * The return value of getSender() is only valid while executing a 
visit method.
          *
          * @return handle of the client whose message is currently being 
visited
          */
@@ -178,39 +340,16 @@
             return currentSender;
         }
 
+        /**
+         * Private method used to set the sender for the getSender() method.
+         *
+         * @param clientHandle the client handle to set as the sender
+         */
         private void setSender(ClientHandle clientHandle) {
             currentSender = clientHandle;
         }
     }
 
-
-    private void doAccept(final ServerSocketChannel srv) {
-        Scheduler.TaskConfiguration b = new 
Scheduler.TaskConfiguration(RelativeTime.FOREVER,
-                new Scheduler.Task() {
-                    @Override
-                    public void run(Scheduler.RunContext ctx) {
-                        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);
-                            }
-
-                        } catch (IOException e) {
-                            throw new RuntimeException("accept failed", e);
-                        }
-                        doAccept(srv);
-                    }
-                });
-        b.selectAccept(srv);
-        acceptTask = b.schedule();
-    }
-
-
     /**
      * Create a server listening on all specified addresses.
      *
@@ -221,7 +360,6 @@
     public Server(List<SocketAddress> addresses, RelativeTime idleTimeout, 
boolean requireFound) {
         this.idleTimeout = idleTimeout;
         this.requireFound = requireFound;
-        listenSockets = new ArrayList<ServerSocketChannel>(addresses.size());
         try {
             for (SocketAddress addr : addresses) {
                 ServerSocketChannel socket = ServerSocketChannel.open();
@@ -229,20 +367,53 @@
                 socket.socket().bind(addr);
                 logger.debug("socket listening on {}", addr.toString());
                 listenSockets.add(socket);
-                doAccept(socket);
+                addAcceptSocket(socket);
             }
         } catch (IOException e) {
-            throw new RuntimeException("could not bind");
+            throw new RuntimeException("could not bind", e);
         }
     }
 
+    /**
+     * Create a server, not listening on any sockets yet for new connections.
+     *
+     * @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(RelativeTime idleTimeout, boolean requireFound) {
         this.idleTimeout = idleTimeout;
         this.requireFound = requireFound;
     }
 
-    public void addAcceptSocket(ServerSocketChannel sock) {
-        doAccept(sock);
+    /**
+     * Accept new connections from the given server socket.
+     *
+     * @param sock the new socket to accept connections from
+     */
+    public final void addAcceptSocket(final ServerSocketChannel sock) {
+        Scheduler.TaskConfiguration b = new 
Scheduler.TaskConfiguration(RelativeTime.FOREVER,
+                new Scheduler.Task() {
+                    @Override
+                    public void run(Scheduler.RunContext ctx) {
+                        acceptTask = null;
+                        try {
+                            SocketChannel cli = sock.accept();
+
+                            if (cli != null) {
+                                logger.debug("client connected");
+                                cli.configureBlocking(false);
+                                ClientHandle clientHandle = new 
ClientHandle(cli);
+                                clientHandles.add(clientHandle);
+                            }
+
+                        } catch (IOException e) {
+                            throw new RuntimeException("accept failed", e);
+                        }
+                        addAcceptSocket(sock);
+                    }
+                });
+        b.selectAccept(sock);
+        acceptTask = b.schedule();
     }
 
     /**
@@ -253,10 +424,18 @@
      * @param msgRunabout handler
      */
     public void setHandler(MessageRunabout msgRunabout) {
-        receivedMessagehandler = msgRunabout;
+        receivedMessageHandler = msgRunabout;
         expectedMessages = RunaboutUtil.getRunaboutVisitees(msgRunabout);
     }
 
+    /**
+     * Ask the server to notify us whenever a client disconnects.
+     * This handler is called whenever the actual network connection
+     * is closed; the reference count may be zero or larger than zero
+     * at this point. Note that the disconnect handler is also called when
+     *
+     * @param disconnectHandler handler to call on disconnect
+     */
     public Cancelable notifyDisconnect(final DisconnectHandler 
disconnectHandler) {
         this.disconnectHandlers.add(disconnectHandler);
         return new Cancelable() {
@@ -268,19 +447,63 @@
     }
 
     /**
-     * Stop the listen socket and get ready to shutdown the server
-     * once only 'monitor' clients are left.
+     * Stop the listen socket destroy the server as soon as only monitor 
clients are left.
      */
     public void stopListening() {
-        shutdownRequested = true;
-        // todo: shut down if only monitor clients left
+        inSoftShutdown = true;
+        if (acceptTask != null) {
+            acceptTask.cancel();
+            acceptTask = null;
+        }
+        testForSoftShutdown();
     }
 
+    /**
+     * Disconnect all clients forcefully from the server and stop listening.
+     * <p/>
+     * No methods should be called on a server and its client handles after 
destroy() has been called.
+     */
     public void destroy() {
-        for (ClientHandle h : new ArrayList<ClientHandle>(clients)) {
+        if (destroyed) {
+            return;
+        }
+        destroyed = true;
+        for (ClientHandle h : clientHandles) {
             h.disconnect();
         }
-        acceptTask.cancel();
+        clientHandles.clear();
+        if (acceptTask != null) {
+            acceptTask.cancel();
+            acceptTask = null;
+        }
+        for (ServerSocketChannel ssc : listenSockets) {
+            try {
+                ssc.close();
+            } catch (IOException e) {
+                logger.error("closing listen socket failed", e);
+            }
+        }
     }
 
+    /**
+     * Test if we should destroy outselves.
+     */
+    private void testForSoftShutdown() {
+        // do this so we don't have many recursive calls to 
testForSoftShutdown when shutting down
+        if (destroyed) {
+            return;
+        }
+        if (inSoftShutdown) {
+            System.out.println(""+clientHandles.size());
+            boolean done = true;
+            for (ClientHandle clientHandle : this.clientHandles) {
+                if (!clientHandle.isMonitor) {
+                    done = false;
+                }
+            }
+            if (done) {
+                destroy();
+            }
+        }
+    }
 }

Modified: gnunet-java/src/org/gnunet/util/Service.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Service.java        2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Service.java        2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -29,14 +29,21 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.nio.ByteBuffer;
 import java.nio.channels.Channel;
 import java.nio.channels.FileChannel;
+import java.nio.channels.Pipe;
 import java.nio.channels.SelectableChannel;
 import java.util.LinkedList;
 
 /**
  * Server the entry point class for every gnunet-java component providing 
services
  * to other components.
+ *
+ * The configuration for the server (i.e. ports/interfaces) is loaded with the 
standard configuration system.
+ *
+ * Note that other processes can send signals to the service via a pipe, whose 
name has to be given in the
+ * environment variable GNUNET_OS_CONTROL_PIPE
  */
 public abstract class Service extends Program {
     private static final Logger logger = LoggerFactory
@@ -47,8 +54,9 @@
     private RelativeTime idleTimeout;
     private boolean requireFound;
 
+
     private Cancelable sigpipeTask;
-    private SelectableChannel sigpipeChannel;
+    private Pipe.SourceChannel sigpipeChannel;
 
     public Service(String serviceName, RelativeTime idleTimeout, boolean 
requireFound, String[] args) {
         super(args);
@@ -57,63 +65,94 @@
         this.requireFound = requireFound;
     }
 
-    
+    /**
+     * Obtain the server used by a service.  Note that the server must NOT
+     * be destroyed by the caller.
+     *
+     * @return handle to the server for this service, NULL if there is none
+     */
     public final Server getServer() {
         return s;
     }
 
+    /**
+     * Stop the service.
+     */
     public void stop() {
-
+        s.stopListening();
     }
 
-    public void start() {
-        super.start();
+    public void runHook() {
         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));
+        if (ip4AddrList != null) {
+            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));
+        if (ip6AddrList != null) {
+            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");
-            }
+        if (pipeName != null && !pipeName.isEmpty()) {
+            Scheduler.FilePipe p = Scheduler.openFilePipe(new File(pipeName));
 
             Scheduler.TaskConfiguration t = new 
Scheduler.TaskConfiguration(RelativeTime.FOREVER,
                     new SigpipeTask());
+            t.selectRead(p.getSource());
             sigpipeTask = t.schedule();
+            sigpipeChannel = p.getSource();
         }
+
+        run();
     }
 
-    public class SigpipeTask implements Scheduler.Task {
-
+    private 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();
+            ByteBuffer b = ByteBuffer.allocate(1);
+            int n;
+            try {
+                n = sigpipeChannel.read(b);
+            } catch (IOException e) {
+                logger.error("error reading signal pipe", e);
+                return;
+            }
+            b.flip();
+            boolean stopped = false;
+
+            if (n == 1) {
+                byte sig = b.get();
+                // 15=sigterm
+                if (sig == 15) {
+                    logger.info("service shutting down");
+                    getServer().stopListening();
+                    stopped = true;
+                }
+            }
+            if (!stopped) {
+                Scheduler.TaskConfiguration t = new 
Scheduler.TaskConfiguration(RelativeTime.FOREVER, this);
+                sigpipeTask = t.schedule();
+            } else {
+                try {
+                    sigpipeChannel.close();
+                } catch (IOException e) {
+                    logger.error("could not close sigpipe channel, quitting");
+                    System.exit(2);
+                }
+            }
         }
     }
-
-    /**
-     * Override to implement the behavior of the Program.
-     */
-    public abstract void run();
 }
\ No newline at end of file

Modified: gnunet-java/src/org/gnunet/util/Strings.java
===================================================================
--- gnunet-java/src/org/gnunet/util/Strings.java        2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/Strings.java        2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,6 +26,21 @@
 public class Strings {
     private static final String encTable = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
 
+
+    /**
+     * Convert binary data to ASCII encoding.  The ASCII encoding is rather
+     * GNUnet specific.  It was chosen such that it only uses characters
+     * in [0-9A-V], can be produced without complex arithmetics and uses a
+     * small number of characters.
+     * Does not append 0-terminator, but returns a pointer to the place where
+     * it should be placed, if needed.
+     *
+     * returned string has length ((size*8) + (((size*8) % 5) > 0 ? 5 - 
((size*8) % 5) : 0)) / 5 bytes
+     *
+     * @param data data to encode
+     * @return pointer to the next byte in 'out' or NULL on error.
+     */
+
     public static String dataToString(byte[] data) {
         StringBuilder sb = new StringBuilder();
 
@@ -54,15 +69,25 @@
         return sb.toString();
     }
 
-    public static byte[] stringToData(String string) {
-        /*
+    /**
+     * Convert ASCII encoding back to data
+     * out_size must match exactly the size of the data before it was encoded.
+     *
+     * @param string the string to decode
+     * @param outSize size of the output buffer
+     * @return GNUNET_OK on success, GNUNET_SYSERR if result has the wrong 
encoding
+     */
+
+    public static byte[] stringToData(String string, int outSize) {
         long rpos;
         long wpos;
         long bits;
         long vbit;
-        int ret;
-        int shift;
-        int encoded_len = out_size * 8;
+        long ret;
+        long shift;
+        int enclen = string.length();
+        int encoded_len = outSize * 8;
+        byte[] out = new byte[outSize];
         if (encoded_len % 5 > 0) {
             // padding!
             vbit = encoded_len % 5;
@@ -75,29 +100,39 @@
             throw new AssertionError();
         }
 
-        wpos = out_size;
+        wpos = outSize;
         rpos = enclen;
-        bits = (ret = getValue__(enc[--rpos])) >> (5 - encoded_len % 5);
-        if (-1 == ret)
-            return GNUNET_SYSERR;
+        bits = (ret = getValue__(string.charAt((int) (--rpos)))) >> (5 - 
encoded_len % 5);
+        if (-1 == ret) {
+            throw new AssertionError();
+        }
         while (wpos > 0) {
-            GNUNET_assert(rpos > 0);
-            bits = ((ret = getValue__(enc[--rpos])) << vbit) | bits;
-            if (-1 == ret)
-                return GNUNET_SYSERR;
+            assert rpos > 0;
+            bits = ((ret = getValue__(string.charAt((int) (--rpos)))) << vbit) 
| bits;
+            if (-1 == ret) {
+                throw new AssertionError();
+            }
             vbit += 5;
             if (vbit >= 8) {
-                out[--wpos] = (unsigned char)bits;
+                out[(int)--wpos] = (byte)((char) bits);
                 bits >>= 8;
                 vbit -= 8;
             }
         }
-        GNUNET_assert(rpos == 0);
-        GNUNET_assert(vbit == 0);
-        return GNUNET_OK;
+        assert(rpos == 0);
+        assert(vbit == 0);
+        return out;
+    }
 
+
+    private static int getValue__ (char a) {
+        if ((a >= '0') && (a <= '9')) {
+            return a - '0';
+        }
+        if ((a >= 'A') && (a <= 'V')) {
+            return (a - 'A' + 10);
+        }
+        return -1;
     }
-    */
-    throw new UnsupportedOperationException("not yet implemented");
-    }
+
 }

Deleted: gnunet-java/src/org/gnunet/util/TESTMessage.java
===================================================================
--- gnunet-java/src/org/gnunet/util/TESTMessage.java    2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/TESTMessage.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -1,31 +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 org.gnunet.construct.UnionCase;
-
-/**
- * Sent back when a client sends this message to a service.
- */
address@hidden(1)
-public class TESTMessage implements GnunetMessage.Body {
-    // empty
-}

Copied: gnunet-java/src/org/gnunet/util/TestMessage.java (from rev 23244, 
gnunet-java/src/org/gnunet/util/TESTMessage.java)
===================================================================
--- gnunet-java/src/org/gnunet/util/TestMessage.java                            
(rev 0)
+++ gnunet-java/src/org/gnunet/util/TestMessage.java    2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -0,0 +1,31 @@
+/*
+ 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.UnionCase;
+
+/**
+ * Sent back when a client sends this message to a service.
+ */
address@hidden(1)
+public class TestMessage implements GnunetMessage.Body {
+    // empty
+}

Modified: gnunet-java/src/org/gnunet/util/UnknownMessageBody.java
===================================================================
--- gnunet-java/src/org/gnunet/util/UnknownMessageBody.java     2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/util/UnknownMessageBody.java     2012-08-29 
23:27:31 UTC (rev 23513)
@@ -25,7 +25,7 @@
  * is not understood, and therefore no real message body could be constructed.
  *
  * Note that this class implements GnunetMessage.Body but does not have a 
MessageID associated.
- * This message should not be sent/received over the network as a message body.
+ * This message should not, and can not, be sent/received over the network 
directly as a message body.
  *
  * @author Florian Dold
  */

Copied: gnunet-java/src/org/gnunet/util/getopt/Argument.java (from rev 23244, 
gnunet-java/src/org/gnunet/util/getopt/Option.java)
===================================================================
--- gnunet-java/src/org/gnunet/util/getopt/Argument.java                        
        (rev 0)
+++ gnunet-java/src/org/gnunet/util/getopt/Argument.java        2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,47 @@
+/*
+ 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.getopt;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for fields receiving an argument from the command line.
+ */
address@hidden(RetentionPolicy.RUNTIME)
address@hidden(ElementType.FIELD)
+public @interface Argument {
+    public String shortname();
+    public String longname();
+    /**
+     * Possible values: "store-string", "set", "reset", "count", "store-int"
+     */
+    public ArgumentAction action();
+    /*
+     * Name of the Option's argument(s), empty string of option takes no 
arguments
+     *
+     */
+    public String argumentName() default "";
+    public String description();
+}

Copied: gnunet-java/src/org/gnunet/util/getopt/ArgumentAction.java (from rev 
23244, gnunet-java/src/org/gnunet/util/getopt/OptionAction.java)
===================================================================
--- gnunet-java/src/org/gnunet/util/getopt/ArgumentAction.java                  
        (rev 0)
+++ gnunet-java/src/org/gnunet/util/getopt/ArgumentAction.java  2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,29 @@
+/*
+ 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.getopt;
+
+
+/**
+ * Possibilities for what should happen when an argument is read from the 
command line
+ */
+public enum ArgumentAction {
+    SET, RESET, STORE_STRING, STORE_NUMBER
+}

Deleted: gnunet-java/src/org/gnunet/util/getopt/Option.java
===================================================================
--- gnunet-java/src/org/gnunet/util/getopt/Option.java  2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/getopt/Option.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -1,44 +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.getopt;
-
-
-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 Option {
-    public String shortname();
-    public String longname();
-    /**
-     * Possible values: "store-string", "set", "reset", "count", "store-int"
-     */
-    public OptionAction action();
-    /*
-     * Name of the Option's argument(s), empty string of option takes no 
arguments
-     *
-     */
-    public String argumentName() default "";
-    public String description();
-}

Deleted: gnunet-java/src/org/gnunet/util/getopt/OptionAction.java
===================================================================
--- gnunet-java/src/org/gnunet/util/getopt/OptionAction.java    2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/src/org/gnunet/util/getopt/OptionAction.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,26 +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.getopt;
-
-
-public enum OptionAction {
-    SET, RESET, STORE_STRING, STORE_NUMBER, INCREMENT
-}

Modified: gnunet-java/src/org/gnunet/util/getopt/Parser.java
===================================================================
--- gnunet-java/src/org/gnunet/util/getopt/Parser.java  2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/gnunet/util/getopt/Parser.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -22,7 +22,6 @@
 
 import org.gnunet.construct.ReflectUtil;
 import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.util.*;
 
 /**
@@ -45,10 +44,10 @@
      * An option together with its target field.
      */
     static class OptionField {
-        Option opt;
+        Argument opt;
         Field f;
 
-        public OptionField(Option opt, Field f) {
+        public OptionField(Argument opt, Field f) {
             this.opt = opt;
             this.f = f;
         }
@@ -66,7 +65,7 @@
     private Map<String, OptionField> longOpt = new HashMap<String, 
OptionField>();
     private Map<String, OptionField> shortOpt = new HashMap<String, 
OptionField>();
 
-    private Collection<Option> options = new LinkedList<Option>();
+    private Collection<Argument> arguments = new LinkedList<Argument>();
 
     private Object targetObject;
 
@@ -75,11 +74,7 @@
         this.targetObject = targetObject;
         // gather option annotations
         for (Field f : getFields(targetObject.getClass())) {
-            if (f.isSynthetic() || Modifier.isStatic(f.getModifiers())) {
-                continue;
-            }
-            // todo: validity checking of annotations
-            Option opt = f.getAnnotation(Option.class);
+            Argument opt = f.getAnnotation(Argument.class);
             if (opt != null) {
                 if (opt.shortname().length() != 1) {
                     throw new AssertionError("short name must be of length 1");
@@ -89,14 +84,14 @@
 
                 longOpt.put(opt.longname(), new OptionField(opt, f));
                 shortOpt.put(opt.shortname(), new OptionField(opt, f));
-                options.add(opt);
+                arguments.add(opt);
             }
         }
     }
 
     public String getHelp() {
         StringBuilder helpString = new StringBuilder();
-        for (Option opt : options) {
+        for (Argument opt : arguments) {
             StringBuilder line = new StringBuilder();
             line.append("  -");
             line.append(opt.shortname());
@@ -118,10 +113,10 @@
         return helpString.toString();
     }
 
-    public void doLongOpt(final LinkedList<String> argsList, Field 
targetField, Option option, String right) {
+    private void doLongOpt(final LinkedList<String> argsList, Field 
targetField, Argument argument, String right) {
         try {
             Class targetFieldType = targetField.getType();
-            switch (option.action()) {
+            switch (argument.action()) {
                 case SET:
                     if (!targetFieldType.equals(Boolean.TYPE)) {
                         throw new AssertionError("action SET only valid on 
boolean member");
@@ -141,7 +136,7 @@
                     if (right == null) {
                         argsList.removeFirst();
                         if (argsList.isEmpty()) {
-                            throw new ArgumentError("missing string argument 
to option " + option.longname());
+                            throw new ArgumentError("missing string argument 
to option " + argument.longname());
                         }
                         targetField.set(targetObject, argsList.getFirst());
                     } else {
@@ -154,7 +149,7 @@
                     if (right == null) {
                         argsList.removeFirst();
                         if (argsList.isEmpty()) {
-                            throw new ArgumentError("missing number argument 
to option " + option.longname());
+                            throw new ArgumentError("missing number argument 
to option " + argument.longname());
                         }
                         numString = argsList.getFirst();
                     } else {
@@ -163,11 +158,9 @@
                     try {
                         nf.set(targetObject, Long.parseLong(numString));
                     } catch (NumberFormatException e) {
-                        throw new ArgumentError("error in number format to 
option " + option.longname());
+                        throw new ArgumentError("error in number format to 
option " + argument.longname());
                     }
                     break;
-                case INCREMENT:
-                    throw new UnsupportedOperationException("not yet 
implemented");
             }
         } catch (IllegalAccessException e) {
             throw new AssertionError(
@@ -175,9 +168,13 @@
         }
     }
 
-    public boolean doShortOpt(final LinkedList<String> argsList, Field 
targetField, Option option, String shortName) {
+    /**
+     * returns true if we processed a shortopt with a parameter, and thus have 
to discard the rest
+     * of the current argument string (that is, stop scanning for more 
shortopts)
+     */
+    private boolean doShortOpt(final LinkedList<String> argsList, Field 
targetField, Argument argument, String shortName) {
         try {
-            switch (option.action()) {
+            switch (argument.action()) {
                 case SET:
                     if (!targetField.getType().equals(Boolean.TYPE)) {
                         throw new AssertionError("action SET only valid on 
boolean member");
@@ -186,16 +183,15 @@
                     break;
                 case RESET:
                     if (!targetField.getType().equals(Boolean.TYPE)) {
-                        throw new AssertionError("action RESET only valid on 
boolean member");
+                        throw new AssertionError("action RESET only valid on 
boolean field");
                     }
                     targetField.set(targetObject, false);
                     break;
                 case STORE_STRING:
                     if (!targetField.getType().equals(String.class)) {
-                        throw new AssertionError("action STORE_STRING only 
valid on boolean " +
-                                "member");
+                        throw new AssertionError("action STORE_STRING only 
valid on 'String' field");
                     }
-                    if (argsList.getFirst().length() == 2) { // -X
+                    if (argsList.getFirst().length() == 2) { // -P xxx (with 
space)
                         argsList.removeFirst();
                         if (argsList.isEmpty()) {
                             throw new ArgumentError(String.format("no argument 
for short option '%s'",
@@ -205,31 +201,25 @@
                     } else {
                         targetField.set(targetObject, 
argsList.getFirst().substring(2)); // -Pxxx...
                     }
-                    // consumed entire shortopt
                     return true;
                 case STORE_NUMBER:
                     ReflectUtil.NumField nf = new 
ReflectUtil.NumField(targetField);
                     String numString;
-                    boolean consumed;
                     if (argsList.getFirst().length() == 2) { // -X
                         argsList.removeFirst();
                         if (argsList.isEmpty()) {
-                            throw new ArgumentError("missing number argument 
to option " + option.longname());
+                            throw new ArgumentError("missing number argument 
to option " + argument.longname());
                         }
                         numString = argsList.getFirst();
-                        consumed = false;
                     } else {
                         numString = argsList.getFirst().substring(2);
-                        consumed = true;
                     }
                     try {
                         nf.set(targetObject, Long.parseLong(numString));
                     } catch (NumberFormatException e) {
-                        throw new ArgumentError("error in number format to 
option " + option.longname());
+                        throw new ArgumentError("error in number format to 
option " + argument.longname());
                     }
-                    return consumed;
-                case INCREMENT:
-                    throw new UnsupportedOperationException("not yet 
implemented");
+                    return true;
             }
         } catch (IllegalAccessException e) {
             throw new ArgumentError(
@@ -238,7 +228,6 @@
         return false; // did not consume entire shortopt -Xxxxxx
     }
 
-
     /**
      * Parses the given arguments, and sets the target object's fields
      * according to its annotations.
@@ -271,7 +260,8 @@
                 }
                 String right = (components.length == 2) ? components[1] : null;
                 doLongOpt(argsList, of.f, of.opt, right);
-            } else if (argsList.getFirst().length() > 1 && 
argsList.getFirst().startsWith("-")) {
+            } else if ((argsList.getFirst().length() > 1) && 
argsList.getFirst().startsWith("-")) {
+                // handle each flag after the "-"
                 for (int i = 1; i < argsList.getFirst().length(); ++i) {
                     String optShortName = argsList.getFirst().substring(i, i + 
1);
                     OptionField of = shortOpt.get(optShortName);
@@ -280,13 +270,13 @@
                                 String.format("unknown short option: -%s", 
argsList.getFirst().charAt(i)));
                     }
 
-                    boolean consumed = doShortOpt(argsList, of.f, of.opt, 
optShortName);
+                    boolean discard = doShortOpt(argsList, of.f, of.opt, 
optShortName);
 
-                    if (consumed && i != 1) {
+                    if (discard && (i != 1)) {
                         throw new ArgumentError("short options with argument 
must be seperate");
                     }
 
-                    if (consumed) {
+                    if (discard) {
                         break;
                     }
 

Modified: gnunet-java/src/org/grothoff/Runabout.java
===================================================================
--- gnunet-java/src/org/grothoff/Runabout.java  2012-08-29 22:46:41 UTC (rev 
23512)
+++ gnunet-java/src/org/grothoff/Runabout.java  2012-08-29 23:27:31 UTC (rev 
23513)
@@ -54,7 +54,7 @@
  * <ul>
  * <li>all subclasses must be public, sadly this also means that <strong>you
  * can not use an anonymous inner class</strong> (!)</li>
- * <li>the types to all arguments of visit methods must be public</li>
+ * <li>the types_length to all arguments of visit methods must be public</li>
  * <li>all visit methods must be public (!)</li>
  * </ul>
  * Otherwise the visitor will die with an IllegalAccessError during execution.
@@ -265,7 +265,8 @@
                                 } catch (IllegalAccessException e) {
                                     throw new RunaboutException(e.toString());
                                 } catch (InvocationTargetException e) {
-                                    e.getCause().printStackTrace();
+                                    System.err.println("stacktrace:");
+                                    e.getCause().printStackTrace(System.out);
                                     throw new 
RunaboutException(e.getCause().toString());
                                 }
                             }

Modified: gnunet-java/src/org/grothoff/package-info.java
===================================================================
--- gnunet-java/src/org/grothoff/package-info.java      2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/src/org/grothoff/package-info.java      2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -1,4 +1,4 @@
 /**
- * java implementation of single argument multiple dispatch
+ * Pure java implementation of single argument multiple dispatch
  */
 package org.grothoff;

Modified: gnunet-java/test/org/gnunet/construct/ByteFillMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/ByteFillMessage.java  2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/ByteFillMessage.java  2012-08-29 
23:27:31 UTC (rev 23513)
@@ -26,7 +26,7 @@
     @UInt32
     public int someValue;
 
-    @ByteFill
+    @FillWith @UInt8
     public byte[] rest;
     
 }

Modified: gnunet-java/test/org/gnunet/construct/ConstructTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/ConstructTest.java    2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/ConstructTest.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -13,7 +13,7 @@
         @FrameSize
         @UInt32
         public int frameSize;
-        @ByteFill
+        @FillWith @UInt8
         public byte[] bytes;
     }
 

Added: gnunet-java/test/org/gnunet/construct/FillParserTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/FillParserTest.java                   
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/FillParserTest.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,37 @@
+package org.gnunet.construct;
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class FillParserTest {
+
+    public static class FillTestMessage implements Message {
+        @FrameSize
+        @UInt32
+        public int size;
+        @FillWith
+        public StringTuple[] strings;
+    }
+
+    @Test
+    public void test_fillParser() {
+        FillTestMessage m = new FillTestMessage();
+        m.strings = new StringTuple[]{new StringTuple("foo", "bar"), new 
StringTuple("quux", "spam")};
+        Construct.patch(m);
+        System.out.println(m.size);
+        byte[] data = Construct.toBinary(m);
+        Assert.assertEquals(m.size, data.length);
+
+        FillTestMessage m2 = Construct.parseAs(data, FillTestMessage.class);
+
+        Assert.assertEquals(m.strings.length, m2.strings.length);
+
+        Assert.assertEquals(m.strings[0], m2.strings[0]);
+        Assert.assertEquals(m.strings[1], m2.strings[1]);
+    }
+}

Added: gnunet-java/test/org/gnunet/construct/FixedSizeTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/FixedSizeTest.java                    
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/FixedSizeTest.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,52 @@
+package org.gnunet.construct;
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class FixedSizeTest {
+
+    public static class Msg implements Message {
+        @UInt8
+        public int v;
+
+        public Msg() {
+            // default ctor required by Construct
+        }
+
+        public Msg(int v) {
+            this.v = v;
+        }
+    }
+
+    public static class FixedSizeTestMessage implements Message {
+        @FixedSizeArray(length = 4)
+        public Msg[] msgs;
+    }
+
+
+    @Test
+    public void test_fixedNested() {
+        FixedSizeTestMessage m = new FixedSizeTestMessage();
+        m.msgs = new Msg[]{new Msg(1), new Msg(2), new Msg(3), new Msg(4)};
+        byte[] bytes = Construct.toBinary(m);
+
+        FixedSizeTestMessage m2 = Construct.parseAs(bytes, 
FixedSizeTestMessage.class);
+
+        Assert.assertEquals(m.msgs[0].v, m2.msgs[0].v);
+        Assert.assertEquals(m.msgs[1].v, m2.msgs[1].v);
+        Assert.assertEquals(m.msgs[2].v, m2.msgs[2].v);
+        Assert.assertEquals(m.msgs[3].v, m2.msgs[3].v);
+    }
+
+    @Test(expected = AssertionError.class)
+    public void test_sizeMismatch() {
+        FixedSizeTestMessage m = new FixedSizeTestMessage();
+        m.msgs = new Msg[]{new Msg(1), new Msg(2)};
+        byte[] bytes = Construct.toBinary(m);
+    }
+}

Added: gnunet-java/test/org/gnunet/construct/FrameSizeTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/FrameSizeTest.java                    
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/FrameSizeTest.java    2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,50 @@
+package org.gnunet.construct;
+
+import junit.framework.Assert;
+import org.gnunet.util.GnunetMessage;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class FrameSizeTest {
+    public static class CoordMessage implements Message {
+        @FrameSize
+        @UInt32
+        public int size;
+        @UInt32
+        public int x;
+        @UInt8
+        public int y;
+    }
+
+    public static class RecursiveMessage implements Message {
+        @FrameSize
+        @UInt32
+        public int size;
+
+        @ZeroTerminatedString
+        public String data;
+
+        @NestedMessage(newFrame = true, optional = true)
+        public RecursiveMessage rec;
+
+    }
+
+    @Test
+    public void test_simple() {
+        CoordMessage m = new CoordMessage();
+        Construct.patch(m);
+        Assert.assertEquals(9, m.size);
+    }
+
+
+    //@Test
+    public void test_recursive_1() {
+        RecursiveMessage rm = new RecursiveMessage();
+        rm.data = "foo";
+        Construct.patch(rm);
+    }
+}

Modified: gnunet-java/test/org/gnunet/construct/QueryMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/QueryMessage.java     2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/QueryMessage.java     2012-08-29 
23:27:31 UTC (rev 23513)
@@ -26,6 +26,6 @@
     @UInt8
     public int query;
 
-    @ByteFill
+    @FillWith @UInt8
     public byte[] varsize;
 }

Added: gnunet-java/test/org/gnunet/construct/SendMessageTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SendMessageTest.java                  
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/SendMessageTest.java  2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,34 @@
+package org.gnunet.construct;
+
+import org.gnunet.core.SendMessage;
+import org.gnunet.util.AbsoluteTime;
+import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.PeerIdentity;
+import org.gnunet.util.TestMessage;
+import org.junit.Test;
+
+/**
+ * Regression test for a message class in org.gnunet.core
+ *
+ * todo: should this test be really here?
+ *
+ * @author Florian Dold
+ */
+public class SendMessageTest {
+
+    @Test
+    public void test_patch() {
+        SendMessage m = new SendMessage();
+        m.deadline = AbsoluteTime.FOREVER.asMessage();
+        m.peer = new PeerIdentity(); // null identity
+        m.payloadMessage = new GnunetMessage();
+        m.payloadMessage.body = new TestMessage();
+        m.payloadMessage.header = new GnunetMessage.Header();
+
+        GnunetMessage container = new GnunetMessage();
+        container.body = m;
+        container.header = new GnunetMessage.Header();
+
+        Construct.patch(container);
+    }
+}

Deleted: gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java        
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/SimpleTestMessage.java        
2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,36 +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.construct;
-
-public class SimpleTestMessage implements Message {
-
-    @UInt8
-    public short v1;
-
-    @UInt8
-    public short v2;
-
-    @NestedMessage
-    public SimpleTestMessage2 mn;
-    
-    @FixedSizeArray(length=5)
-    public SimpleTestMessage2[] mns;
-}

Deleted: gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java       
2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/SimpleTestMessage2.java       
2012-08-29 23:27:31 UTC (rev 23513)
@@ -1,29 +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.construct;
-
-//@MessageId(321)
-public class SimpleTestMessage2 implements Message {
-
-    @UInt32
-    public long value;
-
-}

Deleted: gnunet-java/test/org/gnunet/construct/SizeTestMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/SizeTestMessage.java  2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/SizeTestMessage.java  2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,34 +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.construct;
-
-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/StringTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/StringTest.java                       
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/StringTest.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,50 @@
+package org.gnunet.construct;
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class StringTest {
+    public static class StrMsg implements Message {
+        @FrameSize
+        @UInt32
+        public int len;
+        @ZeroTerminatedString(optional = false)
+        public String str1;
+        @ZeroTerminatedString(optional = true)
+        public String str2;
+    }
+
+
+    @Test
+    public void test_empty() {
+        StrMsg m = new StrMsg();
+        m.str1 = "";
+        m.str2 = "";
+        Construct.patch(m);
+        byte[] data = Construct.toBinary(m);
+        Assert.assertEquals(4+1+1, data.length);
+        StrMsg m2 = Construct.parseAs(data, StrMsg.class);
+        Assert.assertEquals("", m2.str1);
+        Assert.assertEquals("", m2.str2);
+    }
+
+    @Test
+    public void test_null() {
+        StrMsg m = new StrMsg();
+        m.str1 = "";
+        m.str2 = null;
+        Construct.patch(m);
+        byte[] data = Construct.toBinary(m);
+        Assert.assertEquals(4+1, data.length);
+        Assert.assertEquals(4+1, m.len);
+        StrMsg m2 = Construct.parseAs(data, StrMsg.class);
+        Assert.assertEquals("", m2.str1);
+        Assert.assertEquals(null, m2.str2);
+    }
+}
+

Added: gnunet-java/test/org/gnunet/construct/StringTuple.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/StringTuple.java                      
        (rev 0)
+++ gnunet-java/test/org/gnunet/construct/StringTuple.java      2012-08-29 
23:27:31 UTC (rev 23513)
@@ -0,0 +1,29 @@
+package org.gnunet.construct;
+
+/**
+* ...
+*
+* @author Florian Dold
+*/
+public class StringTuple implements Message {
+    @ZeroTerminatedString
+    public String str1;
+    @ZeroTerminatedString
+    public String str2;
+
+    public StringTuple() {
+        // empty default ctor needed by Construct
+    }
+    public StringTuple(String str1, String str2) {
+        this.str1 = str1;
+        this.str2 = str2;
+    }
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof StringTuple)) {
+            return false;
+        }
+        StringTuple otherT = (StringTuple) other;
+        return otherT.str1.equals(this.str1) && otherT.str2.equals(this.str2);
+    }
+}

Deleted: gnunet-java/test/org/gnunet/construct/VarTestMessage.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/VarTestMessage.java   2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/construct/VarTestMessage.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,29 +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.construct;
-
-public class VarTestMessage implements Message {
-    @UInt16
-    public long length;
-    
-    @VariableSizeArray(lengthField="length")
-    public SimpleTestMessage2[] msgs;
-}

Added: gnunet-java/test/org/gnunet/construct/VariableSizeArrayTest.java
===================================================================
--- gnunet-java/test/org/gnunet/construct/VariableSizeArrayTest.java            
                (rev 0)
+++ gnunet-java/test/org/gnunet/construct/VariableSizeArrayTest.java    
2012-08-29 23:27:31 UTC (rev 23513)
@@ -0,0 +1,33 @@
+package org.gnunet.construct;
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class VariableSizeArrayTest {
+    public static class VariableTestMessage implements Message {
+        @UInt32
+        public int num;
+        @VariableSizeArray(lengthField = "num")
+        public StringTuple[] msgs;
+    }
+
+    @Test
+    public void test_variableSizeArray() {
+        VariableTestMessage m = new VariableTestMessage();
+        m.msgs = new StringTuple[]{new StringTuple("foo", "bar"), new 
StringTuple("quux", "baz"), new StringTuple("spam", "eggs")};
+        Construct.patch(m);
+        Assert.assertEquals(3, m.num);
+        byte[] data = Construct.toBinary(m);
+        VariableTestMessage m2 = Construct.parseAs(data, 
VariableTestMessage.class);
+        Assert.assertEquals(m2.num, 3);
+        Assert.assertEquals(m.msgs[0], m2.msgs[0]);
+        Assert.assertEquals(m.msgs[1], m2.msgs[1]);
+        Assert.assertEquals(m.msgs[2], m2.msgs[2]);
+
+    }
+}

Modified: gnunet-java/test/org/gnunet/core/CoreTest.java
===================================================================
--- gnunet-java/test/org/gnunet/core/CoreTest.java      2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/test/org/gnunet/core/CoreTest.java      2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -26,18 +26,15 @@
 import org.gnunet.util.*;
 import org.grothoff.Runabout;
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import static org.junit.Assert.assertTrue;
 
 public class CoreTest {
-    TestingSetup testing = new TestingSetup();
-
     @Test(timeout = 500)
     public void test_core_init() {
 
-        TestingSubsystem ts = testing.startSubsystem("core");
+        TestingSubsystem ts = new TestingSubsystem("core");
 
         final Wrapper<Boolean> res = new Wrapper<Boolean>(false);
 
@@ -68,13 +65,13 @@
     @Test(timeout = 5000)
     public void test_core_echo() {
 
-        TestingSubsystem ts = testing.startSubsystem("core");
+        TestingSubsystem ts = new TestingSubsystem("core");
 
         final Wrapper<Boolean> gotResponse = new Wrapper<Boolean>(false);
 
         final Core core = new Core(ts.getConfiguration());
         core.setMessageHandler(new Runabout() {
-            public void visit(TESTMessage t) {
+            public void visit(TestMessage t) {
                 gotResponse.set(true);
                 core.disconnect();
             }
@@ -86,7 +83,7 @@
                 core.notifyTransmitReady(0, RelativeTime.FOREVER, myIdentity, 
4, new MessageTransmitter() {
                     @Override
                     public void transmit(Connection.MessageSink sink) {
-                        sink.send(new TESTMessage());
+                        sink.send(new TestMessage());
                     }
 
                     @Override

Modified: gnunet-java/test/org/gnunet/dht/DHTTest.java
===================================================================
--- gnunet-java/test/org/gnunet/dht/DHTTest.java        2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/test/org/gnunet/dht/DHTTest.java        2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -33,10 +33,8 @@
     public void test_dht_put() {
         final Wrapper<Boolean> putFinished = new Wrapper<Boolean>(true);
 
-        TestingSetup testing = new TestingSetup();
+        TestingSubsystem ts = new TestingSubsystem("dht");
 
-        TestingSubsystem ts = testing.startSubsystem("dht");
-
         final DistributedHashTable dht = new 
DistributedHashTable(ts.getConfiguration());
         dht.put(new HashCode("gnj-test"), new byte[]{1, 2, 3}, 1, 
EnumSet.noneOf(RouteOption.class),
                 BlockType.TEST.val, RelativeTime.HOUR.toAbsolute(), 
RelativeTime.FOREVER, new Continuation() {

Modified: gnunet-java/test/org/gnunet/nse/NSETest.java
===================================================================
--- gnunet-java/test/org/nse/NSETest.java       2012-08-14 23:45:49 UTC (rev 
23244)
+++ gnunet-java/test/org/gnunet/nse/NSETest.java        2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -18,9 +18,8 @@
  Boston, MA 02111-1307, USA.
  */
 
-package org.nse;
+package org.gnunet.nse;
 
-import org.gnunet.nse.NetworkSizeEstimation;
 import org.gnunet.testing.TestingSetup;
 import org.gnunet.testing.TestingSubsystem;
 import org.gnunet.util.AbsoluteTime;
@@ -38,8 +37,7 @@
     @Test
     public void test_nse() {
         final Wrapper<Boolean> gotResult = new Wrapper<Boolean>(false);
-        TestingSetup testing = new TestingSetup();
-        TestingSubsystem ts = testing.startSubsystem("nse");
+        TestingSubsystem ts = new TestingSubsystem("nse");
 
         final NetworkSizeEstimation nse = new 
NetworkSizeEstimation(ts.getConfiguration());
         nse.subscribe(new NetworkSizeEstimation.Subscriber() {

Modified: gnunet-java/test/org/gnunet/statistics/StatisticsTest.java
===================================================================
--- gnunet-java/test/org/gnunet/statistics/StatisticsTest.java  2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/statistics/StatisticsTest.java  2012-08-29 
23:27:31 UTC (rev 23513)
@@ -27,9 +27,6 @@
 import org.junit.Test;
 
 public class StatisticsTest {
-    TestingSetup testing = new TestingSetup();
-
-
     public interface Next {
         void next();
     }
@@ -64,7 +61,8 @@
 
     @Test(timeout = 1000)
     public void test_simple() {
-        final TestingSubsystem ts = testing.startSubsystem("statistics");
+        Program.configureLogging("DEBUG", null);
+        final TestingSubsystem ts = new TestingSubsystem("statistics");
 
         final Statistics stat = new Statistics(ts.getConfiguration());
 
@@ -97,7 +95,7 @@
 
     @Test(timeout = 1000)
     public void test_statistics_get_set() {
-        final TestingSubsystem ts = testing.startSubsystem("statistics");
+        final TestingSubsystem ts = new TestingSubsystem("statistics");
 
         final AssertionList assertions = new AssertionList();
 
@@ -149,7 +147,7 @@
 
     @Test(timeout = 1000)
     public void test_watch() {
-        final TestingSubsystem ts = testing.startSubsystem("statistics");
+        final TestingSubsystem ts = new TestingSubsystem("statistics");
 
         final Wrapper<Integer> updates = new Wrapper<Integer>(0);
 

Modified: gnunet-java/test/org/gnunet/testing/TestingSetupTest.java
===================================================================
--- gnunet-java/test/org/gnunet/testing/TestingSetupTest.java   2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/testing/TestingSetupTest.java   2012-08-29 
23:27:31 UTC (rev 23513)
@@ -29,8 +29,7 @@
     @Test(timeout = 1000)
     public void test_testing() {
         // could be any service, just use statistics
-        TestingSetup testing = new TestingSetup();
-        TestingSubsystem ts = testing.startSubsystem("statistics");
+        TestingSubsystem ts = new TestingSubsystem("statistics");
         String port = ts.getConfiguration().getValueString("statistics", 
"PORT");
         org.junit.Assert.assertTrue(port != null);
 
@@ -39,16 +38,13 @@
 
     @Test(expected = TestingSetup.SetupException.class)
     public void test_no_service() {
-        TestingSetup testing = new TestingSetup();
-        testing.startSubsystem("foobar _ !!!");
+        new TestingSubsystem("foobar _ !!!");
     }
 
     @Test(timeout = 1000)
     public void test_restart() {
-        // could be any service, just use statistics
-        TestingSetup testing = new TestingSetup();
-        TestingSubsystem ts = testing.startSubsystem("statistics");
-        //ts.restart();
+        TestingSubsystem ts = new TestingSubsystem("statistics");
+        ts.restart();
         ts.destroy();
     }
 }

Modified: gnunet-java/test/org/gnunet/util/ClientServerTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/ClientServerTest.java      2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/util/ClientServerTest.java      2012-08-29 
23:27:31 UTC (rev 23513)
@@ -1,10 +1,16 @@
 package org.gnunet.util;
 
+import com.google.common.collect.Lists;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.UnionCase;
 import org.gnunet.testing.TestingServer;
 import org.gnunet.testing.TestingSetup;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.net.*;
+import java.util.ArrayList;
+
 /**
  * ...
  *
@@ -12,20 +18,26 @@
  */
 public class ClientServerTest {
 
+    @Test
+    public void test_start_stop() {
+        Program.configureLogging("DEBUG", null);
+        final TestingServer srv = new TestingServer();
+        srv.server.stopListening();
+    }
+
     /**
      * Test if the server receives a message sent by a client.
      */
-    @Test(timeout = 1000)
+    @Test
     public void test_testing_server() {
-        final TestingSetup setup = new TestingSetup();
         Program.configureLogging("DEBUG", null);
 
-        final TestingServer srv = setup.createServer();
+        final TestingServer srv = new TestingServer();
 
         final Wrapper<Boolean> gotMessage = new Wrapper<Boolean>(false);
 
         srv.server.setHandler(new Server.MessageRunabout() {
-            public void visit(TESTMessage tm) {
+            public void visit(TestMessage tm) {
                 gotMessage.set(true);
                 srv.server.destroy();
             }
@@ -39,7 +51,7 @@
                     @Override
                     public void transmit(Connection.MessageSink sink) {
                         System.out.println("ntr!");
-                        sink.send(new TESTMessage());
+                        sink.send(new TestMessage());
                     }
 
                     @Override
@@ -57,13 +69,12 @@
 
     /**
      * Test what happens when a client calls notifyTransmitReady, but does not 
send
-     * a message in the callback but disconnects.
+     * a message in the callback and disconnects.
      */
     @Test(timeout = 1000)
     public void test_premature_disconnect() {
-        final TestingSetup setup = new TestingSetup();
         Program.configureLogging("DEBUG", null);
-        final TestingServer srv = setup.createServer();
+        final TestingServer srv = new TestingServer();
 
         srv.server.notifyDisconnect(new Server.DisconnectHandler() {
             @Override
@@ -79,7 +90,7 @@
                 cli.notifyTransmitReady(RelativeTime.FOREVER,true, 0, new 
MessageTransmitter() {
                     @Override
                     public void transmit(Connection.MessageSink sink) {
-                        sink.send(new TESTMessage());
+                        sink.send(new TestMessage());
                         cli.disconnect();
                     }
 
@@ -91,4 +102,146 @@
             }
         });
     }
+
+
+    @Test
+    public void test_receiveDone() {
+        Program.configureLogging("DEBUG", null);
+        final TestingServer srv = new TestingServer();
+
+        final Wrapper<Integer> msgCount = new Wrapper<Integer>(0);
+
+        srv.server.setHandler(new Server.MessageRunabout() {
+            public void visit(TestMessage tm) {
+                msgCount.set(msgCount.get() + 1);
+                if (msgCount.get() == 3) {
+                    getSender().receiveDone(false);
+                    srv.server.stopListening();
+                } else {
+                    getSender().receiveDone(true);
+                }
+            }
+        });
+
+        Scheduler.run(new Scheduler.Task() {
+            @Override
+            public void run(Scheduler.RunContext ctx) {
+                final Client cli = srv.createClient();
+
+                cli.transmitWhenReady(RelativeTime.FOREVER, new TestMessage(), 
new Continuation() {
+                    @Override
+                    public void cont(boolean success) {
+                        cli.transmitWhenReady(RelativeTime.FOREVER, new 
TestMessage(), new Continuation() {
+                            @Override
+                            public void cont(boolean success) {
+                                cli.transmitWhenReady(RelativeTime.FOREVER, 
new TestMessage(), null);
+                            }
+                        });
+                    }
+                });
+            }
+        });
+    }
+
+    @Test
+    public void test_acceptFromAddresses() {
+        Program.configureLogging("DEBUG", null);
+
+        InetAddress localhost = null;
+        try {
+           localhost = Inet4Address.getLocalHost();
+        } catch (UnknownHostException e) {
+            Assert.fail();
+        }
+
+        // does this work on all operating systems?
+        SocketAddress addr = new InetSocketAddress(localhost, 0);
+
+        Server server = new Server(Lists.newArrayList(addr), 
RelativeTime.FOREVER, false);
+
+        server.destroy();
+
+    }
+
+
+    @Test
+    public void test_keep_drop() {
+        Program.configureLogging("DEBUG", null);
+        final TestingServer srv = new TestingServer();
+
+        final Wrapper<Integer> msgCount = new Wrapper<Integer>(0);
+
+
+
+        srv.server.setHandler(new Server.MessageRunabout() {
+            public void visit(TestMessage tm) {
+                srv.server.stopListening();
+                if (msgCount.get() == 0) {
+                    getSender().keep();
+                    getSender().drop();
+                    getSender().receiveDone(true);
+                } else if (msgCount.get() == 1) {
+                    getSender().receiveDone(false);
+
+                } else {
+                    Assert.fail();
+                }
+
+                msgCount.set(msgCount.get() + 1);
+            }
+        });
+
+        Scheduler.run(new Scheduler.Task() {
+            @Override
+            public void run(Scheduler.RunContext ctx) {
+                final Client cli = srv.createClient();
+                cli.transmitWhenReady(new TestMessage(), new Continuation() {
+                    @Override
+                    public void cont(boolean success) {
+                        cli.transmitWhenReady(new TestMessage(), null);
+                    }
+                });
+            }
+        });
+    }
+
+
+
+    /**
+    * test if markMonitor / soft shutdown works.
+    */
+    @Test
+    public void test_monitor_clients() {
+        Program.configureLogging("DEBUG", null);
+        final TestingServer srv = new TestingServer();
+
+        final Wrapper<Integer> msgCount = new Wrapper<Integer>(0);
+
+        srv.server.setHandler(new Server.MessageRunabout() {
+            public void visit(TestMessage tm) {
+                if (msgCount.get() == 0) {
+                    getSender().markMonitor();
+                    getSender().receiveDone(true);
+                } else if (msgCount.get() == 1) {
+                    srv.server.stopListening();
+                    getSender().receiveDone(false);
+                } else {
+                    Assert.fail();
+                }
+
+                msgCount.set(msgCount.get() + 1);
+            }
+        });
+
+        Scheduler.run(new Scheduler.Task() {
+            @Override
+            public void run(Scheduler.RunContext ctx) {
+                final Client cli1 = srv.createClient();
+                final Client cli2 = srv.createClient();
+
+                cli1.transmitWhenReady(new TestMessage(), null);
+                cli2.transmitWhenReady(new TestMessage(), null);
+            }
+        });
+    }
 }

Modified: gnunet-java/test/org/gnunet/util/FilePipeExample.java
===================================================================
--- gnunet-java/test/org/gnunet/util/FilePipeExample.java       2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/util/FilePipeExample.java       2012-08-29 
23:27:31 UTC (rev 23513)
@@ -13,8 +13,9 @@
 public class FilePipeExample {
     public static void main(String... args) {
 
+        Program.configureLogging("DEBUG", null);
 
-        final Scheduler.FilePipe fp = Scheduler.createFilePipe(new 
File("test.pipe"));
+        final Scheduler.FilePipe fp = Scheduler.openFilePipe(new 
File("test.pipe"));
 
 
         Scheduler.addRead(RelativeTime.FOREVER, fp.getSource(), new 
Scheduler.Task() {

Added: gnunet-java/test/org/gnunet/util/MeshTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/MeshTest.java                              
(rev 0)
+++ gnunet-java/test/org/gnunet/util/MeshTest.java      2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -0,0 +1,36 @@
+package org.gnunet.util;
+
+import org.gnunet.mesh.Mesh;
+import org.gnunet.testing.TestingSubsystem;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class MeshTest {
+
+    @Test
+    public void test_tunnel_create() {
+        /*
+        Program.configureLogging("DEBUG", null);
+        TestingSubsystem ts = new TestingSubsystem("mesh");
+
+        Mesh m = new Mesh(ts.getConfiguration(), null, null, new 
RunaboutMessageReceiver() {
+            public void visit(TestMessage tm) {
+
+            }
+            @Override
+            public void handleError() {
+
+            }
+        });
+
+        m.createTunnel(null, null);
+
+        Sc
+        Sheduler.run();
+        */
+    }
+}

Modified: gnunet-java/test/org/gnunet/util/ResolverTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/ResolverTest.java  2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/test/org/gnunet/util/ResolverTest.java  2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -43,11 +43,9 @@
         final Wrapper<Boolean> finished1 = new Wrapper<Boolean>(true);
         final Wrapper<Boolean> finished2 = new Wrapper<Boolean>(true);
 
-        TestingSetup testing = new TestingSetup();
+        TestingSubsystem ts = new TestingSubsystem("resolver");
 
-        TestingSubsystem ts = testing.startSubsystem("resolver");
 
-
         Resolver r = Resolver.getInstance();
         r.setConfiguration(ts.getConfiguration());
 

Modified: gnunet-java/test/org/gnunet/util/ServerExample.java
===================================================================
--- gnunet-java/test/org/gnunet/util/ServerExample.java 2012-08-29 22:46:41 UTC 
(rev 23512)
+++ gnunet-java/test/org/gnunet/util/ServerExample.java 2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -23,7 +23,6 @@
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.util.Arrays;
-import java.util.LinkedList;
 
 import static org.gnunet.util.Server.*;
 
@@ -43,13 +42,13 @@
                         RelativeTime.MINUTE,
                         false);
                 s.setHandler(new Server.MessageRunabout() {
-                    public void visit(TESTMessage tm) {
+                    public void visit(TestMessage tm) {
                         System.out.println("got TEST message");
                         final Server.ClientHandle sender = getSender();
                         sender.notifyTransmitReady(4, RelativeTime.FOREVER, 
new MessageTransmitter() {
                             @Override
                             public void transmit(Connection.MessageSink sink) {
-                                sink.send(new TESTMessage());
+                                sink.send(new TestMessage());
                                 System.out.println("TEST message sent");
                                 sender.receiveDone(true);
                             }

Added: gnunet-java/test/org/gnunet/util/StringsTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/StringsTest.java                           
(rev 0)
+++ gnunet-java/test/org/gnunet/util/StringsTest.java   2012-08-29 23:27:31 UTC 
(rev 23513)
@@ -0,0 +1,20 @@
+package org.gnunet.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * ...
+ *
+ * @author Florian Dold
+ */
+public class StringsTest {
+    @Test
+    public void test_inverse() {
+        byte[] data = "asdfgASDD$!123".getBytes();
+        String str = Strings.dataToString(data);
+        byte[] data2 = Strings.stringToData(str, data.length);
+        Assert.assertArrayEquals(data, data2);
+    }
+}
+

Modified: gnunet-java/test/org/gnunet/util/getopt/GetoptTest.java
===================================================================
--- gnunet-java/test/org/gnunet/util/getopt/GetoptTest.java     2012-08-29 
22:46:41 UTC (rev 23512)
+++ gnunet-java/test/org/gnunet/util/getopt/GetoptTest.java     2012-08-29 
23:27:31 UTC (rev 23513)
@@ -25,8 +25,8 @@
 import org.junit.Test;
 
 class Target {
-    @Option(
-            action = OptionAction.STORE_STRING,
+    @Argument(
+            action = ArgumentAction.STORE_STRING,
             shortname = "s",
             longname = "string",
             argumentName = "SOME_STRING",
@@ -34,16 +34,16 @@
     )
     String someString;
 
-    @Option(
-            action = OptionAction.SET,
+    @Argument(
+            action = ArgumentAction.SET,
             shortname = "y",
             longname = "set",
             description = "enable, default disabled"
     )
     boolean set = false;
 
-    @Option(
-            action = OptionAction.RESET,
+    @Argument(
+            action = ArgumentAction.RESET,
             shortname = "n",
             longname = "reset",
             description = "disable, default enabled"
@@ -51,35 +51,29 @@
     boolean reset = true;
 
 
-    @Option(
-            action = OptionAction.INCREMENT,
-            shortname = "i",
-            longname = "inc",
-            description = "increment a counter"
-    )
-    int counter = 0;
-
-    @Option(
-            action = OptionAction.STORE_NUMBER,
+    @Argument(
+            action = ArgumentAction.STORE_NUMBER,
             shortname = "w",
             longname = "value",
             description = "some value"
     )
     int intVal = 0;
+
+    static int someConstant = 42;
 }
 
+class InvalidTarget {
+    @Argument(action = ArgumentAction.SET, shortname = "foo", longname = 
"bar", description = "bla bla")
+    boolean foo;
+}
+
 public class GetoptTest {
     @Test
     public void test_str() {
         Target t = new Target();
         Parser p = new Parser(t);
 
-        t.someString = null;
 
-        // argument after shortopt
-        p.parse(new String[]{"-s", "foo"});
-        Assert.assertEquals("foo", t.someString);
-        
         t.someString = null;
         
         // argument directly with shortopt
@@ -88,6 +82,12 @@
 
         t.someString = null;
 
+        // argument after shortopt
+        p.parse(new String[]{"-s", "foo"});
+        Assert.assertEquals("foo", t.someString);
+
+        t.someString = null;
+
         p.parse(new String[]{"--string=foo"});
         Assert.assertEquals("foo", t.someString);
 
@@ -186,6 +186,21 @@
         Assert.assertArrayEquals(new String[]{"foo", "bar", "--reset", "baz"}, 
rest);
     }
 
+
+    @Test(expected = Parser.ArgumentError.class)
+    public void test_missingLongopt() {
+        Target t = new Target();
+        Parser p = new Parser(t);
+        p.parse(new String[]{"--foobar"});
+    }
+
+    @Test(expected = Parser.ArgumentError.class)
+    public void test_missingShortopt_1() {
+        Target t = new Target();
+        Parser p = new Parser(t);
+        p.parse(new String[]{"-x"});
+    }
+
     @Test
     public void test_long() {
         Target t = new Target();
@@ -196,6 +211,9 @@
         rest = p.parse(new String[]{"-w5"});
         Assert.assertEquals(5, t.intVal);
 
+        rest = p.parse(new String[]{"-w", "5"});
+        Assert.assertEquals(5, t.intVal);
+
         rest = p.parse(new String[]{"--value=6"});
         Assert.assertEquals(6, t.intVal);
 
@@ -213,4 +231,57 @@
         }
         Assert.assertTrue(thrown);
     }
+
+
+    @Test(expected = Parser.ArgumentError.class)
+    public void test_missingNumberArgument_short() {
+        Target t = new Target();
+        Parser p = new Parser(t);
+
+        p.parse(new String[]{"-w"});
+        Assert.assertEquals(5, t.intVal);
+    }
+
+    @Test(expected = Parser.ArgumentError.class)
+    public void test_missingNumberArgument_long() {
+        Target t = new Target();
+        Parser p = new Parser(t);
+
+
+        p.parse(new String[]{"--w"});
+        Assert.assertEquals(5, t.intVal);
+    }
+
+
+    @Test(expected = Parser.ArgumentError.class)
+    public void test_invalidNumberFormat() {
+        Target t = new Target();
+        Parser p = new Parser(t);
+
+        String[] rest;
+
+        rest = p.parse(new String[]{"-w", "abc"});
+        Assert.assertEquals(5, t.intVal);
+    }
+
+
+    @Test
+    public void test_dashRest() {
+        Target t = new Target();
+        Parser p = new Parser(t);
+
+        String[] rest;
+
+        rest = p.parse(new String[]{"-w", "123", "-"});
+        Assert.assertArrayEquals(new String[]{"-"}, rest);
+    }
+
+
+    @Test(expected = AssertionError.class)
+    public void test_invalid() {
+        InvalidTarget it = new InvalidTarget();
+        Parser p = new Parser(it);
+
+        p.parse(new String[]{"-foo"});
+    }
 }

Modified: gnunet-java/tools/build
===================================================================
--- gnunet-java/tools/build     2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/tools/build     2012-08-29 23:27:31 UTC (rev 23513)
@@ -12,6 +12,9 @@
 BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
 
 
+OUTDIR="$BASEDIR/build/"
+
+
 # collect all source files
 SOURCES_PROD=`find "$BASEDIR/src/" -name "*.java"`
 SOURCES_TEST=`find "$BASEDIR/test/" -name "*.java"`

Modified: gnunet-java/tools/coverage
===================================================================
--- gnunet-java/tools/coverage  2012-08-29 22:46:41 UTC (rev 23512)
+++ gnunet-java/tools/coverage  2012-08-29 23:27:31 UTC (rev 23513)
@@ -6,9 +6,6 @@
 
 echo $INSTRUMENT_CMD
 
-set -x
-
-
 case "$1" in
 instrument)
     echo "instrumenteing"




reply via email to

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