Merge branch 'master' of git+ssh://gnunet.org/gnunet
[oweals/gnunet.git] / doc / gnunet-c-tutorial.tex
index 7c0680d73b9882e29cfdcb84f6f281310019d6fb..55b0ee3102fc1e5f25cd4215fc65b7d89a1b8a59 100644 (file)
@@ -35,9 +35,9 @@ Christian Grothoff $\qquad$ Bart Polot $\qquad$ Matthias Wachs
 
 \today
 \end{center}
-This tutorials explains how to install GNUnet on a GNU/Linux system and gives an introduction how
+This tutorials explains how to install GNUnet on a GNU/Linux system and gives an introduction on how
 GNUnet can be used to develop a Peer-to-Peer application. Detailed installation instructions for
-various operating systems and a detailed list of all dependencies can found on our website at
+various operating systems and a detailed list of all dependencies can be found on our website at
 \url{https://gnunet.org/installation}.
 
 \textbf{Please read this tutorial carefully since every single step is
@@ -76,7 +76,7 @@ $ gpg --verify gnunet-0.10.x.tar.gz.sig gnunet-0.10.x.tar.gz
 After successfully verifying the integrity you can extract the tarball using
 \begin{lstlisting}
 $ tar xvzf gnunet-0.10.x.tar.gz
-$ mv gnunet-0.10.x gnunet # we will use the directory "gnunet" in the remainder of this document
+$ mv gnunet-0.10.x gnunet              # we will use the directory "gnunet" in the remainder of this document
 $ cd gnunet
 \end{lstlisting}
 
@@ -153,7 +153,7 @@ $ make install
 
 After installing GNUnet you have to add your GNUnet installation to your path
 environmental variable. In addition you have to create the \lstinline|.gnunet|
-directory in your home directory where GNUnet stores it's data and an empty
+directory in your home directory where GNUnet stores its data and an empty
 GNUnet configuration file:
 
 \lstset{language=bash}
@@ -181,7 +181,7 @@ $
 \end{lstlisting}
 check your {\tt PATH} variable to ensure GNUnet's {\tt bin} directory is included.
 
-GNUnet provides tests for all of it's subcomponents. Run
+GNUnet provides tests for all of its subcomponents. Run
 \begin{lstlisting}
 $ make check
 \end{lstlisting}
@@ -247,7 +247,7 @@ the programmer.
 \section{First Steps with GNUnet}
 
 \subsection{Configure your peer}
-First of all we need to configure your peer. Each peer is started with a configuration containing settings for GNUnet itself and it's services. This configuration is based on the default configuration shipped with GNUnet and can be modified. The default configuration is located in the {\tt \$PREFIX/share/gnunet/config.d} directory. When starting a peer, you can specify a customized configuration using the the {\tt$-c$} command line switch when starting the ARM service and all other services. When using a modified configuration the default values are loaded and only values specified in the configuration file will replace the default values.
+First of all we need to configure your peer. Each peer is started with a configuration containing settings for GNUnet itself and its services. This configuration is based on the default configuration shipped with GNUnet and can be modified. The default configuration is located in the {\tt \$PREFIX/share/gnunet/config.d} directory. When starting a peer, you can specify a customized configuration using the the {\tt$-c$} command line switch when starting the ARM service and all other services. When using a modified configuration the default values are loaded and only values specified in the configuration file will replace the default values.
 
 Since we want to start additional peers later, we need
 some modifications from the default configuration. We need to create a separate service home and a file containing our modifications for this peer:
@@ -262,55 +262,59 @@ network since this could lead to confusing output. This modifications
 will replace the default settings:
 \begin{lstlisting}
 [PATHS]
-GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data
+GNUNET_HOME = ~/gnunet1/               # Use this directory to store GNUnet data
 [hostlist]
-SERVERS = # prevent bootstrapping
+SERVERS =                              # prevent bootstrapping
 \end{lstlisting}
 
 \subsection{Start a peer}
 Each GNUnet instance (called peer) has an identity (\textit{peer ID}) based on a
 cryptographic public private key pair. The peer ID is the printable hash of the
-public key. So before starting the peer, you may want to just generate the peer's private
-key using the command
+public key.
+
+GNUnet services are controlled by a master service the so called \textit{Automatic Restart Manager} (ARM).
+ARM starts, stops and even restarts services automatically or on demand when a client connects.
+You interact with the ARM service using the \lstinline|gnunet-arm| tool.
+GNUnet can then be started with \lstinline|gnunet-arm -s| and stopped with
+\lstinline|gnunet-arm -e|.  An additional service not automatically started
+can be started using \lstinline|gnunet-arm -i <service name>| and stopped
+using \lstinline|gnunet-arm -k <servicename>|.
+
+Once you have started your peer, you can use many other GNUnet commands
+to interact with it.  For example, you can run:
 \lstset{language=bash}
 \begin{lstlisting}
-$ gnunet-peerinfo -c ~/peer1.conf -s
+$ gnunet-peerinfo -s
 \end{lstlisting}
+to obtain the public key of your peer.
 You should see an output containing the peer ID similar to:
 \lstset{language=bash}
 \begin{lstlisting}
 I am peer `0PA02UVRKQTS2C .. JL5Q78F6H0B1ACPV1CJI59MEQUMQCC5G'.
 \end{lstlisting}
 
-GNUnet services are controlled by a master service the so called \textit{Automatic Restart Manager} (ARM).
-ARM starts, stops and even restarts services automatically or on demand when a client connects.
-You interact with the ARM service using the \lstinline|gnunet-arm| tool.
-GNUnet can then be started with \lstinline|gnunet-arm -s| and stopped with
-\lstinline|gnunet-arm -e|.  An additional service not automatically started
-can be started using \lstinline|gnunet-arm -i <service name>| and stopped
-using \lstinline|gnunet-arm -k <servicename>|.
 
 \subsection{Monitor a peer}
 In this section, we will monitor the behaviour of our peer's DHT service with respect to a
 specific key. First we will start GNUnet and then start the DHT service and use the DHT monitor tool
 to monitor the PUT and GET commands we issue ussing the \lstinline|gnunet-dht-put| and
-\lstinline|gnunet-dht-get| command. Using the ``monitor'' line given below, you can observe the behavior of
+\lstinline|gnunet-dht-get| commands. Using the ``monitor'' line given below, you can observe the behavior of
 your own peer's DHT with respect to the specified KEY:
 
 \lstset{language=bash}
 \begin{lstlisting}
-$ gnunet-arm -c ~/peer1.conf -s # start gnunet with all default services
-$ gnunet-arm -c ~/peer1.conf -i dht # start DHT service
+$ gnunet-arm -c ~/peer1.conf -s                        # start gnunet with all default services
+$ gnunet-arm -c ~/peer1.conf -i dht            # start DHT service
 $ cd ~/gnunet/src/dht;
 $ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY
 \end{lstlisting}
 Now open a separate terminal and change again to the \lstinline|gnunet/src/dht| directory:
 \begin{lstlisting}
 $ cd ~/gnunet/src/dht
-$ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE # put VALUE under KEY in the DHT
-$ ./gnunet/src/dht/gnunet-dht-get -c ~/peer1.conf -k KEY # get key KEY from the DHT
-$ gnunet-statistics -c ~/peer1.conf # print statistics about current GNUnet state
-$ gnunet-statistics -c ~/peer1.conf -s dht # print statistics about DHT service
+$ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE             # put VALUE under KEY in the DHT
+$ ./gnunet/src/dht/gnunet-dht-get -c ~/peer1.conf -k KEY       # get key KEY from the DHT
+$ gnunet-statistics -c ~/peer1.conf            # print statistics about current GNUnet state
+$ gnunet-statistics -c ~/peer1.conf -s dht     # print statistics about DHT service
 \end{lstlisting}
 % $
 \subsection{Starting Two Peers by Hand}
@@ -386,9 +390,9 @@ OPTIONS = -p
 Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with
 ``\texttt{http://localhost:8080/}''.  Restart both peers using:
 \begin{lstlisting}
-$ gnunet-arm -c peer1.conf -e # stop first peer
-$ gnunet-arm -c peer1.conf -s # start first peer
-$ gnunet-arm -c peer2.conf -s # start second peer
+$ gnunet-arm -c peer1.conf -e          # stop first peer
+$ gnunet-arm -c peer1.conf -s          # start first peer
+$ gnunet-arm -c peer2.conf -s          # start second peer
 \end{lstlisting}
 
 Note that if you start your peers without changing these settings, they
@@ -402,7 +406,7 @@ by you.
 If you want to use the \texttt{peerinfo} tool to connect your peers, you should:
 \begin{itemize}
 \itemsep0em
- \item{Remove {\tt hostlist} from {\tt DEFAULTSERVICES} (to not connect to the global GNUnet)}
+ \item{Set {\tt FORCESTART = NO} in section {\tt hostlist} (to not connect to the global GNUnet)}
  \item{Start both peers running {\tt gnunet-arm -c peer1.conf -s} and {\tt gnunet-arm -c peer2.conf -s}}
  \item{Get \texttt{HELLO} message of the first peer running {\tt gnunet-peerinfo -c peer1.conf -g}}
  \item{Give the output to the second peer by running {\tt gnunet-peerinfo -c peer2.conf -p '<output>'}}
@@ -412,7 +416,7 @@ Check that they are connected using {\tt gnunet-core -c peer1.conf}, which shoul
 peer identity:
 \begin{lstlisting}
 $ gnunet-core -c peer1.conf
-Peer `9TVUCS8P5A7ILLBGO6JSTSSN2B44H3D2MUIFJMLKAITC0I22UVFBFP1H8NRK2IA35VKAK16LLO0MFS7TAQ9M1KNBJ4NGCHP3JPVULDG'
+Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG'
 \end{lstlisting}
 
 \subsection{Starting Peers Using the Testbed Service}
@@ -440,9 +444,12 @@ configuration file.  Various available options and details about them can be
 found in the testbed default configuration file \texttt{src/testbed/testbed.conf}.
 
 With the testbed API, a sample test case can be structured as follows:
+% <lynX> Is there a way to pick a more readable font for this include?
 \lstinputlisting[language=C]{testbed_test.c}
 The source code for the above listing can be found at
-\url{https://gnunet.org/svn/gnunet/doc/testbed_test.c}.  After installing GNUnet, the above source code can be compiled as:
+\url{https://gnunet.org/svn/gnunet/doc/testbed_test.c}
+or in the doc folder of your repository check-out.
+After installing GNUnet, the above source code can be compiled as:
 \lstset{language=bash}
 \begin{lstlisting}
 $ export CPPFLAGS="-I/path/to/gnunet/headers"
@@ -978,7 +985,6 @@ in the {\tt gnunet\_server\_lib.h} header.
 \exercise{Change the service respond to the request from your
 client.  Make sure you handle malformed messages in both directions.}
 
-
 \section{Interacting directly with other Peers using the CORE Service}
 
 One of the most important services in GNUnet is the \texttt{CORE} service
@@ -1113,6 +1119,128 @@ disconnects (void *cls,
 
 \exercise{Fix your service to handle peer disconnects.}
 
+\section{Storing peer-specific data using the PEERSTORE service}
+
+GNUnet's PEERSTORE service offers a persistorage for arbitrary peer-specific data.
+Other GNUnet services can use the PEERSTORE to store, retrieve and monitor data records.
+Each data record stored with PEERSTORE contains the following fields:
+
+\begin{itemize}
+\itemsep0em
+  \item subsystem: Name of the subsystem responsible for the record.
+  \item peerid: Identity of the peer this record is related to.
+  \item key: a key string identifying the record.
+  \item value: binary record value.
+  \item expiry: record expiry date.
+\end{itemize}
+
+The first step is to start a connection to the PEERSTORE service:
+\begin{lstlisting}
+#include "gnunet_peerstore_service.h"
+
+peerstore_handle = GNUNET_PEERSTORE_connect (cfg);
+\end{lstlisting}
+The service handle \lstinline|peerstore_handle| will be needed for all subsequent
+PEERSTORE operations.
+
+\subsection{Storing records}
+
+To store a new record, use the following function:
+\begin{lstlisting}
+struct GNUNET_PEERSTORE_StoreContext *
+GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
+                        const char *sub_system,
+                        const struct GNUNET_PeerIdentity *peer,
+                        const char *key,
+                        const void *value,
+                        size_t size,
+                        struct GNUNET_TIME_Absolute expiry,
+                        enum GNUNET_PEERSTORE_StoreOption options,
+                        GNUNET_PEERSTORE_Continuation cont,
+                        void *cont_cls);
+\end{lstlisting}
+
+The \lstinline|options| parameter can either be \lstinline|GNUNET_PEERSTORE_STOREOPTION_MULTIPLE|
+which means that multiple values can be stored under the same key combination (subsystem, peerid, key),
+or \lstinline|GNUNET_PEERSTORE_STOREOPTION_REPLACE| which means that PEERSTORE will replace any
+existing values under the given key combination (subsystem, peerid, key) with the new given value.
+
+The continuation function \lstinline|cont| will be called after the store request is successfully
+sent to the PEERSTORE service. This does not guarantee that the record is successfully stored, only
+that it was received by the service.
+
+The \lstinline|GNUNET_PEERSTORE_store| function returns a handle to the store operation. This handle
+can be used to cancel the store operation only before the continuation function is called:
+\begin{lstlisting}
+void
+GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc);
+\end{lstlisting}
+
+\subsection{Retrieving records}
+
+To retrieve stored records, use the following function:
+\begin{lstlisting}
+struct GNUNET_PEERSTORE_IterateContext *
+GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h,
+                          const char *sub_system,
+                          const struct GNUNET_PeerIdentity *peer,
+                          const char *key,
+                          struct GNUNET_TIME_Relative timeout,
+                          GNUNET_PEERSTORE_Processor callback,
+                          void *callback_cls);
+\end{lstlisting}
+The values of \lstinline|peer| and \lstinline|key| can be \lstinline|NULL|. This allows the
+iteration over values stored under any of the following key combinations:
+\begin{itemize}
+\itemsep0em
+  \item (subsystem)
+  \item (subsystem, peerid)
+  \item (subsystem, key)
+  \item (subsystem, peerid, key)
+\end{itemize}
+
+The \lstinline|callback| function will be called once with each retrieved record and once
+more with a \lstinline|NULL| record to signal the end of results.
+
+The \lstinline|GNUNET_PEERSTORE_iterate| function returns a handle to the iterate operation. This
+handle can be used to cancel the iterate operation only before the callback function is called with
+a \lstinline|NULL| record.
+
+\subsection{Monitoring records}
+
+PEERSTORE offers the functionality of monitoring for new records stored under a specific key
+combination (subsystem, peerid, key). To start the monitoring, use the following function:
+\begin{lstlisting}
+struct GNUNET_PEERSTORE_WatchContext *
+GNUNET_PEERSTORE_watch (struct GNUNET_PEERSTORE_Handle *h,
+                        const char *sub_system,
+                        const struct GNUNET_PeerIdentity *peer,
+                        const char *key,
+                        GNUNET_PEERSTORE_Processor callback,
+                        void *callback_cls);
+\end{lstlisting}
+
+Whenever a new record is stored under the given key combination, the \lstinline|callback| function
+will be called with this new record. This will continue until the connection to the PEERSTORE service
+is broken or the watch operation is canceled:
+\begin{lstlisting}
+void
+GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext *wc);
+\end{lstlisting}
+
+\subsection{Disconnecting from PEERSTORE}
+
+When the connection to the PEERSTORE service is no longer needed, disconnect using the following
+function:
+\begin{lstlisting}
+void
+GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first);
+\end{lstlisting}
+
+If the \lstinline|sync_first| flag is set to \lstinline|GNUNET_YES|, the API will delay the
+disconnection until all store requests are received by the PEERSTORE service. Otherwise,
+it will disconnect immediately.
+
 \section{Using the DHT}
 The DHT allows to store data so other peers in the P2P network can
 access it and retrieve data stored by any peers in the network.