aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-03-07 23:44:40 +0100
committerChristian Grothoff <christian@grothoff.org>2017-03-07 23:44:40 +0100
commitf64bd0cae02eb4a1e8e3dfdd911260f7185ffd37 (patch)
tree2125d3c01015d68123b3639a1e68fa39c98ef224 /doc
parent8a32cac23d7289cfb7d1d356603a523cf6effd13 (diff)
update tutorial
Diffstat (limited to 'doc')
-rw-r--r--doc/gnunet-c-tutorial.pdfbin262596 -> 293947 bytes
-rw-r--r--doc/gnunet-c-tutorial.tex285
-rw-r--r--doc/testbed_test.c112
3 files changed, 124 insertions, 273 deletions
diff --git a/doc/gnunet-c-tutorial.pdf b/doc/gnunet-c-tutorial.pdf
index f0dfe58b3f..115ed77028 100644
--- a/doc/gnunet-c-tutorial.pdf
+++ b/doc/gnunet-c-tutorial.pdf
Binary files differ
diff --git a/doc/gnunet-c-tutorial.tex b/doc/gnunet-c-tutorial.tex
index 069c1838fe..2b4a0d8e13 100644
--- a/doc/gnunet-c-tutorial.tex
+++ b/doc/gnunet-c-tutorial.tex
@@ -1,12 +1,13 @@
\documentclass[10pt]{article}
\usepackage[ansinew]{inputenc}
\usepackage{makeidx,amsmath,amssymb,exscale,multicol,epsfig,graphics,verbatim,ulem}
-\usepackage{epsfig,geometry,url,listings, subcaption}
+\usepackage{epsfig,geometry,url,listings,subcaption}
\usepackage{boxedminipage}
\usepackage[T1]{fontenc}%required
\usepackage{textcomp}
\geometry{headsep=3ex,hscale=0.9}
\usepackage{hyperref}
+\usepackage{color}
\hypersetup{pdftitle={GNUnet C Tutorial},
pdfsubject={GNUnet},
pdfauthor={Christian Grothoff <christian@grothoff.org>},
@@ -28,6 +29,26 @@ literate={*}{{\char42}}1
\begin{document}
+\lstset{ %
+language=C, % choose the language of the code
+basicstyle=\footnotesize, % the size of the fonts that are used for the code
+numbers=left, % where to put the line-numbers
+numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers
+stepnumber=1, % the step between two line-numbers. If it is 1 each line will be numbered
+numbersep=5pt, % how far the line-numbers are from the code
+backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
+showspaces=false, % show spaces adding particular underscores
+showstringspaces=false, % underline spaces within strings
+showtabs=false, % show tabs within strings adding particular underscores
+frame=single, % adds a frame around the code
+tabsize=2, % sets default tabsize to 2 spaces
+captionpos=b, % sets the caption-position to bottom
+breaklines=true, % sets automatic line breaking
+breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
+escapeinside={\%*}{*)} % if you want to add a comment within your code
+}
+
+
\begin{center}
\large {A Tutorial for GNUnet 0.10.x (C version)}
@@ -68,20 +89,25 @@ You should also download the signature file and verify the integrity of the tarb
\url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz.sig}
\end{center}
To verify the signature you should first import the GPG key used to sign the tarball
+\lstset{language=bash}
\begin{lstlisting}
$ gpg --keyserver keys.gnupg.net --recv-keys 48426C7E
\end{lstlisting}
And use this key to verify the tarball's signature
+\lstset{language=bash}
\begin{lstlisting}
$ gpg --verify gnunet-0.10.x.tar.gz.sig gnunet-0.10.x.tar.gz
\end{lstlisting}
After successfully verifying the integrity you can extract the tarball using
+\lstset{language=bash}
\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
$ cd gnunet
\end{lstlisting}
+However, please note that stable versions can be very outdated, as a developer
+you are strongly encouraged to use the version from \url{https://gnunet.org/git/}.
\subsection{Installing Build Tool Chain and Dependencies}
@@ -116,15 +142,15 @@ The remainder of this tutorial assumes that you have Git Master checked out.
\subsection{Compiling and Installing GNUnet}
First, you need to install at least {\tt libgnupgerror} version
-1.12\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.12.tar.bz2}}
+1.27\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.27.tar.bz2}}
and {\tt libgcrypt} version
-1.6\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.6.0.tar.bz2}}.
+1.7.6\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.6.tar.bz2}}.
\lstset{language=bash}
\begin{lstlisting}
-$ wget ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.12.tar.bz2
-$ tar xf libgpg-error-1.12.tar.bz2
-$ cd libgpg-error-1.12
+$ wget ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.27.tar.bz2
+$ tar xf libgpg-error-1.27.tar.bz2
+$ cd libgpg-error-1.27
$ ./configure
$ sudo make install
$ cd ..
@@ -132,9 +158,9 @@ $ cd ..
\lstset{language=bash}
\begin{lstlisting}
-$ wget ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.6.0.tar.bz2
-$ tar xf libgcrypt-1.6.0.tar.bz2
-$ cd libgcrypt-1.6.0
+$ wget ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.6.tar.bz2
+$ tar xf libgcrypt-1.7.6.tar.bz2
+$ cd libgcrypt-1.7.6
$ ./configure
$ sudo make install
$ cd ..
@@ -176,12 +202,14 @@ $ touch ~/.config/gnunet.conf
You should check your installation to ensure that installing GNUnet
was successful up to this point. You should be able to access GNUnet's
binaries and run GNUnet's self check.
+\lstset{language=bash}
\begin{lstlisting}
$ which gnunet-arm
\end{lstlisting}
should return \lstinline|$PREFIX/bin/gnunet-arm|. It should be
located in your GNUnet installation and the output should not be
empty. If you see an output like:
+\lstset{language=bash}
\begin{lstlisting}
$ which gnunet-arm
$
@@ -189,29 +217,20 @@ $
check your {\tt PATH} variable to ensure GNUnet's {\tt bin} directory is included.
GNUnet provides tests for all of its subcomponents. Run
+\lstset{language=bash}
\begin{lstlisting}
$ make check
\end{lstlisting}
to execute tests for all components. {\tt make check} traverses all subdirectories in {\tt src}.
For every subdirectory you should get a message like this:
-\begin{lstlisting}
+\begin{verbatim}
make[2]: Entering directory `/home/$USER/gnunet/contrib'
PASS: test_gnunet_prefix
=============
1 test passed
=============
-\end{lstlisting}
-
-If you see a message like this:
-
-\begin{lstlisting}
-Mar 12 16:57:56-642482 resolver-api-19449 ERROR Must specify `HOSTNAME' for `resolver' in configuration!
-Mar 12 16:57:56-642573 test_program-19449 ERROR Assertion failed at resolver_api.c:204.
-/bin/bash: line 5: 19449 Aborted (core dumped) ${dir}$tst
-FAIL: test_program
-\end{lstlisting}
-double check the steps performed in ~\ref{sub:install}
+\end{verbatim}
\section{Background: GNUnet Architecture}
@@ -262,6 +281,7 @@ First of all we need to configure your peer. Each peer is started with a configu
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:
+\lstset{language=bash}
\begin{lstlisting}
$ mkdir ~/gnunet1/
$ touch peer1.conf
@@ -271,12 +291,12 @@ Now add the following lines to peer1.conf to use this directory. For
simplified usage we want to prevent the peer to connect to the GNUnet
network since this could lead to confusing output. This modifications
will replace the default settings:
-\begin{lstlisting}
+\begin{verbatim}
[PATHS]
GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data
[hostlist]
SERVERS = # prevent bootstrapping
-\end{lstlisting}
+\end{verbatim}
\subsection{Start a peer}
@@ -322,6 +342,7 @@ $ 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:
+\lstset{language=bash}
\begin{lstlisting}
$ cd ~/gnunet/src/dht
$ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE # put VALUE under KEY in the DHT
@@ -348,6 +369,7 @@ To configure the second peer, use the files {\tt
configuration file:
%
\lstset{language=bash}
+\lstset{language=bash}
\begin{lstlisting}
$ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf
\end{lstlisting}
@@ -399,10 +421,10 @@ If you want the two peers to connect, you have multiple options:
To setup peer 1 as bootstrapping server change the configuration of
the first one to be a hostlist server by adding the following lines to
\texttt{peer1.conf} to enable bootstrapping server:
- \begin{lstlisting}
+ \begin{verbatim}
[hostlist]
OPTIONS = -p
-\end{lstlisting}
+\end{verbatim}
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:
@@ -432,6 +454,7 @@ If you want to use the \texttt{peerinfo} tool to connect your peers, you should:
Check that they are connected using {\tt gnunet-core -c peer1.conf}, which should give you the other peer's
peer identity:
+\lstset{language=bash}
\begin{lstlisting}
$ gnunet-core -c peer1.conf
Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG'
@@ -463,7 +486,8 @@ 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}
+\lstset{language=C}
+\lstinputlisting{testbed_test.c}
The source code for the above listing can be found at
\url{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c}
or in the {\tt doc/} folder of your repository check-out.
@@ -593,7 +617,7 @@ command-line options, setup the scheduler and then invoke the {\tt
to the parsed configuration (and the configuration file name that was
used, which is typically not needed):
-\lstset{language=c}
+\lstset{language=C}
\begin{lstlisting}
#include <gnunet/platform.h>
#include <gnunet/gnunet_util_lib.h>
@@ -606,7 +630,7 @@ run (void *cls,
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
- /* main code here */
+ // main code here
ret = 0;
}
@@ -632,6 +656,7 @@ expanding the {\tt options} array. For example, the following would
add a string-option and a binary flag (defaulting to {\tt NULL} and
{\tt GNUNET\_NO} respectively):
+\lstset{language=C}
\begin{lstlisting}
static char *string_option;
static int a_flag;
@@ -696,7 +721,7 @@ file).
Before a client library can implement the application-specific protocol
with the service, a connection must be created:
-\lstset{language=c}
+\lstset{language=C}
\begin{lstlisting}
struct GNUNET_MQ_MessageHandlers handlers[] = {
// ...
@@ -723,36 +748,26 @@ In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_Message
in big endian format. This header defines the size and the type of the
message, the payload follows after this header.
-\lstset{language=c}
+\lstset{language=C}
\begin{lstlisting}
struct GNUNET_MessageHeader
{
-
- /**
- * The length of the struct (in bytes, including the length field itself),
- * in big-endian format.
- */
uint16_t size GNUNET_PACKED;
-
- /**
- * The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
- */
uint16_t type GNUNET_PACKED;
-
};
\end{lstlisting}
Existing message types are defined in {\tt gnunet\_protocols.h}\\
A common way to create a message is with an envelope:
-\lstset{language=c}
+\lstset{language=C}
\begin{lstlisting}
struct GNUNET_MQ_Envelope *env;
struct GNUNET_MessageHeader *msg;
env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE);
memcpy (&msg[1], &payload, payload_size);
-/* Send message via message queue 'mq': */
+// Send message via message queue 'mq'
GNUNET_mq_send (mq, env);
\end{lstlisting}
@@ -785,38 +800,19 @@ and {\tt handle\_} are mandatory.
\lstset{language=c}
\begin{lstlisting}
-/**
- * Function called with MyMessage messages from service.
- *
- * @param cls closure
- * @param msg message received
- */
static void
handle_fix (void *cls, const struct MyMessage *msg)
{
// process 'msg'
}
-/**
- * Function called with MyVarMessage messages from service.
- *
- * @param cls closure
- * @param msg message received
- * @return #GNUNET_OK if @a msg is well-formed
- */
static int
check_var (void *cls, const struct MyVarMessage *msg)
{
// check 'msg' is well-formed
- return GNUNET_OK; /* suppose yes */
+ return GNUNET_OK;
}
-/**
- * Function called with MyMessage messages from service.
- *
- * @param cls closure
- * @param msg message received
- */
static void
handle_var (void *cls, const struct MyVarMessage *msg)
{
@@ -900,13 +896,6 @@ like this:
\lstset{language=c}
\begin{lstlisting}
-/**
- * Launch service.
- *
- * @param cls closure
- * @param c configuration to use
- * @param service the initialized service
- */
static void
run (void *cls,
const struct GNUNET_CONFIGURATION_Handle *c,
@@ -914,14 +903,6 @@ run (void *cls,
{
}
-/**
- * Callback called when a client connects to the service.
- *
- * @param cls closure for the service
- * @param c the new client that connected to the service
- * @param mq the message queue used to send messages to the client
- * @return @a c
- */
static void *
client_connect_cb (void *cls,
struct GNUNET_SERVICE_Client *c,
@@ -930,13 +911,6 @@ client_connect_cb (void *cls,
return c;
}
-/**
- * Callback called when a client disconnected from the service
- *
- * @param cls closure for the service
- * @param c the client that disconnected
- * @param internal_cls should be equal to @a c
- */
static void
client_disconnect_cb (void *cls,
struct GNUNET_SERVICE_Client *c,
@@ -988,11 +962,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_CORE_StartupCallback init,
GNUNET_CORE_ConnectEventHandler connects,
GNUNET_CORE_DisconnectEventHandler disconnects,
- GNUNET_CORE_MessageCallback inbound_notify,
- int inbound_hdr_only,
- GNUNET_CORE_MessageCallback outbound_notify,
- int outbound_hdr_only,
- const struct GNUNET_CORE_MessageHandler *handlers);
+ const struct GNUNET_MQ_MessageHandler *handlers);
\end{lstlisting}
\subsection{New P2P connections}
@@ -1003,45 +973,33 @@ which communicates the identity of the new peer to the service:
\lstset{language=C}
\begin{lstlisting}
-void
+void *
connects (void *cls,
- const struct GNUNET_PeerIdentity * peer)
+ const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_MQ_Handle *mq)
{
- /* Save identity for later use */
- /* Optional: start sending messages to peer */
+ return mq;
}
\end{lstlisting}
+Note that whatever you return from {\tt connects} is given as the
+{\it cls} argument to the message handlers for messages from
+the respective peer.
+
\exercise{Create a service that connects to the \texttt{CORE}. Then
start (and connect) two peers and print a message once your connect
callback is invoked.}
\subsection{Receiving P2P Messages}
-To receive messages from \texttt{CORE}, services register a set of handlers
-(parameter {\tt *handlers} in the \lstinline|GNUNET_CORE_connect| call that are called by \texttt{CORE}
-when a suitable message arrives.
+To receive messages from \texttt{CORE}, you pass the desired
+{\em handlers} to the {\tt GNUNET\_CORE\_connect()} function,
+just as we showed for services.
-\lstset{language=c}
-\begin{lstlisting}
-static int
-callback_function_for_type_one(void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message)
-{
- /* Do stuff */
- return GNUNET_OK; /* or GNUNET_SYSERR to close the connection */
-}
-
-/**
- * Functions to handle messages from core
- */
-static struct GNUNET_CORE_MessageHandler core_handlers[] = {
- {&callback_function_for_type_one, GNUNET_MESSAGE_TYPE_MYSERVICE_TYPE_ONE, 0},
- /* more handlers*/
- {NULL, 0, 0}
-};
-\end{lstlisting}
+It is your responsibility to process messages fast enough or
+to implement flow control. If an application does not process
+CORE messages fast enough, CORE will randomly drop messages
+to not keep a very long queue in memory.
\exercise{Start one peer with a new service that has a message
handler and start a second peer that only has your ``old'' service
@@ -1051,29 +1009,13 @@ the two peers are connected? Why?}
\subsection{Sending P2P Messages}
-In response to events (connect, disconnect, inbound messages,
-timing, etc.) services can then use this API to transmit messages:
+You can transmit messages to other peers using the {\it mq} you were
+given during the {\tt connect} callback. Note that the {\it mq}
+automatically is released upon {\tt disconnect} and that you must
+not use it afterwards.
-\lstset{language=C}
-\begin{lstlisting}
-typedef size_t
-(*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls,
- size_t size,
- void *buf)
-{
- /* Fill "*buf" with up to "size" bytes, must start with GNUNET_MessageHeader */
- return n; /* Total size of the message put in "*buf" */
-}
-
-struct GNUNET_CORE_TransmitHandle *
-GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
- int cork, uint32_t priority,
- struct GNUNET_TIME_Relative maxdelay,
- const struct GNUNET_PeerIdentity *target,
- size_t notify_size,
- GNUNET_CONNECTION_TransmitReadyNotify notify,
- void *notify_cls);
-\end{lstlisting}
+It is your responsibility to not over-fill the message queue, GNUnet
+will send the messages roughly in the order given as soon as possible.
\exercise{Write a service that upon connect sends messages as
fast as possible to the other peer (the other peer should run a
@@ -1258,22 +1200,21 @@ and other unfavorable events, just make several PUT requests!
\lstset{language=C}
\begin{lstlisting}
-void
+static void
message_sent_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- /* Request has left local node */
+ // Request has left local node
}
struct GNUNET_DHT_PutHandle *
GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
const struct GNUNET_HashCode *key,
uint32_t desired_replication_level,
- enum GNUNET_DHT_RouteOption options, /* Route options, see next call */
+ enum GNUNET_DHT_RouteOption options,
enum GNUNET_BLOCK_Type type, size_t size, const void *data,
- struct GNUNET_TIME_Absolute exp, /* When does the data expire? */
- struct GNUNET_TIME_Relative timeout, /* How long to try to send the request */
- GNUNET_DHT_PutContinuation cont,
- void *cont_cls)
+ struct GNUNET_TIME_Absolute exp,
+ struct GNUNET_TIME_Relative timeout,
+ GNUNET_DHT_PutContinuation cont, void *cont_cls)
\end{lstlisting}
\exercise{Store a value in the DHT periodically to make sure it is available
@@ -1305,9 +1246,8 @@ get_result_iterator (void *cls, struct GNUNET_TIME_Absolute expiration,
unsigned int put_path_length,
enum GNUNET_BLOCK_Type type, size_t size, const void *data)
{
- /* Do stuff with the data and/or route */
- /* Optionally: */
- GNUNET_DHT_get_stop (get_handle);
+ // Optionally:
+ GNUNET_DHT_get_stop (get_handle);
}
get_handle =
@@ -1315,9 +1255,9 @@ get_handle =
block_type,
&key,
replication,
- GNUNET_DHT_RO_NONE, /* Route options */
- NULL, /* xquery: not used here */
- 0, /* xquery size */
+ GNUNET_DHT_RO_NONE,
+ NULL,
+ 0,
&get_result_iterator,
cls)
\end{lstlisting}
@@ -1356,13 +1296,13 @@ static enum GNUNET_BLOCK_EvaluationResult
block_plugin_SERVICE_evaluate (void *cls,
enum GNUNET_BLOCK_Type type,
struct GNUNET_BlockGroup *bg,
- const GNUNET_HashCode *query,
- const void *xquery,
- size_t xquery_size,
- const void *reply_block,
- size_t reply_block_size)
+ const GNUNET_HashCode *query,
+ const void *xquery,
+ size_t xquery_size,
+ const void *reply_block,
+ size_t reply_block_size)
{
- /* Verify type, block and bg */
+ // Verify type, block and bg
}
\end{lstlisting}
@@ -1385,10 +1325,10 @@ just fine with such blocks).
\begin{lstlisting}
static int
block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type,
- const void *block, size_t block_size,
- struct GNUNET_HashCode *key)
+ const void *block, size_t block_size,
+ struct GNUNET_HashCode *key)
{
- /* Store the key in the key argument, return GNUNET_OK on success. */
+ // Store the key in the key argument, return GNUNET_OK on success.
}
\end{lstlisting}
@@ -1407,8 +1347,8 @@ libgnunet_plugin_block_SERVICE_init (void *cls)
{
static enum GNUNET_BLOCK_Type types[] =
{
- GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE, /* list of blocks we care about, from gnunet_block_lib.h */
- GNUNET_BLOCK_TYPE_ANY /* end of list */
+ GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE,
+ GNUNET_BLOCK_TYPE_ANY
};
struct GNUNET_BLOCK_PluginFunctions *api;
@@ -1483,7 +1423,7 @@ to allow for filtering of messages. When an event happens, the appropiate callba
is called with all the information about the event.
\lstset{language=C}
\begin{lstlisting}
-void
+static void
get_callback (void *cls,
enum GNUNET_DHT_RouteOption options,
enum GNUNET_BLOCK_Type type,
@@ -1495,7 +1435,8 @@ get_callback (void *cls,
{
}
-void
+
+static void
get_resp_callback (void *cls,
enum GNUNET_BLOCK_Type type,
const struct GNUNET_PeerIdentity *get_path,
@@ -1509,7 +1450,8 @@ get_resp_callback (void *cls,
{
}
-void
+
+static void
put_callback (void *cls,
enum GNUNET_DHT_RouteOption options,
enum GNUNET_BLOCK_Type type,
@@ -1524,13 +1466,14 @@ put_callback (void *cls,
{
}
+
monitor_handle = GNUNET_DHT_monitor_start (dht_handle,
- block_type, /* GNUNET_BLOCK_TYPE_ANY for all */
- key, /* NULL for all */
- &get_callback,
- &get_resp_callback,
- &put_callback,
- cls);
+ block_type,
+ key,
+ &get_callback,
+ &get_resp_callback,
+ &put_callback,
+ cls);
\end{lstlisting}
diff --git a/doc/testbed_test.c b/doc/testbed_test.c
index 0ef0980af0..1696234b05 100644
--- a/doc/testbed_test.c
+++ b/doc/testbed_test.c
@@ -4,65 +4,35 @@
#include <gnunet/gnunet_testbed_service.h>
#include <gnunet/gnunet_dht_service.h>
-/* Number of peers we want to start */
#define NUM_PEERS 20
static struct GNUNET_TESTBED_Operation *dht_op;
static struct GNUNET_DHT_Handle *dht_handle;
-static struct GNUNET_SCHEDULER_Task * shutdown_tid;
-
-/**
- * Closure to 'dht_ca' and 'dht_da' DHT adapters.
- */
struct MyContext
{
- /**
- * Argument we pass to GNUNET_DHT_connect.
- */
int ht_len;
} ctxt;
-/**
- * Global result for testcase.
- */
static int result;
-/**
- * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
- * Cleans up.
- */
static void
shutdown_task (void *cls)
{
- shutdown_tid = NULL;
if (NULL != dht_op)
{
- GNUNET_TESTBED_operation_done (dht_op); /* indirectly calls the dht_da() for closing
- down the connection to the DHT */
+ GNUNET_TESTBED_operation_done (dht_op);
dht_op = NULL;
dht_handle = NULL;
}
result = GNUNET_OK;
- GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
}
-/**
- * This is where the test logic should be, at least that
- * part of it that uses the DHT of peer "0".
- *
- * @param cls closure, for the example: NULL
- * @param op should be equal to "dht_op"
- * @param ca_result result of the connect operation, the
- * connection to the DHT service
- * @param emsg error message, if testbed somehow failed to
- * connect to the DHT.
- */
static void
service_connect_comp (void *cls,
struct GNUNET_TESTBED_Operation *op,
@@ -71,72 +41,31 @@ service_connect_comp (void *cls,
{
GNUNET_assert (op == dht_op);
dht_handle = ca_result;
- /* Service to DHT successful; here we'd usually do something
- with the DHT (ok, if successful) */
-
- /* for now, just indiscriminately terminate after 10s */
- GNUNET_SCHEDULER_cancel (shutdown_tid);
- shutdown_tid = GNUNET_SCHEDULER_add_delayed
- (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
- &shutdown_task, NULL);
+ // Do work here...
+ GNUNET_SCHEDULER_shutdown ();
}
-/**
- * Testbed has provided us with the configuration to access one
- * of the peers and it is time to do "some" connect operation to
- * "some" subsystem of the peer. For this example, we connect
- * to the DHT subsystem. Testbed doesn't know which subsystem,
- * so we need these adapters to do the actual connecting (and
- * possibly pass additional options to the subsystem connect
- * function, such as the "ht_len" argument for the DHT).
- *
- * @param cls closure
- * @param cfg peer configuration (here: peer[0]
- * @return NULL on error, otherwise some handle to access the
- * subsystem
- */
static void *
dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct MyContext *ctxt = cls;
- /* Use the provided configuration to connect to service */
dht_handle = GNUNET_DHT_connect (cfg, ctxt->ht_len);
return dht_handle;
}
-/**
- * Dual of 'dht_ca' to perform the 'disconnect'/cleanup operation
- * once we no longer need to access this subsystem.
- *
- * @param cls closure
- * @param op_result whatever we returned from 'dht_ca'
- */
static void
dht_da (void *cls, void *op_result)
{
struct MyContext *ctxt = cls;
- /* Disconnect from DHT service */
GNUNET_DHT_disconnect ((struct GNUNET_DHT_Handle *) op_result);
dht_handle = NULL;
}
-/**
- * Main function inovked from TESTBED once all of the
- * peers are up and running. This one then connects
- * just to the DHT service of peer 0.
- *
- * @param cls closure
- * @param h the run handle
- * @param peers started peers for the test
- * @param num_peers size of the 'peers' array
- * @param links_succeeded number of links between peers that were created
- * @param links_failed number of links testbed was unable to establish
- */
static void
test_master (void *cls,
struct GNUNET_TESTBED_RunHandle *h,
@@ -145,27 +74,12 @@ test_master (void *cls,
unsigned int links_succeeded,
unsigned int links_failed)
{
- /* Testbed is ready with peers running and connected in a pre-defined overlay
- topology */
-
- /* do something */
ctxt.ht_len = 10;
-
- /* connect to a peers service */
dht_op = GNUNET_TESTBED_service_connect
- (NULL, /* Closure for operation */
- peers[0], /* The peer whose service to connect to */
- "dht", /* The name of the service */
- service_connect_comp, /* callback to call after a handle to service
- is opened */
- NULL, /* closure for the above callback */
- dht_ca, /* callback to call with peer's configuration;
- this should open the needed service connection */
- dht_da, /* callback to be called when closing the
- opened service connection */
- &ctxt); /* closure for the above two callbacks */
- shutdown_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
- &shutdown_task, NULL);
+ (NULL, peers[0], "dht",
+ &service_connect_comp, NULL,
+ &dht_ca, &dht_da, &ctxt);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
}
@@ -176,15 +90,9 @@ main (int argc, char **argv)
result = GNUNET_SYSERR;
ret = GNUNET_TESTBED_test_run
- ("awesome-test", /* test case name */
- "template.conf", /* template configuration */
- NUM_PEERS, /* number of peers to start */
- 0LL, /* Event mask - set to 0 for no event notifications */
- NULL, /* Controller event callback */
- NULL, /* Closure for controller event callback */
- &test_master, /* continuation callback to be called when testbed setup is
- complete */
- NULL); /* Closure for the test_master callback */
+ ("awesome-test", "template.conf",
+ NUM_PEERS, 0LL,
+ NULL, NULL, &test_master, NULL);
if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
return 1;
return 0;