aboutsummaryrefslogtreecommitdiff
path: root/doc/gnunet-java-tutorial.tex
blob: 225a02aeacdb23755b8d9702960221aedd55fa3b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
\documentclass[10pt]{article}
\usepackage[ansinew]{inputenc}
\usepackage{makeidx,amsmath,amssymb,exscale,multicol,epsfig,graphics,verbatim,ulem}
\usepackage{epsfig,geometry,url,listings,subcaption,boxedminipage}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\geometry{headsep=3ex,hscale=0.9}
\usepackage{hyperref}
\hypersetup{
  pdftitle={gnunet-java tutorial},
  pdfsubject={gnunet-java},
  pdfauthor={Florian Dold <dold@in.tum.de>},
  pdfkeywords={gnunet,java,tutorial},
  colorlinks=true, % otherwise the boxes overlap content
  urlcolor=blue
}

\lstset{
basicstyle=\ttfamily,  
upquote=true,
columns=fullflexible,
literate={*}{{\char42}}1
         {-}{{\char45}}1
         {\\\$}{{\$ }}1
}

\newcommand{\exercise}[1]{\vskip5pt\noindent\begin{boxedminipage}{\textwidth}{\bf Exercise:} #1 \end{boxedminipage}}

\title{A Tutorial for GNUnet 0.10.x (Java version)}

\author{Florian Dold}

\begin{document}

\maketitle

Although GNUnet is primarily developed in the C programming language, it is also possible to write peer-to-peer applications
with GNUnet in Java.
The GNUnet-Java project provides bindings to a subset of existing GNUnet components, as well as the infrastructure to
develop new components.  GNUnet-Java is less stable and less complete than the C version. Please report any bugs or feature requests at \url{https://gnunet.org/bugs/}.

\section{Getting Started}
\subsection{Installing GNUnet}
This tutorial assumes that you have GNUnet $\geq$ 0.10.x installed on your
machine.  Instructions on how to do this can be found at
\url{https://gnunet.org/installation}, or in the C version of the GNUnet
tutorial.  
Make sure to run {\tt ./configure} with the option {\tt -{}-enable-javaports}, in order to allow
Java clients to connect to GNUnet services.
Start your GNUnet peer with the command {\tt gnunet-arm -s} and convince yourself that the default GNUnet services are running by typing {\tt gnunet-arm -I}.

\exercise{%
  Read the first three chapters of the GNUnet C tutorial, available at
  \url{https://gnunet.org/svn/gnunet/doc/gnunet-c-tutorial.pdf}.
}

\subsection{Other Dependencies}
Make sure that you have OpenJDK 6 or later installed on your system. 

\section{A simple GNUnet-Java extension}
The simplest way to create a new GNUnet component in Java is to copy
the template extension project,  which already contains a build system
and sample code.

Obtain the extension template from the subversion repository:
\begin{lstlisting}[language=bash,deletekeywords={export}]
\$ svn export https://gnunet.org/svn/gnunet-java-ext/ my-extension
\$ cd my-extension
\end{lstlisting}

The template project uses Gradle\footnote{\url{http://gradle.org}} as a build system.  Simply use the \texttt{./gradlew}
script to run build tasks.  The wrapper script will automatically download the correct version
of Gradle on the first run.  Alternatively, download Gradle$\ge$1.11 yourself, and use the \texttt{gradle} command
directly instead of the wrapper.

Build the template project by running the \texttt{assemble} task:
\begin{lstlisting}[language=bash]
\$ ./gradlew assemble
\end{lstlisting}
This will download all direct and transitive dependencies.  Gradle stores all dependencies in an internal cache.  Run
\begin{lstlisting}[language=bash]
\$ ./gradlew copyDeps
\end{lstlisting}
in order to copy all dependencies into the \texttt{lib/} folder\footnote{This is not strictly necessary---you can also
ask Gradle for the classpath pointing to the internal cache. However, having all dependencies in one folder
is more convenient, especially when using shell wrappers for Java entry points later on.}.

Check if you're on the right track by running the Java client for GNUnet's network size estimation service:
\begin{lstlisting}[language=bash]
\$ java -cp 'lib/*' org.gnunet.nse.NetworkSizeEstimation
\end{lstlisting}
This should print something like \texttt{est: 42.3 dev: 3.14 t: Sun Apr 06 23:40:37 CEST 2014} to
your terminal.  If the program hangs, check if your peer is running and correctly configured.

\subsection{The Basics}

This is the most basic skeleton for a GNUnet-Java application:
\begin{lstlisting}[language=java]
import org.gnunet.util.*;
public class HelloGnuNet {
    public static void main(String[] args) {
            new Program() {
                public void run() {
                    System.out.println("Hello, GNUnet");
                }
            }.start(args);
}
\end{lstlisting}

Calling {\tt start} initializes GNUnet-Java, parses the command line,
loads configuration files and starts the task scheduler, with the code
in the {\tt run} method executed in the initial task.

\exercise{%
  Get the code above to execute by placing it in a \texttt{*.java} file
  in \texttt{src/main/java/}, running the \texttt{assemble} task from Gradle,
  and invoking \texttt{java} with the right parameters.
The source code in the extension template should follow
the the Maven Standard Directory Layout%
\footnote{\url{https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html}}
for application code, tests and resources.
}

\subsection{Adding and using command line arguments}

Command line options are added by annotating members of your
{\tt org.gnunet.util.Program} subclass with the \@Option-annotation.

Here is a simple example:
\begin{lstlisting}[language=java]
new Program(args) {
    @Option(
        shortname = "n",
        longname = "name",
        action = OptionAction.STORE_STRING,
        description = "the name of the person you want to greet")
    String name = "Jane Doe"; // default value if option is missing
[...]
}
\end{lstlisting}

You can now specify a value for the member {\tt name} at the command
line, either by the long name with two dashes ({\tt -{}-name=Foo} / {\tt
-{}-name FOO}) or the short name ({\tt -n FOO}) with one dash.

Before the \texttt{run} method is called, the field {\tt name} will
be set to the given argument.  If the \texttt{name} option is missing,
the field will keep the value specified in the constructor or the field's initializer.

The \texttt{\@Option} annotation can not only be used with Strings, but also
with booleans and numbers. These are a few of the available options:

\begin{itemize}
\item {\tt STORE\_STRING}: Store a string in a {\tt String} variable
\item {\tt STORE\_NUMBER}: Store a number in a member of primitive type
\item {\tt SET}: Set a {\tt boolean} to {\tt true}
\end{itemize}

By default, the following arguments are available on the command line:

\begin{itemize}
  \item {\tt -h} / {\tt -{}-help} shows the help text
  \item {\tt -v} / {\tt -{}-version} shows version information
  \item {\tt -c} / {\tt -{}-config} specify an additional configuration file to load
  \item {\tt -L} / {\tt -{}-log} specify the log level
  \item {\tt -l} / {\tt -{}-logfile} specify a file to write the logs to
\end{itemize}

You can change the about text and the version information by
overriding the {\tt makeHelpText} or {\tt makeVersionDescription} methods in your
{\tt Program} subclass.

\exercise{Add a few different command line options to your program and print them with {\tt System.out}!}

\subsection{Shell Wrappers}
It is usually more convenient to have a shell wrapper for each entry point than
it is to pass the main class and classpath to the JVM manually every time.  The
shell wrappers in the \texttt{bin/} directory of the template set the JVM
classpath classpath relative to the location of the script file.  The shell wrappers
should therefore always be kept in the \texttt{bin/} directory.

\exercise{Copy the wrapper \texttt{bin/my-ext} and modify it to
call your \texttt{HelloGnuNet} class.}

\subsection{More Documentation}
The documentation for \texttt{gnunet-java} generated by Javadoc is available
at \url{https://gnunet.org/javadoc/}.

\section{The statistics API}
The statistics service allows to store numbers under a subsystem and a name.
These values are available to other components, even after your program quits.

\subsection{Connecting to the statistics service}

\begin{lstlisting}[language=java]
Statistics statistics = new Statistics(getConfiguration());
\end{lstlisting}

The Statistics constructor is called with the configuration,
provided by the method {\tt getConfiguration} of the {\tt Program}
class.  The configuration contains the necessary information (port numbers, socket paths, \dots) to establish a connection to the
statistics service.  As with most API calls in GNUnet-Java, this
operation is asynchronous, meaning that the above statement
does not wait for the connection to be established, but returns immediately.

Always remember to explicitly destroy your {\tt
  Statistics} instance by calling its {\tt destroy()}
method. Otherwise there might be pending operations that prevent the
termination of your program.

\subsection{Setting statistics}

You can use the newly created {\tt statistics} handle to, for instance,
set the value named ``\# bytes sent'' to the value 42.
\begin{lstlisting}[language=java]
statistics.set("gnunet-java-hello", "# bytes sent", 42, true);
\end{lstlisting}
The last parameter (\texttt{true})
indicates that the value should be stored persistently (%
persistent values are stored even if the statistics service restarts).


\subsection{Retrieving statistics}

Retrieving a value is slightly more complex. Because of the
asynchronous nature of the GNUnet-Java APIs, the {\tt get} method
does not directly return values, but a handle (implementing the
interface {\tt Cancelable}) to cancel the get request.
The actual values are accessed by passing a callback object to the {\tt get}
method.

This example retrieves the statistics value ``\# Requests Served'' for the subsystem ``gnunet-java-hello''
\begin{lstlisting}[language=java]
Cancelable getCancel = statistics.get(RelativeTime.SECOND, "gnunet-java-hello",
        "# Requests Served", new Statistics.StatisticsReceiver {
    public void onDone() {
        System.out.println("everything done");
    }
    public void onReceive(String subsystem, String name, long val) {
        System.out.println(subsyste + " " + name + " " + val);
    }
    public void onTimeout() {
        // called if the service does not respond after the
        // specified timeout (one second)
        System.out.println("timeout occured");
    }
});
\end{lstlisting}

\exercise{Read the Javadoc of the statistics service.  What other operations can be done on statistics values, other
than reading and writing them?}
\exercise{Write a program that increments a statistics value each second. Check the result with the {\tt gnunet-statistics} command line tool.
\emph{Hint}: Use \texttt{Scheduler.addDelayed} to run a function after a timeout. }

\section{Sending encrypted messages}

The CORE service is one of the most important components of GNUnet, and
allows sending encrypted messages to directly connected peers.  Be aware that,
depending on the used transport protocol, messages sent by CORE arrive with
varying reliability.

\subsection{Defining new Messages}

All GNUnet messages follow a common format.  Every
message consists of a header (with the message size and the message
type) and a body.  The same message format is used both for communication between
GNUnet services and clients, as well as between peers in the network.

You can define a new type of message in GNUnet-Java by annotating a
class with information on how to represent its members in binary format.

Additionally, you have to register your new message type with
GNUnet-Java, giving it a unique message type number.  Here is an example:

\begin{lstlisting}[language=java]
@UnionCase(4242)
public class ExampleMessage implements GnunetMessage.Body {
    @UInt8
    public int age;
    @ZeroTerminatedString;
    public String name;
}
\end{lstlisting}

The {\tt @UnionCase} annotation specifies the message type id of the
message body below (4242 in the example).  GnunetMessage.Body is a
union of messages, and ExampleMessage is one (new) member of the
union.

Every time you add a new type of GNUnet message, you have to run the command
\lstset{language=bash}
\begin{lstlisting}
\$ ./gradle msgtypes
\end{lstlisting}
This generates the file {\tt
  src/main/java/org/gnunet/construct/MsgMap.txt}, which allows the system to
instantiate the right Java class when de-serializing a message from its binary representation.

The above message then contains a value annotated with {\tt @UInt8}:
An {\bf 8}-bit {\bf U}nsigned {\bf int}eger.  There are similar
annotations for integers of other sizes, and {\tt @Int}{\it N}
annotations for signed integers.  The second member is a String, whose
binary representation appends a zero-byte to the string to mark its
end.

Other useful annotations can be found in the package {\tt
  org.gnunet.construct}. Among them are annotations for arrays of
fixed or variable size ({\tt @VariableSizeArray, @FixedSizeArray}),
for embedding other messages in your message ({\tt @NestedMessage} and
for implementing your own message unions.

\exercise{Define a message that contains a 32-bit signed integer.}
\exercise{%
  Look at the class {\tt  org.gnunet.dht.messages.MonitorPutMessage} in the GNUnet-Java source
  code\footnote{\url{https://gnunet.org/svn/gnunet-java/}}.
  This message uses a variety of different annotations, try to understand the purpose
  of each member's annotation.
}

\subsection{Connecting to Core}

After creating a handle to CORE by calling the {\tt Core} constructor,
you have to specify what types of messages you are interested in. The
CORE service will only send messages of these types to you, and only
notify you of connecting peers if they share a subset of the messages
you are interested in.

The {\tt handleMessages} method allows you to specify an object of a
class inheriting {\tt Runabout}.  The Runabout is a mechanism for
single-argument multiple dispatch in Java.  You have to define one
{\tt visit} method for every type of message you are interested in.
Once {\tt Core} receives a message, it is dispatched dynamically to
the {\tt visit} method with the appropriate signature.  Note that
every {\tt visit} method, as well as the receiver's class, has to be
public in order for the dynamic dispatch to work.

Example:

\begin{lstlisting}[language=java]
public class MyMessageReceiver extends Runabout {
    public void visit(MyFooMessage m) {
      // do something 
    }
    public void visit(MyBarMessage m) {
      // do something else 
    }
}
\end{lstlisting}

After specifying your message handler, the {\tt init} method has to be
called with a callback object.  This starts the handshake with the
CORE service, and once done the callback object's {\tt onInit} method will
be called with your peer's identity.

\subsection{Sending a message to another peer}

Before you can actually send a message, you have to wait until the
CORE service is ready to send your message.  This is done by calling
the {\tt notifyTransmitReady} method. You have to provide a callback
object to this method, whose {\tt transmit} method is invoked with a
{\tt MessageSink} object once CORE is ready to transmit your
message.  Call the {\tt transmit} method in the {\tt MessageSink}
with a {\tt GnunetMessage.Body} in order transmit it to CORE.
to finally transmit it. The header of the message is automatically
added to your message body.

Example:
\begin{lstlisting}[language=java]
// arguments: messagePriority, timeout, targetPeer, messageSize, transmitter
core.notifyTransmitReady(0, RelativeTime.FOREVER, myIdentity, 42, new MessageTransmitter() {
    public transmit(Connection.MessageSink sink) {
        sink.transmit(myMessage);
    }
    public handleError() {
        // do something
    }
\end{lstlisting}

You can use {\tt Construct.getSize} to calculate the size of a
message, or compute it manually.

\exercise{Write an echo program for CORE: Send a message to the local peer and receive it!}

\section{Establishing channels to remote peers with MESH}
In contrast to CORE, the MESH
service can send messages reliably (if requested) over channels to distant peers, who must not necessarily be directly connected.
The following code connects to the mesh service, and waits for connections on port 42:
\begin{lstlisting}[language=java]
Mesh m = new Mesh(cfg, inboundChannelHandler, messageHandler, 42);
\end{lstlisting}

The \texttt{inboundChannelHandler}'s \texttt{onInboundChannel} is called whenever another peer wants to establish a connection
to our peer on port 42.  The \texttt{messageHandle} must be a Runabout instance, and implement visit methods analogously to the
CORE message handler in the previous section.

The following snippet establishes a channel to the given peer on port 42, where
the channel should not buffer data (first boolean argument) and be reliable (second boolean argument).
\begin{lstlisting}[language=java]
Channel c = m.createChannel(targetPeer, 42, true, true);
\end{lstlisting}

A channel can be used to send messages, which are first queued and then sent to the mesh service:
\begin{lstlisting}[language=java]
c.send(myMessage);
\end{lstlisting}

Using this way of sending messages may cause the message queue of the channel to fill up quickly.
To prevent this, wrap the message in an \texttt{Envelope}, which can invoke a notification callback
once the message has been sent to the service:
\begin{lstlisting}[language=java]
Envelope ev = new Envelope(myMessage);
ev.notifySent(myNotifySentHandler);
c.send(myMessage);
// use ev.cancel() to abort sending the message
\end{lstlisting}
Note that the notification is called when the local MESH service accepts the message for further transmission,
not when the target peer receives the message.

\exercise{Write a netcat-style tool that allows to interactively send and receive a stream of text on the command line over MESH.}

\section{Managing a peer's egos}
An ego in GNUnet is a name tied to a key pair. Egos can represent the identity of actual users, organisations,
or more abstract entities.  Managed by the \texttt{IDENTITY} service, egos are entirely local to your peer.

For looking up the key of egos, there is a convenient helper function:
\begin{lstlisting}[language=java]
Identity.lookup(getConfiguration(), "my-ego-name", new IdentityCallback() {
    @Override
    public void onEgo(Identity.Ego ego) {
        System.out.println("public key: " + ego.getPublicKey());
        });
    }
    @Override
    public void onError(String errorMessage) {
        System.err.println("lookup failed: " + errorMessage);
    }
});
\end{lstlisting}
Creating, renaming and deleting egos requires a handle to the identity service:
\begin{lstlisting}[language=java]
Identity identity = new Identity();
identity.connect(getConfiguration(), null);
\end{lstlisting}
The second parameter of \texttt{connect}, which is null in the above code, can
be a listener object of type \texttt{IdentityListCallback}, and is called whenever an identity
is added, deleted or changed.

After connecting, identities can be created like this:
\begin{lstlisting}[language=java]
identity.create(myEgoName, new IdentityContinuation() {
    @Override
    public void onError(String errorMessage) {
      System.out.println("create failed: " + error message);
    }
    @Override
    public void onDone() {
      System.out.println("create successful");
    }
});
\end{lstlisting}
Renaming and deleting egos is done by similar means.


\section{Using the GNU Name System}
Resolving and publishing name records in the network can be done with GNS, a secure
and decentralized alternative to the widely used Domain Name System.
Currently, GNUnet-Java only supports resolving names.

Names must be looked up in a zone, which is simply an ego. 
Run \texttt{gnunet-gns-import.sh} (distributed with the main GNUnet package) in order to
set up GNS.

Verify that this created the master-zone ego:
\begin{lstlisting}[language=bash]
\$ gnunet-identity -d # display all egos
\end{lstlisting}

Create an A-record in your your master-zone with:
\begin{lstlisting}[language=bash]
\$ gnunet-namestore -z master-zone -a -n myrecord -t A -V 1.2.3.4 -e never
\end{lstlisting}

The following snippet assumes that \texttt{master} is the ego with the name ``master-zone'',
as retrieved with the \texttt{Identity.lookup} function.
\begin{lstlisting}
final Gns gns = new Gns(getConfiguration());
// look up an A record
long typeId = GnsRecord.getIdFromString("A");
gns.lookup("alice.gnu", master.getPublicKey(), typeId, GNS_LOOKUP_OPTION_DEFAULT,
        null, new LookupResultProcessor() {
    @Override
    public void process(GnsRecord[] records) {
        for (GnsRecord record : records) {
            System.out.println("Record " +
                record.getRecordData().asRecordString());
        }
    }
});
\end{lstlisting}
A \texttt{GnsRecord} contains the record stored in binary form.
Calling \texttt{getRecordData} on the record instantiates an object
whose class is specific to the record type (e.g. \texttt{ARecordData}),
or an object of type \texttt{UnknownRecordData} if GNUnet-Java does not support
the given record type.

\exercise{Read more about GNS at \url{https://gnunet.org/gns-namestore-editing}.}
\exercise{Look at the Javadoc for \texttt{org.gnunet.gns.record}. What types of records are
currently supported, which are missing?}


\section{Other useful APIs}
Some other useful service APIs currently implemented are NSE (in {\tt
  org.gnunet.nse.NetworkSizeEstimation}), a service that gives an
estimation of the current size of the network, DHT (in {\tt
  org.gnunet.dht.DistributedHashTable}), a service that allows
  key/value pairs to be stored distributed across the network, and PEERINFO
  (in {\tt org.gnunet.peerinfo.PeerInfo}), a service for
retrieving information about other known peers.

The API to the TESTBED service, which allows to manage multiple peers
for testing and evaluating GNUnet components, is partially implemented.

Among the most important APIs still missing are FS (filesharing) and NAMESTORE (manages GNS zone entries).

\section{Writing your own client and service}

GNUnet is split up into many components, with every component running in its own
process.  In the previous sections you have used existing APIs to
interface with other services written in C.  GNUnet-Java also provides
the tools necessary to both directly interface with services yourself and
write completely new services.

\subsection{The service configuration}
Each service has its own configuration, specifying basic information like the
executable file of the service (used by ARM), the port or socket used to reach it,
as well as configuration options specific to the service.

\exercise{%
  Look at the configuration file for the example service {\tt config/greeting.conf}
  and try to understand the meaning of each option, by looking at the comments and the source code
  of the example service.
}

\subsection{Writing a client}
The {\tt org.gnunet.util.Client} class allows you to connect to a GNUnet
service and exchange messages with it:
\begin{lstlisting}[language=java]
Client myClient = new Client("myservice", configuration);
\end{lstlisting}
In the above example, the configuration values for the clients are
taken from the configuration section {\tt myservice}.

Keep in mind that all configuration files either have to be in one of the default locations, or
specified on the command line with the {\tt -c CFGFILE} option.

\subsection{Writing a service}

To implement your own service, inherit {\tt org.gnunet.util.Service} instead of
{\tt org.gnunet.util.Program}. The main difference between {\tt Program} and {\tt Service} is that the
{\tt Service} also creates a {\tt Server}, which waits for messages from clients.
You can register a Runabout to receive messages from clients with
{\tt getServer().setHandler(myRunabout)}, in similar fashion to handling messages from {\tt core}.

Example:
\begin{lstlisting}[language=java]
public class MyService {
    public static void main(String... argv) {
        new Service(
            "greeting", // name of the service, for choosing the right configuration
            RelativeTime.MINUTE, // timeout for disconnecting idle clients
            true, // disallow messages of unknown type
            argv) { // command line arguments parsed by Service

            @Override
            public void run() {
                getServer().setHandler(new Server.MessageRunabout() {
                    public void visit(MyMessage m) {
                        [...]
                        getSender().receiveDone();
                    }
                });
            }
        }.start(args);
    }
}
\end{lstlisting}

Always remember to call {\tt getSender().receiveDone()}, as the server does not receive further messages
until {\tt receiveDone} is called, in order to support flow control.
The object returned by {\tt getSender()} has a {\tt notifyTransmitReady} method, which can be used
to send messages to clients in a similar fashion to sending messages with CORE.

\exercise{Look at the example service implemented in {\tt org.gnunet.ext.GreetingService}.
  Run the service ({\tt gnunet-service-greeting}), and connect to it with the client program
  ({\tt gnunet-greeting}).
  Try to understand the code, and modify both the client and the service so that can send and accept
  another message type.}
\exercise{Write an API for a GNUnet service that has not been implemented yet in gnunet-java and contribute it back to the project.}

\end{document}