[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r32924 - gnunet-java/doc
From: |
gnunet |
Subject: |
[GNUnet-SVN] r32924 - gnunet-java/doc |
Date: |
Mon, 7 Apr 2014 16:21:56 +0200 |
Author: dold
Date: 2014-04-07 16:21:56 +0200 (Mon, 07 Apr 2014)
New Revision: 32924
Modified:
gnunet-java/doc/gnunet-java-tutorial.pdf
gnunet-java/doc/gnunet-java-tutorial.tex
Log:
tutorial
Modified: gnunet-java/doc/gnunet-java-tutorial.pdf
===================================================================
(Binary files differ)
Modified: gnunet-java/doc/gnunet-java-tutorial.tex
===================================================================
--- gnunet-java/doc/gnunet-java-tutorial.tex 2014-04-07 14:14:40 UTC (rev
32923)
+++ gnunet-java/doc/gnunet-java-tutorial.tex 2014-04-07 14:21:56 UTC (rev
32924)
@@ -24,7 +24,7 @@
{\\\$}{{\$ }}1
}
-\newcommand{\exercise}[1]{\noindent\begin{boxedminipage}{\textwidth}{\bf
Exercise:} #1 \end{boxedminipage}}
+\newcommand{\exercise}[1]{\vskip5pt\noindent\begin{boxedminipage}{\textwidth}{\bf
Exercise:} #1 \end{boxedminipage}}
\title{A Tutorial for GNUnet 0.10.x (Java version)}
@@ -34,7 +34,10 @@
\maketitle
-Although GNUnet is primarily developed in the C programming language, it is
also possible to write components in Java.
+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, and provides 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}
@@ -42,7 +45,7 @@
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
+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}.
@@ -70,11 +73,11 @@
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 \emph{assemble} task.
+Build the template project by running the \texttt{assemble} task:
\begin{lstlisting}[language=bash]
\$ ./gradlew assemble
\end{lstlisting}
-This will download all required dependencies. Gradle stores all dependencies
in an internal cache. Run
+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}
@@ -112,6 +115,10 @@
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}
@@ -133,8 +140,8 @@
\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.
+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,
@@ -152,11 +159,11 @@
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
+ \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
@@ -172,20 +179,17 @@
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 so that
-calls your \texttt{HelloGnuNet} class.}
+\exercise{Copy the wrapper \texttt{bin/my-ext} and modify it to
+call your \texttt{HelloGnuNet} class.}
\subsection{More Documentation}
-The documentation for \emph{gnunet-java} generated by Javadoc is available
+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.
-In this section we will use the statistics API of GNUnet-Java. The statistics
-service allows to store numbers under a subsystem and a name, which
-are still available to you and other components of your peer after
-your program exits.
-
\subsection{Connecting to the statistics service}
\begin{lstlisting}[language=java]
@@ -194,14 +198,14 @@
The Statistics constructor is called with the configuration,
provided by the method {\tt getConfiguration} of the {\tt Program}
-class. This establishes a connection to the
+class. This establishes a connection to the
statistics service. As with most API calls in GNUnet-Java, this
operation is asynchronous. This is one of the main reasons why one
-has to wrap teir program in the {\tt run} method of {\tt
+has to wrap their program in the {\tt run} method of {\tt
Program}: Once all method calls are done, the run method
returns, and GNUnet-Java keeps the system running until all work is done.
-Always remember that you always explicitly have to destroy your {\tt
+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.
@@ -209,9 +213,9 @@
\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. The \texttt{true}
-indicates that the value should be stored persistently.
-Persistent values are kept even if the statistics service restarts.
+set the value named ``\# bytes sent'' to the value 42. The last parameter
(\texttt{true})
+indicates that the value should be stored persistently (%
+persistent values are stored even if the statistics service restarts).
\begin{lstlisting}[language=java]
statistics.set("gnunet-java-hello", "# bytes sent", 42, true);
@@ -219,11 +223,11 @@
\subsection{Retrieving statistics}
-Retrieving a value is a little bit more complex. Because of the
+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}
+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''
@@ -237,31 +241,37 @@
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{Write a program that sets statistics values, and check the result
with the {\tt gnunet-statistics} command line tool.}
\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}
-\section{The core API}
+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.
-The core API allows sending encrypted messages to directly connected peers.
-
\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.
+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.
Additionaly, you have to register your new message type with
-GNUnet-Java, giving it a unique id. Here is an example:
+GNUnet-Java, giving it a unique message type number. Here is an example:
\begin{lstlisting}[language=java]
@UnionCase(4242)
@@ -281,7 +291,7 @@
Every time you add a new type of GNUnet message, you have to run the command
\lstset{language=bash}
\begin{lstlisting}
-\$ gradle msgtypes
+\$ ./gradle msgtypes
\end{lstlisting}
This generates the file {\tt
src/main/java/org/gnunet/construct/MsgMap.txt}, which allows the system to
@@ -336,7 +346,7 @@
After specifing your message handler, the {\tt init} method has to be
called with a callback object. This starts the handshake with the
-core service, once done the callback object's {\tt onInit} method will
+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}
@@ -346,11 +356,12 @@
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 the core is ready to transmit your
-message. Call the {\tt send} method in the {\tt MessageSink} in order
-to finally transmit it.
+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() {
@@ -367,9 +378,134 @@
\exercise{Write an echo program for core: Send a message to the local peer and
receive it!}
-\section{The Distributed Hash Table (DHT) API}
+\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.
+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 estavlishes 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");
+ }
+});
+Renaming and deleting egos is done by similar means.
+\end{lstlisting}
+
+
+\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 a 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 snipped 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
@@ -379,11 +515,14 @@
(in {\tt org.gnunet.peerinfo.PeerInfo}), a service for
retrieving information about other known peers.
-Note that some GNUnet services do not yet have Java bindings.
+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, every component runs in its own
+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
@@ -414,7 +553,7 @@
\subsection{Writing a service}
-To implement your own service, just inherit {\tt org.gnunet.util.Service}
instead of
+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
@@ -439,7 +578,7 @@
}
});
}
- }.start();
+ }.start(args);
}
}
\end{lstlisting}
@@ -447,7 +586,7 @@
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 writing to CORE.
+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
@@ -456,14 +595,4 @@
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.}
-\section{MESH}
-TODO
-
-
-\section{The state of GNUnet-Java}
-
-The GNUnet-Java project is still somewhat unstable and under development,
expect
-changes that break your stuff! Please report any bugs or feature
-requests at \url{https://gnunet.org/bugs/}.
-
\end{document}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r32924 - gnunet-java/doc,
gnunet <=