aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 f0dfe58b3..115ed7702 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 069c1838f..2b4a0d8e1 100644
--- a/doc/gnunet-c-tutorial.tex
+++ b/doc/gnunet-c-tutorial.tex
@@ -1,12 +1,13 @@
1\documentclass[10pt]{article} 1\documentclass[10pt]{article}
2\usepackage[ansinew]{inputenc} 2\usepackage[ansinew]{inputenc}
3\usepackage{makeidx,amsmath,amssymb,exscale,multicol,epsfig,graphics,verbatim,ulem} 3\usepackage{makeidx,amsmath,amssymb,exscale,multicol,epsfig,graphics,verbatim,ulem}
4\usepackage{epsfig,geometry,url,listings, subcaption} 4\usepackage{epsfig,geometry,url,listings,subcaption}
5\usepackage{boxedminipage} 5\usepackage{boxedminipage}
6\usepackage[T1]{fontenc}%required 6\usepackage[T1]{fontenc}%required
7\usepackage{textcomp} 7\usepackage{textcomp}
8\geometry{headsep=3ex,hscale=0.9} 8\geometry{headsep=3ex,hscale=0.9}
9\usepackage{hyperref} 9\usepackage{hyperref}
10\usepackage{color}
10\hypersetup{pdftitle={GNUnet C Tutorial}, 11\hypersetup{pdftitle={GNUnet C Tutorial},
11 pdfsubject={GNUnet}, 12 pdfsubject={GNUnet},
12 pdfauthor={Christian Grothoff <christian@grothoff.org>}, 13 pdfauthor={Christian Grothoff <christian@grothoff.org>},
@@ -28,6 +29,26 @@ literate={*}{{\char42}}1
28 29
29\begin{document} 30\begin{document}
30 31
32\lstset{ %
33language=C, % choose the language of the code
34basicstyle=\footnotesize, % the size of the fonts that are used for the code
35numbers=left, % where to put the line-numbers
36numberstyle=\footnotesize, % the size of the fonts that are used for the line-numbers
37stepnumber=1, % the step between two line-numbers. If it is 1 each line will be numbered
38numbersep=5pt, % how far the line-numbers are from the code
39backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
40showspaces=false, % show spaces adding particular underscores
41showstringspaces=false, % underline spaces within strings
42showtabs=false, % show tabs within strings adding particular underscores
43frame=single, % adds a frame around the code
44tabsize=2, % sets default tabsize to 2 spaces
45captionpos=b, % sets the caption-position to bottom
46breaklines=true, % sets automatic line breaking
47breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
48escapeinside={\%*}{*)} % if you want to add a comment within your code
49}
50
51
31\begin{center} 52\begin{center}
32\large {A Tutorial for GNUnet 0.10.x (C version)} 53\large {A Tutorial for GNUnet 0.10.x (C version)}
33 54
@@ -68,20 +89,25 @@ You should also download the signature file and verify the integrity of the tarb
68\url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz.sig} 89\url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz.sig}
69\end{center} 90\end{center}
70To verify the signature you should first import the GPG key used to sign the tarball 91To verify the signature you should first import the GPG key used to sign the tarball
92\lstset{language=bash}
71\begin{lstlisting} 93\begin{lstlisting}
72$ gpg --keyserver keys.gnupg.net --recv-keys 48426C7E 94$ gpg --keyserver keys.gnupg.net --recv-keys 48426C7E
73\end{lstlisting} 95\end{lstlisting}
74And use this key to verify the tarball's signature 96And use this key to verify the tarball's signature
97\lstset{language=bash}
75\begin{lstlisting} 98\begin{lstlisting}
76$ gpg --verify gnunet-0.10.x.tar.gz.sig gnunet-0.10.x.tar.gz 99$ gpg --verify gnunet-0.10.x.tar.gz.sig gnunet-0.10.x.tar.gz
77\end{lstlisting} 100\end{lstlisting}
78After successfully verifying the integrity you can extract the tarball using 101After successfully verifying the integrity you can extract the tarball using
102\lstset{language=bash}
79\begin{lstlisting} 103\begin{lstlisting}
80$ tar xvzf gnunet-0.10.x.tar.gz 104$ tar xvzf gnunet-0.10.x.tar.gz
81$ mv gnunet-0.10.x gnunet # we will use the directory "gnunet" in the remainder of this document 105$ mv gnunet-0.10.x gnunet # we will use the directory "gnunet" in the remainder of this document
82$ cd gnunet 106$ cd gnunet
83\end{lstlisting} 107\end{lstlisting}
84 108
109However, please note that stable versions can be very outdated, as a developer
110you are strongly encouraged to use the version from \url{https://gnunet.org/git/}.
85 111
86\subsection{Installing Build Tool Chain and Dependencies} 112\subsection{Installing Build Tool Chain and Dependencies}
87 113
@@ -116,15 +142,15 @@ The remainder of this tutorial assumes that you have Git Master checked out.
116\subsection{Compiling and Installing GNUnet} 142\subsection{Compiling and Installing GNUnet}
117 143
118First, you need to install at least {\tt libgnupgerror} version 144First, you need to install at least {\tt libgnupgerror} version
1191.12\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.12.tar.bz2}} 1451.27\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.27.tar.bz2}}
120and {\tt libgcrypt} version 146and {\tt libgcrypt} version
1211.6\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.6.0.tar.bz2}}. 1471.7.6\footnote{\url{ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.6.tar.bz2}}.
122 148
123\lstset{language=bash} 149\lstset{language=bash}
124\begin{lstlisting} 150\begin{lstlisting}
125$ wget ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.12.tar.bz2 151$ wget ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-1.27.tar.bz2
126$ tar xf libgpg-error-1.12.tar.bz2 152$ tar xf libgpg-error-1.27.tar.bz2
127$ cd libgpg-error-1.12 153$ cd libgpg-error-1.27
128$ ./configure 154$ ./configure
129$ sudo make install 155$ sudo make install
130$ cd .. 156$ cd ..
@@ -132,9 +158,9 @@ $ cd ..
132 158
133\lstset{language=bash} 159\lstset{language=bash}
134\begin{lstlisting} 160\begin{lstlisting}
135$ wget ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.6.0.tar.bz2 161$ wget ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.7.6.tar.bz2
136$ tar xf libgcrypt-1.6.0.tar.bz2 162$ tar xf libgcrypt-1.7.6.tar.bz2
137$ cd libgcrypt-1.6.0 163$ cd libgcrypt-1.7.6
138$ ./configure 164$ ./configure
139$ sudo make install 165$ sudo make install
140$ cd .. 166$ cd ..
@@ -176,12 +202,14 @@ $ touch ~/.config/gnunet.conf
176You should check your installation to ensure that installing GNUnet 202You should check your installation to ensure that installing GNUnet
177was successful up to this point. You should be able to access GNUnet's 203was successful up to this point. You should be able to access GNUnet's
178binaries and run GNUnet's self check. 204binaries and run GNUnet's self check.
205\lstset{language=bash}
179\begin{lstlisting} 206\begin{lstlisting}
180$ which gnunet-arm 207$ which gnunet-arm
181\end{lstlisting} 208\end{lstlisting}
182should return \lstinline|$PREFIX/bin/gnunet-arm|. It should be 209should return \lstinline|$PREFIX/bin/gnunet-arm|. It should be
183located in your GNUnet installation and the output should not be 210located in your GNUnet installation and the output should not be
184empty. If you see an output like: 211empty. If you see an output like:
212\lstset{language=bash}
185\begin{lstlisting} 213\begin{lstlisting}
186$ which gnunet-arm 214$ which gnunet-arm
187$ 215$
@@ -189,29 +217,20 @@ $
189check your {\tt PATH} variable to ensure GNUnet's {\tt bin} directory is included. 217check your {\tt PATH} variable to ensure GNUnet's {\tt bin} directory is included.
190 218
191GNUnet provides tests for all of its subcomponents. Run 219GNUnet provides tests for all of its subcomponents. Run
220\lstset{language=bash}
192\begin{lstlisting} 221\begin{lstlisting}
193$ make check 222$ make check
194\end{lstlisting} 223\end{lstlisting}
195to execute tests for all components. {\tt make check} traverses all subdirectories in {\tt src}. 224to execute tests for all components. {\tt make check} traverses all subdirectories in {\tt src}.
196For every subdirectory you should get a message like this: 225For every subdirectory you should get a message like this:
197 226
198\begin{lstlisting} 227\begin{verbatim}
199make[2]: Entering directory `/home/$USER/gnunet/contrib' 228make[2]: Entering directory `/home/$USER/gnunet/contrib'
200PASS: test_gnunet_prefix 229PASS: test_gnunet_prefix
201============= 230=============
2021 test passed 2311 test passed
203============= 232=============
204\end{lstlisting} 233\end{verbatim}
205
206If you see a message like this:
207
208\begin{lstlisting}
209Mar 12 16:57:56-642482 resolver-api-19449 ERROR Must specify `HOSTNAME' for `resolver' in configuration!
210Mar 12 16:57:56-642573 test_program-19449 ERROR Assertion failed at resolver_api.c:204.
211/bin/bash: line 5: 19449 Aborted (core dumped) ${dir}$tst
212FAIL: test_program
213\end{lstlisting}
214double check the steps performed in ~\ref{sub:install}
215 234
216 235
217\section{Background: GNUnet Architecture} 236\section{Background: GNUnet Architecture}
@@ -262,6 +281,7 @@ First of all we need to configure your peer. Each peer is started with a configu
262 281
263Since we want to start additional peers later, we need 282Since we want to start additional peers later, we need
264some modifications from the default configuration. We need to create a separate service home and a file containing our modifications for this peer: 283some modifications from the default configuration. We need to create a separate service home and a file containing our modifications for this peer:
284\lstset{language=bash}
265\begin{lstlisting} 285\begin{lstlisting}
266$ mkdir ~/gnunet1/ 286$ mkdir ~/gnunet1/
267$ touch peer1.conf 287$ touch peer1.conf
@@ -271,12 +291,12 @@ Now add the following lines to peer1.conf to use this directory. For
271simplified usage we want to prevent the peer to connect to the GNUnet 291simplified usage we want to prevent the peer to connect to the GNUnet
272network since this could lead to confusing output. This modifications 292network since this could lead to confusing output. This modifications
273will replace the default settings: 293will replace the default settings:
274\begin{lstlisting} 294\begin{verbatim}
275[PATHS] 295[PATHS]
276GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data 296GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data
277[hostlist] 297[hostlist]
278SERVERS = # prevent bootstrapping 298SERVERS = # prevent bootstrapping
279\end{lstlisting} 299\end{verbatim}
280 300
281 301
282\subsection{Start a peer} 302\subsection{Start a peer}
@@ -322,6 +342,7 @@ $ cd ~/gnunet/src/dht;
322$ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY 342$ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY
323\end{lstlisting} 343\end{lstlisting}
324Now open a separate terminal and change again to the \lstinline|gnunet/src/dht| directory: 344Now open a separate terminal and change again to the \lstinline|gnunet/src/dht| directory:
345\lstset{language=bash}
325\begin{lstlisting} 346\begin{lstlisting}
326$ cd ~/gnunet/src/dht 347$ cd ~/gnunet/src/dht
327$ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE # put VALUE under KEY in the DHT 348$ ./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
348configuration file: 369configuration file:
349% 370%
350\lstset{language=bash} 371\lstset{language=bash}
372\lstset{language=bash}
351\begin{lstlisting} 373\begin{lstlisting}
352$ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf 374$ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf
353\end{lstlisting} 375\end{lstlisting}
@@ -399,10 +421,10 @@ If you want the two peers to connect, you have multiple options:
399To setup peer 1 as bootstrapping server change the configuration of 421To setup peer 1 as bootstrapping server change the configuration of
400the first one to be a hostlist server by adding the following lines to 422the first one to be a hostlist server by adding the following lines to
401\texttt{peer1.conf} to enable bootstrapping server: 423\texttt{peer1.conf} to enable bootstrapping server:
402 \begin{lstlisting} 424 \begin{verbatim}
403[hostlist] 425[hostlist]
404OPTIONS = -p 426OPTIONS = -p
405\end{lstlisting} 427\end{verbatim}
406 428
407Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with 429Then change {\tt peer2.conf} and replace the ``\texttt{SERVERS}'' line in the ``\texttt{[hostlist]}'' section with
408``\texttt{http://localhost:8080/}''. Restart both peers using: 430``\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:
432 454
433Check that they are connected using {\tt gnunet-core -c peer1.conf}, which should give you the other peer's 455Check that they are connected using {\tt gnunet-core -c peer1.conf}, which should give you the other peer's
434peer identity: 456peer identity:
457\lstset{language=bash}
435\begin{lstlisting} 458\begin{lstlisting}
436$ gnunet-core -c peer1.conf 459$ gnunet-core -c peer1.conf
437Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG' 460Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG'
@@ -463,7 +486,8 @@ found in the testbed default configuration file \texttt{src/testbed/testbed.conf
463 486
464With the testbed API, a sample test case can be structured as follows: 487With the testbed API, a sample test case can be structured as follows:
465% <lynX> Is there a way to pick a more readable font for this include? 488% <lynX> Is there a way to pick a more readable font for this include?
466\lstinputlisting[language=C]{testbed_test.c} 489\lstset{language=C}
490\lstinputlisting{testbed_test.c}
467The source code for the above listing can be found at 491The source code for the above listing can be found at
468\url{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c} 492\url{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c}
469or in the {\tt doc/} folder of your repository check-out. 493or 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
593to the parsed configuration (and the configuration file name that was 617to the parsed configuration (and the configuration file name that was
594used, which is typically not needed): 618used, which is typically not needed):
595 619
596\lstset{language=c} 620\lstset{language=C}
597\begin{lstlisting} 621\begin{lstlisting}
598#include <gnunet/platform.h> 622#include <gnunet/platform.h>
599#include <gnunet/gnunet_util_lib.h> 623#include <gnunet/gnunet_util_lib.h>
@@ -606,7 +630,7 @@ run (void *cls,
606 const char *cfgfile, 630 const char *cfgfile,
607 const struct GNUNET_CONFIGURATION_Handle *cfg) 631 const struct GNUNET_CONFIGURATION_Handle *cfg)
608{ 632{
609 /* main code here */ 633 // main code here
610 ret = 0; 634 ret = 0;
611} 635}
612 636
@@ -632,6 +656,7 @@ expanding the {\tt options} array. For example, the following would
632add a string-option and a binary flag (defaulting to {\tt NULL} and 656add a string-option and a binary flag (defaulting to {\tt NULL} and
633{\tt GNUNET\_NO} respectively): 657{\tt GNUNET\_NO} respectively):
634 658
659\lstset{language=C}
635\begin{lstlisting} 660\begin{lstlisting}
636static char *string_option; 661static char *string_option;
637static int a_flag; 662static int a_flag;
@@ -696,7 +721,7 @@ file).
696Before a client library can implement the application-specific protocol 721Before a client library can implement the application-specific protocol
697with the service, a connection must be created: 722with the service, a connection must be created:
698 723
699\lstset{language=c} 724\lstset{language=C}
700\begin{lstlisting} 725\begin{lstlisting}
701 struct GNUNET_MQ_MessageHandlers handlers[] = { 726 struct GNUNET_MQ_MessageHandlers handlers[] = {
702 // ... 727 // ...
@@ -723,36 +748,26 @@ In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_Message
723in big endian format. This header defines the size and the type of the 748in big endian format. This header defines the size and the type of the
724message, the payload follows after this header. 749message, the payload follows after this header.
725 750
726\lstset{language=c} 751\lstset{language=C}
727\begin{lstlisting} 752\begin{lstlisting}
728struct GNUNET_MessageHeader 753struct GNUNET_MessageHeader
729{ 754{
730
731 /**
732 * The length of the struct (in bytes, including the length field itself),
733 * in big-endian format.
734 */
735 uint16_t size GNUNET_PACKED; 755 uint16_t size GNUNET_PACKED;
736
737 /**
738 * The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
739 */
740 uint16_t type GNUNET_PACKED; 756 uint16_t type GNUNET_PACKED;
741
742}; 757};
743\end{lstlisting} 758\end{lstlisting}
744 759
745Existing message types are defined in {\tt gnunet\_protocols.h}\\ 760Existing message types are defined in {\tt gnunet\_protocols.h}\\
746A common way to create a message is with an envelope: 761A common way to create a message is with an envelope:
747 762
748\lstset{language=c} 763\lstset{language=C}
749\begin{lstlisting} 764\begin{lstlisting}
750struct GNUNET_MQ_Envelope *env; 765struct GNUNET_MQ_Envelope *env;
751struct GNUNET_MessageHeader *msg; 766struct GNUNET_MessageHeader *msg;
752 767
753env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE); 768env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE);
754memcpy (&msg[1], &payload, payload_size); 769memcpy (&msg[1], &payload, payload_size);
755/* Send message via message queue 'mq': */ 770// Send message via message queue 'mq'
756GNUNET_mq_send (mq, env); 771GNUNET_mq_send (mq, env);
757\end{lstlisting} 772\end{lstlisting}
758 773
@@ -785,38 +800,19 @@ and {\tt handle\_} are mandatory.
785 800
786\lstset{language=c} 801\lstset{language=c}
787\begin{lstlisting} 802\begin{lstlisting}
788/**
789 * Function called with MyMessage messages from service.
790 *
791 * @param cls closure
792 * @param msg message received
793 */
794static void 803static void
795handle_fix (void *cls, const struct MyMessage *msg) 804handle_fix (void *cls, const struct MyMessage *msg)
796{ 805{
797 // process 'msg' 806 // process 'msg'
798} 807}
799 808
800/**
801 * Function called with MyVarMessage messages from service.
802 *
803 * @param cls closure
804 * @param msg message received
805 * @return #GNUNET_OK if @a msg is well-formed
806 */
807static int 809static int
808check_var (void *cls, const struct MyVarMessage *msg) 810check_var (void *cls, const struct MyVarMessage *msg)
809{ 811{
810 // check 'msg' is well-formed 812 // check 'msg' is well-formed
811 return GNUNET_OK; /* suppose yes */ 813 return GNUNET_OK;
812} 814}
813 815
814/**
815 * Function called with MyMessage messages from service.
816 *
817 * @param cls closure
818 * @param msg message received
819 */
820static void 816static void
821handle_var (void *cls, const struct MyVarMessage *msg) 817handle_var (void *cls, const struct MyVarMessage *msg)
822{ 818{
@@ -900,13 +896,6 @@ like this:
900 896
901\lstset{language=c} 897\lstset{language=c}
902\begin{lstlisting} 898\begin{lstlisting}
903/**
904 * Launch service.
905 *
906 * @param cls closure
907 * @param c configuration to use
908 * @param service the initialized service
909 */
910static void 899static void
911run (void *cls, 900run (void *cls,
912 const struct GNUNET_CONFIGURATION_Handle *c, 901 const struct GNUNET_CONFIGURATION_Handle *c,
@@ -914,14 +903,6 @@ run (void *cls,
914{ 903{
915} 904}
916 905
917/**
918 * Callback called when a client connects to the service.
919 *
920 * @param cls closure for the service
921 * @param c the new client that connected to the service
922 * @param mq the message queue used to send messages to the client
923 * @return @a c
924 */
925static void * 906static void *
926client_connect_cb (void *cls, 907client_connect_cb (void *cls,
927 struct GNUNET_SERVICE_Client *c, 908 struct GNUNET_SERVICE_Client *c,
@@ -930,13 +911,6 @@ client_connect_cb (void *cls,
930 return c; 911 return c;
931} 912}
932 913
933/**
934 * Callback called when a client disconnected from the service
935 *
936 * @param cls closure for the service
937 * @param c the client that disconnected
938 * @param internal_cls should be equal to @a c
939 */
940static void 914static void
941client_disconnect_cb (void *cls, 915client_disconnect_cb (void *cls,
942 struct GNUNET_SERVICE_Client *c, 916 struct GNUNET_SERVICE_Client *c,
@@ -988,11 +962,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
988 GNUNET_CORE_StartupCallback init, 962 GNUNET_CORE_StartupCallback init,
989 GNUNET_CORE_ConnectEventHandler connects, 963 GNUNET_CORE_ConnectEventHandler connects,
990 GNUNET_CORE_DisconnectEventHandler disconnects, 964 GNUNET_CORE_DisconnectEventHandler disconnects,
991 GNUNET_CORE_MessageCallback inbound_notify, 965 const struct GNUNET_MQ_MessageHandler *handlers);
992 int inbound_hdr_only,
993 GNUNET_CORE_MessageCallback outbound_notify,
994 int outbound_hdr_only,
995 const struct GNUNET_CORE_MessageHandler *handlers);
996\end{lstlisting} 966\end{lstlisting}
997 967
998\subsection{New P2P connections} 968\subsection{New P2P connections}
@@ -1003,45 +973,33 @@ which communicates the identity of the new peer to the service:
1003 973
1004\lstset{language=C} 974\lstset{language=C}
1005\begin{lstlisting} 975\begin{lstlisting}
1006void 976void *
1007connects (void *cls, 977connects (void *cls,
1008 const struct GNUNET_PeerIdentity * peer) 978 const struct GNUNET_PeerIdentity *peer,
979 struct GNUNET_MQ_Handle *mq)
1009{ 980{
1010 /* Save identity for later use */ 981 return mq;
1011 /* Optional: start sending messages to peer */
1012} 982}
1013\end{lstlisting} 983\end{lstlisting}
1014 984
985Note that whatever you return from {\tt connects} is given as the
986{\it cls} argument to the message handlers for messages from
987the respective peer.
988
1015\exercise{Create a service that connects to the \texttt{CORE}. Then 989\exercise{Create a service that connects to the \texttt{CORE}. Then
1016start (and connect) two peers and print a message once your connect 990start (and connect) two peers and print a message once your connect
1017callback is invoked.} 991callback is invoked.}
1018 992
1019\subsection{Receiving P2P Messages} 993\subsection{Receiving P2P Messages}
1020 994
1021To receive messages from \texttt{CORE}, services register a set of handlers 995To receive messages from \texttt{CORE}, you pass the desired
1022(parameter {\tt *handlers} in the \lstinline|GNUNET_CORE_connect| call that are called by \texttt{CORE} 996{\em handlers} to the {\tt GNUNET\_CORE\_connect()} function,
1023when a suitable message arrives. 997just as we showed for services.
1024 998
1025\lstset{language=c} 999It is your responsibility to process messages fast enough or
1026\begin{lstlisting} 1000to implement flow control. If an application does not process
1027static int 1001CORE messages fast enough, CORE will randomly drop messages
1028callback_function_for_type_one(void *cls, 1002to not keep a very long queue in memory.
1029 const struct GNUNET_PeerIdentity *peer,
1030 const struct GNUNET_MessageHeader *message)
1031{
1032 /* Do stuff */
1033 return GNUNET_OK; /* or GNUNET_SYSERR to close the connection */
1034}
1035
1036/**
1037 * Functions to handle messages from core
1038 */
1039static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1040 {&callback_function_for_type_one, GNUNET_MESSAGE_TYPE_MYSERVICE_TYPE_ONE, 0},
1041 /* more handlers*/
1042 {NULL, 0, 0}
1043};
1044\end{lstlisting}
1045 1003
1046\exercise{Start one peer with a new service that has a message 1004\exercise{Start one peer with a new service that has a message
1047handler and start a second peer that only has your ``old'' service 1005handler and start a second peer that only has your ``old'' service
@@ -1051,29 +1009,13 @@ the two peers are connected? Why?}
1051 1009
1052\subsection{Sending P2P Messages} 1010\subsection{Sending P2P Messages}
1053 1011
1054In response to events (connect, disconnect, inbound messages, 1012You can transmit messages to other peers using the {\it mq} you were
1055timing, etc.) services can then use this API to transmit messages: 1013given during the {\tt connect} callback. Note that the {\it mq}
1014automatically is released upon {\tt disconnect} and that you must
1015not use it afterwards.
1056 1016
1057\lstset{language=C} 1017It is your responsibility to not over-fill the message queue, GNUnet
1058\begin{lstlisting} 1018will send the messages roughly in the order given as soon as possible.
1059typedef size_t
1060(*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls,
1061 size_t size,
1062 void *buf)
1063{
1064 /* Fill "*buf" with up to "size" bytes, must start with GNUNET_MessageHeader */
1065 return n; /* Total size of the message put in "*buf" */
1066}
1067
1068struct GNUNET_CORE_TransmitHandle *
1069GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
1070 int cork, uint32_t priority,
1071 struct GNUNET_TIME_Relative maxdelay,
1072 const struct GNUNET_PeerIdentity *target,
1073 size_t notify_size,
1074 GNUNET_CONNECTION_TransmitReadyNotify notify,
1075 void *notify_cls);
1076\end{lstlisting}
1077 1019
1078\exercise{Write a service that upon connect sends messages as 1020\exercise{Write a service that upon connect sends messages as
1079fast as possible to the other peer (the other peer should run a 1021fast 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!
1258 1200
1259\lstset{language=C} 1201\lstset{language=C}
1260\begin{lstlisting} 1202\begin{lstlisting}
1261void 1203static void
1262message_sent_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1204message_sent_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1263{ 1205{
1264 /* Request has left local node */ 1206 // Request has left local node
1265} 1207}
1266 1208
1267struct GNUNET_DHT_PutHandle * 1209struct GNUNET_DHT_PutHandle *
1268GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, 1210GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
1269 const struct GNUNET_HashCode *key, 1211 const struct GNUNET_HashCode *key,
1270 uint32_t desired_replication_level, 1212 uint32_t desired_replication_level,
1271 enum GNUNET_DHT_RouteOption options, /* Route options, see next call */ 1213 enum GNUNET_DHT_RouteOption options,
1272 enum GNUNET_BLOCK_Type type, size_t size, const void *data, 1214 enum GNUNET_BLOCK_Type type, size_t size, const void *data,
1273 struct GNUNET_TIME_Absolute exp, /* When does the data expire? */ 1215 struct GNUNET_TIME_Absolute exp,
1274 struct GNUNET_TIME_Relative timeout, /* How long to try to send the request */ 1216 struct GNUNET_TIME_Relative timeout,
1275 GNUNET_DHT_PutContinuation cont, 1217 GNUNET_DHT_PutContinuation cont, void *cont_cls)
1276 void *cont_cls)
1277\end{lstlisting} 1218\end{lstlisting}
1278 1219
1279\exercise{Store a value in the DHT periodically to make sure it is available 1220\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,
1305 unsigned int put_path_length, 1246 unsigned int put_path_length,
1306 enum GNUNET_BLOCK_Type type, size_t size, const void *data) 1247 enum GNUNET_BLOCK_Type type, size_t size, const void *data)
1307{ 1248{
1308 /* Do stuff with the data and/or route */ 1249 // Optionally:
1309 /* Optionally: */ 1250 GNUNET_DHT_get_stop (get_handle);
1310 GNUNET_DHT_get_stop (get_handle);
1311} 1251}
1312 1252
1313get_handle = 1253get_handle =
@@ -1315,9 +1255,9 @@ get_handle =
1315 block_type, 1255 block_type,
1316 &key, 1256 &key,
1317 replication, 1257 replication,
1318 GNUNET_DHT_RO_NONE, /* Route options */ 1258 GNUNET_DHT_RO_NONE,
1319 NULL, /* xquery: not used here */ 1259 NULL,
1320 0, /* xquery size */ 1260 0,
1321 &get_result_iterator, 1261 &get_result_iterator,
1322 cls) 1262 cls)
1323\end{lstlisting} 1263\end{lstlisting}
@@ -1356,13 +1296,13 @@ static enum GNUNET_BLOCK_EvaluationResult
1356block_plugin_SERVICE_evaluate (void *cls, 1296block_plugin_SERVICE_evaluate (void *cls,
1357 enum GNUNET_BLOCK_Type type, 1297 enum GNUNET_BLOCK_Type type,
1358 struct GNUNET_BlockGroup *bg, 1298 struct GNUNET_BlockGroup *bg,
1359 const GNUNET_HashCode *query, 1299 const GNUNET_HashCode *query,
1360 const void *xquery, 1300 const void *xquery,
1361 size_t xquery_size, 1301 size_t xquery_size,
1362 const void *reply_block, 1302 const void *reply_block,
1363 size_t reply_block_size) 1303 size_t reply_block_size)
1364{ 1304{
1365 /* Verify type, block and bg */ 1305 // Verify type, block and bg
1366} 1306}
1367\end{lstlisting} 1307\end{lstlisting}
1368 1308
@@ -1385,10 +1325,10 @@ just fine with such blocks).
1385\begin{lstlisting} 1325\begin{lstlisting}
1386static int 1326static int
1387block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, 1327block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type,
1388 const void *block, size_t block_size, 1328 const void *block, size_t block_size,
1389 struct GNUNET_HashCode *key) 1329 struct GNUNET_HashCode *key)
1390{ 1330{
1391 /* Store the key in the key argument, return GNUNET_OK on success. */ 1331 // Store the key in the key argument, return GNUNET_OK on success.
1392} 1332}
1393\end{lstlisting} 1333\end{lstlisting}
1394 1334
@@ -1407,8 +1347,8 @@ libgnunet_plugin_block_SERVICE_init (void *cls)
1407{ 1347{
1408 static enum GNUNET_BLOCK_Type types[] = 1348 static enum GNUNET_BLOCK_Type types[] =
1409 { 1349 {
1410 GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE, /* list of blocks we care about, from gnunet_block_lib.h */ 1350 GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE,
1411 GNUNET_BLOCK_TYPE_ANY /* end of list */ 1351 GNUNET_BLOCK_TYPE_ANY
1412 }; 1352 };
1413 struct GNUNET_BLOCK_PluginFunctions *api; 1353 struct GNUNET_BLOCK_PluginFunctions *api;
1414 1354
@@ -1483,7 +1423,7 @@ to allow for filtering of messages. When an event happens, the appropiate callba
1483is called with all the information about the event. 1423is called with all the information about the event.
1484\lstset{language=C} 1424\lstset{language=C}
1485\begin{lstlisting} 1425\begin{lstlisting}
1486void 1426static void
1487get_callback (void *cls, 1427get_callback (void *cls,
1488 enum GNUNET_DHT_RouteOption options, 1428 enum GNUNET_DHT_RouteOption options,
1489 enum GNUNET_BLOCK_Type type, 1429 enum GNUNET_BLOCK_Type type,
@@ -1495,7 +1435,8 @@ get_callback (void *cls,
1495{ 1435{
1496} 1436}
1497 1437
1498void 1438
1439static void
1499get_resp_callback (void *cls, 1440get_resp_callback (void *cls,
1500 enum GNUNET_BLOCK_Type type, 1441 enum GNUNET_BLOCK_Type type,
1501 const struct GNUNET_PeerIdentity *get_path, 1442 const struct GNUNET_PeerIdentity *get_path,
@@ -1509,7 +1450,8 @@ get_resp_callback (void *cls,
1509{ 1450{
1510} 1451}
1511 1452
1512void 1453
1454static void
1513put_callback (void *cls, 1455put_callback (void *cls,
1514 enum GNUNET_DHT_RouteOption options, 1456 enum GNUNET_DHT_RouteOption options,
1515 enum GNUNET_BLOCK_Type type, 1457 enum GNUNET_BLOCK_Type type,
@@ -1524,13 +1466,14 @@ put_callback (void *cls,
1524{ 1466{
1525} 1467}
1526 1468
1469
1527monitor_handle = GNUNET_DHT_monitor_start (dht_handle, 1470monitor_handle = GNUNET_DHT_monitor_start (dht_handle,
1528 block_type, /* GNUNET_BLOCK_TYPE_ANY for all */ 1471 block_type,
1529 key, /* NULL for all */ 1472 key,
1530 &get_callback, 1473 &get_callback,
1531 &get_resp_callback, 1474 &get_resp_callback,
1532 &put_callback, 1475 &put_callback,
1533 cls); 1476 cls);
1534\end{lstlisting} 1477\end{lstlisting}
1535 1478
1536 1479
diff --git a/doc/testbed_test.c b/doc/testbed_test.c
index 0ef0980af..1696234b0 100644
--- a/doc/testbed_test.c
+++ b/doc/testbed_test.c
@@ -4,65 +4,35 @@
4#include <gnunet/gnunet_testbed_service.h> 4#include <gnunet/gnunet_testbed_service.h>
5#include <gnunet/gnunet_dht_service.h> 5#include <gnunet/gnunet_dht_service.h>
6 6
7/* Number of peers we want to start */
8#define NUM_PEERS 20 7#define NUM_PEERS 20
9 8
10static struct GNUNET_TESTBED_Operation *dht_op; 9static struct GNUNET_TESTBED_Operation *dht_op;
11 10
12static struct GNUNET_DHT_Handle *dht_handle; 11static struct GNUNET_DHT_Handle *dht_handle;
13 12
14static struct GNUNET_SCHEDULER_Task * shutdown_tid;
15 13
16
17/**
18 * Closure to 'dht_ca' and 'dht_da' DHT adapters.
19 */
20struct MyContext 14struct MyContext
21{ 15{
22 /**
23 * Argument we pass to GNUNET_DHT_connect.
24 */
25 int ht_len; 16 int ht_len;
26} ctxt; 17} ctxt;
27 18
28 19
29/**
30 * Global result for testcase.
31 */
32static int result; 20static int result;
33 21
34 22
35/**
36 * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
37 * Cleans up.
38 */
39static void 23static void
40shutdown_task (void *cls) 24shutdown_task (void *cls)
41{ 25{
42 shutdown_tid = NULL;
43 if (NULL != dht_op) 26 if (NULL != dht_op)
44 { 27 {
45 GNUNET_TESTBED_operation_done (dht_op); /* indirectly calls the dht_da() for closing 28 GNUNET_TESTBED_operation_done (dht_op);
46 down the connection to the DHT */
47 dht_op = NULL; 29 dht_op = NULL;
48 dht_handle = NULL; 30 dht_handle = NULL;
49 } 31 }
50 result = GNUNET_OK; 32 result = GNUNET_OK;
51 GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
52} 33}
53 34
54 35
55/**
56 * This is where the test logic should be, at least that
57 * part of it that uses the DHT of peer "0".
58 *
59 * @param cls closure, for the example: NULL
60 * @param op should be equal to "dht_op"
61 * @param ca_result result of the connect operation, the
62 * connection to the DHT service
63 * @param emsg error message, if testbed somehow failed to
64 * connect to the DHT.
65 */
66static void 36static void
67service_connect_comp (void *cls, 37service_connect_comp (void *cls,
68 struct GNUNET_TESTBED_Operation *op, 38 struct GNUNET_TESTBED_Operation *op,
@@ -71,72 +41,31 @@ service_connect_comp (void *cls,
71{ 41{
72 GNUNET_assert (op == dht_op); 42 GNUNET_assert (op == dht_op);
73 dht_handle = ca_result; 43 dht_handle = ca_result;
74 /* Service to DHT successful; here we'd usually do something 44 // Do work here...
75 with the DHT (ok, if successful) */ 45 GNUNET_SCHEDULER_shutdown ();
76
77 /* for now, just indiscriminately terminate after 10s */
78 GNUNET_SCHEDULER_cancel (shutdown_tid);
79 shutdown_tid = GNUNET_SCHEDULER_add_delayed
80 (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
81 &shutdown_task, NULL);
82} 46}
83 47
84 48
85/**
86 * Testbed has provided us with the configuration to access one
87 * of the peers and it is time to do "some" connect operation to
88 * "some" subsystem of the peer. For this example, we connect
89 * to the DHT subsystem. Testbed doesn't know which subsystem,
90 * so we need these adapters to do the actual connecting (and
91 * possibly pass additional options to the subsystem connect
92 * function, such as the "ht_len" argument for the DHT).
93 *
94 * @param cls closure
95 * @param cfg peer configuration (here: peer[0]
96 * @return NULL on error, otherwise some handle to access the
97 * subsystem
98 */
99static void * 49static void *
100dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) 50dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
101{ 51{
102 struct MyContext *ctxt = cls; 52 struct MyContext *ctxt = cls;
103 53
104 /* Use the provided configuration to connect to service */
105 dht_handle = GNUNET_DHT_connect (cfg, ctxt->ht_len); 54 dht_handle = GNUNET_DHT_connect (cfg, ctxt->ht_len);
106 return dht_handle; 55 return dht_handle;
107} 56}
108 57
109 58
110/**
111 * Dual of 'dht_ca' to perform the 'disconnect'/cleanup operation
112 * once we no longer need to access this subsystem.
113 *
114 * @param cls closure
115 * @param op_result whatever we returned from 'dht_ca'
116 */
117static void 59static void
118dht_da (void *cls, void *op_result) 60dht_da (void *cls, void *op_result)
119{ 61{
120 struct MyContext *ctxt = cls; 62 struct MyContext *ctxt = cls;
121 63
122 /* Disconnect from DHT service */
123 GNUNET_DHT_disconnect ((struct GNUNET_DHT_Handle *) op_result); 64 GNUNET_DHT_disconnect ((struct GNUNET_DHT_Handle *) op_result);
124 dht_handle = NULL; 65 dht_handle = NULL;
125} 66}
126 67
127 68
128/**
129 * Main function inovked from TESTBED once all of the
130 * peers are up and running. This one then connects
131 * just to the DHT service of peer 0.
132 *
133 * @param cls closure
134 * @param h the run handle
135 * @param peers started peers for the test
136 * @param num_peers size of the 'peers' array
137 * @param links_succeeded number of links between peers that were created
138 * @param links_failed number of links testbed was unable to establish
139 */
140static void 69static void
141test_master (void *cls, 70test_master (void *cls,
142 struct GNUNET_TESTBED_RunHandle *h, 71 struct GNUNET_TESTBED_RunHandle *h,
@@ -145,27 +74,12 @@ test_master (void *cls,
145 unsigned int links_succeeded, 74 unsigned int links_succeeded,
146 unsigned int links_failed) 75 unsigned int links_failed)
147{ 76{
148 /* Testbed is ready with peers running and connected in a pre-defined overlay
149 topology */
150
151 /* do something */
152 ctxt.ht_len = 10; 77 ctxt.ht_len = 10;
153
154 /* connect to a peers service */
155 dht_op = GNUNET_TESTBED_service_connect 78 dht_op = GNUNET_TESTBED_service_connect
156 (NULL, /* Closure for operation */ 79 (NULL, peers[0], "dht",
157 peers[0], /* The peer whose service to connect to */ 80 &service_connect_comp, NULL,
158 "dht", /* The name of the service */ 81 &dht_ca, &dht_da, &ctxt);
159 service_connect_comp, /* callback to call after a handle to service 82 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
160 is opened */
161 NULL, /* closure for the above callback */
162 dht_ca, /* callback to call with peer's configuration;
163 this should open the needed service connection */
164 dht_da, /* callback to be called when closing the
165 opened service connection */
166 &ctxt); /* closure for the above two callbacks */
167 shutdown_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
168 &shutdown_task, NULL);
169} 83}
170 84
171 85
@@ -176,15 +90,9 @@ main (int argc, char **argv)
176 90
177 result = GNUNET_SYSERR; 91 result = GNUNET_SYSERR;
178 ret = GNUNET_TESTBED_test_run 92 ret = GNUNET_TESTBED_test_run
179 ("awesome-test", /* test case name */ 93 ("awesome-test", "template.conf",
180 "template.conf", /* template configuration */ 94 NUM_PEERS, 0LL,
181 NUM_PEERS, /* number of peers to start */ 95 NULL, NULL, &test_master, NULL);
182 0LL, /* Event mask - set to 0 for no event notifications */
183 NULL, /* Controller event callback */
184 NULL, /* Closure for controller event callback */
185 &test_master, /* continuation callback to be called when testbed setup is
186 complete */
187 NULL); /* Closure for the test_master callback */
188 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) ) 96 if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
189 return 1; 97 return 1;
190 return 0; 98 return 0;