aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/gnunet-c-tutorial.tex434
1 files changed, 210 insertions, 224 deletions
diff --git a/doc/gnunet-c-tutorial.tex b/doc/gnunet-c-tutorial.tex
index 55b0ee310..84df14833 100644
--- a/doc/gnunet-c-tutorial.tex
+++ b/doc/gnunet-c-tutorial.tex
@@ -47,9 +47,10 @@ various operating systems and a detailed list of all dependencies can be found o
47 47
48 48
49\section{Installing GNUnet} 49\section{Installing GNUnet}
50
50First of all you have to install a current version of GNUnet. You can download a 51First of all you have to install a current version of GNUnet. You can download a
51tarball of a stable version from GNU FTP mirrors or obtain the latest development 52tarball of a stable version from GNU FTP mirrors or obtain the latest development
52version from our Subversion repository. 53version from our Git repository.
53 54
54Most of the time you should prefer to download the stable version since with the 55Most of the time you should prefer to download the stable version since with the
55latest development version things can be broken, functionality can be changed or tests 56latest development version things can be broken, functionality can be changed or tests
@@ -57,6 +58,7 @@ can fail. You should only use the development version if you know that you requi
57certain feature or a certain issue has been fixed since the last release. 58certain feature or a certain issue has been fixed since the last release.
58 59
59\subsection{Obtaining a stable version} 60\subsection{Obtaining a stable version}
61
60You can download the latest stable version of GNUnet from GNU FTP mirrors: 62You can download the latest stable version of GNUnet from GNU FTP mirrors:
61\begin{center} 63\begin{center}
62\url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz} 64\url{ftp://ftp.gnu.org/gnu/gnunet/gnunet-0.10.x.tar.gz}
@@ -80,23 +82,26 @@ $ mv gnunet-0.10.x gnunet # we will use the directory "gnunet" in the remainder
80$ cd gnunet 82$ cd gnunet
81\end{lstlisting} 83\end{lstlisting}
82 84
85
83\subsection{Installing Build Tool Chain and Dependencies} 86\subsection{Installing Build Tool Chain and Dependencies}
87
84To successfully compile GNUnet you need the tools to build GNUnet and the required dependencies. 88To successfully compile GNUnet you need the tools to build GNUnet and the required dependencies.
85Please have a look at \url{https://gnunet.org/dependencies} for a list of required dependencies 89Please have a look at \url{https://gnunet.org/dependencies} for a list of required dependencies
86and \url{https://gnunet.org/generic_installation} for specific instructions for your operating system. 90and \url{https://gnunet.org/generic_installation} for specific instructions for your operating system.
87 91
88Please check the notes at the end of the configure process about required dependencies. 92Please check the notes at the end of the configure process about required dependencies.
89 93
90For GNUNet bootstrapping support and the http(s) plugin you should install \texttt{libcurl}. 94For GNUnet bootstrapping support and the http(s) plugin you should install \texttt{libgnurl}.
91For the filesharing service you should install at least one of the datastore backends \texttt{mysql}, 95For the filesharing service you should install at least one of the datastore backends \texttt{mysql},
92\texttt{sqlite} or \texttt{postgresql}. 96\texttt{sqlite} or \texttt{postgresql}.
93 97
94\subsection{Obtaining the latest version from Subversion} 98\subsection{Obtaining the latest version from Git}
95The latest development version can obtained from our Subversion (\textit{svn}) repository. To obtain 99
96the code you need Subversion installed and checkout the repository using: 100The latest development version can obtained from our Git repository. To obtain
101the code you need Git installed and checkout the repository using:
97\lstset{language=bash} 102\lstset{language=bash}
98\begin{lstlisting} 103\begin{lstlisting}
99$ svn checkout https://gnunet.org/svn/gnunet 104$ git clone https://gnunet.org/git/gnunet
100\end{lstlisting} 105\end{lstlisting}
101After cloning the repository you have to execute 106After cloning the repository you have to execute
102\lstset{language=bash} 107\lstset{language=bash}
@@ -105,7 +110,8 @@ $ cd gnunet
105$ ./bootstrap 110$ ./bootstrap
106\end{lstlisting} 111\end{lstlisting}
107 112
108The remainder of this tutorial assumes that you have SVN HEAD checked out. 113The remainder of this tutorial assumes that you have Git Master checked out.
114
109 115
110\subsection{Compiling and Installing GNUnet} 116\subsection{Compiling and Installing GNUnet}
111 117
@@ -152,7 +158,7 @@ $ make install
152\end{lstlisting} 158\end{lstlisting}
153 159
154After installing GNUnet you have to add your GNUnet installation to your path 160After installing GNUnet you have to add your GNUnet installation to your path
155environmental variable. In addition you have to create the \lstinline|.gnunet| 161environmental variable. In addition you have to create the \lstinline|.config|
156directory in your home directory where GNUnet stores its data and an empty 162directory in your home directory where GNUnet stores its data and an empty
157GNUnet configuration file: 163GNUnet configuration file:
158 164
@@ -160,12 +166,13 @@ GNUnet configuration file:
160\begin{lstlisting} 166\begin{lstlisting}
161$ export PATH=$PATH:$PREFIX/bin 167$ export PATH=$PATH:$PREFIX/bin
162$ echo export PATH=$PREFIX/bin:\\$PATH >> ~/.bashrc 168$ echo export PATH=$PREFIX/bin:\\$PATH >> ~/.bashrc
163$ mkdir ~/.gnunet/ 169$ mkdir ~/.config/
164$ touch ~/.gnunet/gnunet.conf 170$ touch ~/.config/gnunet.conf
165\end{lstlisting} 171\end{lstlisting}
166% $ 172% $
167 173
168\subsection{Common Issues - Check your GNUnet installation} 174\subsection{Common Issues - Check your GNUnet installation}
175
169You should check your installation to ensure that installing GNUnet 176You should check your installation to ensure that installing GNUnet
170was successful up to this point. You should be able to access GNUnet's 177was successful up to this point. You should be able to access GNUnet's
171binaries and run GNUnet's self check. 178binaries and run GNUnet's self check.
@@ -189,7 +196,7 @@ to execute tests for all components. {\tt make check} traverses all subdirectori
189For every subdirectory you should get a message like this: 196For every subdirectory you should get a message like this:
190 197
191\begin{lstlisting} 198\begin{lstlisting}
192make[2]: Entering directory `/home/mwachs/gnunet/contrib' 199make[2]: Entering directory `/home/$USER/gnunet/contrib'
193PASS: test_gnunet_prefix 200PASS: test_gnunet_prefix
194============= 201=============
1951 test passed 2021 test passed
@@ -206,7 +213,9 @@ FAIL: test_program
206\end{lstlisting} 213\end{lstlisting}
207double check the steps performed in ~\ref{sub:install} 214double check the steps performed in ~\ref{sub:install}
208 215
216
209\section{Background: GNUnet Architecture} 217\section{Background: GNUnet Architecture}
218
210GNUnet is organized in layers and services. Each service is composed of a 219GNUnet is organized in layers and services. Each service is composed of a
211main service implementation and a client library for other programs to use 220main service implementation and a client library for other programs to use
212the service's functionality, described by an API. This approach is shown in 221the service's functionality, described by an API. This approach is shown in
@@ -244,9 +253,11 @@ client do not affect the service process or other clients. The service and the
244clients communicate via a message protocol to be defined and implemented by 253clients communicate via a message protocol to be defined and implemented by
245the programmer. 254the programmer.
246 255
256
247\section{First Steps with GNUnet} 257\section{First Steps with GNUnet}
248 258
249\subsection{Configure your peer} 259\subsection{Configure your peer}
260
250First 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. 261First 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.
251 262
252Since we want to start additional peers later, we need 263Since we want to start additional peers later, we need
@@ -267,6 +278,7 @@ GNUNET_HOME = ~/gnunet1/ # Use this directory to store GNUnet data
267SERVERS = # prevent bootstrapping 278SERVERS = # prevent bootstrapping
268\end{lstlisting} 279\end{lstlisting}
269 280
281
270\subsection{Start a peer} 282\subsection{Start a peer}
271Each GNUnet instance (called peer) has an identity (\textit{peer ID}) based on a 283Each GNUnet instance (called peer) has an identity (\textit{peer ID}) based on a
272cryptographic public private key pair. The peer ID is the printable hash of the 284cryptographic public private key pair. The peer ID is the printable hash of the
@@ -295,6 +307,7 @@ I am peer `0PA02UVRKQTS2C .. JL5Q78F6H0B1ACPV1CJI59MEQUMQCC5G'.
295 307
296 308
297\subsection{Monitor a peer} 309\subsection{Monitor a peer}
310
298In this section, we will monitor the behaviour of our peer's DHT service with respect to a 311In this section, we will monitor the behaviour of our peer's DHT service with respect to a
299specific key. First we will start GNUnet and then start the DHT service and use the DHT monitor tool 312specific key. First we will start GNUnet and then start the DHT service and use the DHT monitor tool
300to monitor the PUT and GET commands we issue ussing the \lstinline|gnunet-dht-put| and 313to monitor the PUT and GET commands we issue ussing the \lstinline|gnunet-dht-put| and
@@ -317,7 +330,10 @@ $ gnunet-statistics -c ~/peer1.conf # print statistics about current GNUnet sta
317$ gnunet-statistics -c ~/peer1.conf -s dht # print statistics about DHT service 330$ gnunet-statistics -c ~/peer1.conf -s dht # print statistics about DHT service
318\end{lstlisting} 331\end{lstlisting}
319% $ 332% $
333
334
320\subsection{Starting Two Peers by Hand} 335\subsection{Starting Two Peers by Hand}
336
321\subsubsection{Setup a second peer} 337\subsubsection{Setup a second peer}
322We will now start a second peer on your machine. 338We will now start a second peer on your machine.
323For the second peer, you will need to manually create a modified 339For the second peer, you will need to manually create a modified
@@ -364,6 +380,7 @@ as needed. Also, make sure the output is different from the {\tt
364error in the configuration). 380error in the configuration).
365 381
366\subsubsection{Start the second peer and connect the peers} 382\subsubsection{Start the second peer and connect the peers}
383
367Then, you can start a second peer using: 384Then, you can start a second peer using:
368\lstset{language=bash} 385\lstset{language=bash}
369\begin{lstlisting} 386\begin{lstlisting}
@@ -403,6 +420,7 @@ likely observe traffic and behaviors that are not explicitly controlled
403by you. 420by you.
404 421
405\subsubsection{How to connect manually} 422\subsubsection{How to connect manually}
423
406If you want to use the \texttt{peerinfo} tool to connect your peers, you should: 424If you want to use the \texttt{peerinfo} tool to connect your peers, you should:
407\begin{itemize} 425\begin{itemize}
408\itemsep0em 426\itemsep0em
@@ -447,8 +465,8 @@ With the testbed API, a sample test case can be structured as follows:
447% <lynX> Is there a way to pick a more readable font for this include? 465% <lynX> Is there a way to pick a more readable font for this include?
448\lstinputlisting[language=C]{testbed_test.c} 466\lstinputlisting[language=C]{testbed_test.c}
449The source code for the above listing can be found at 467The source code for the above listing can be found at
450\url{https://gnunet.org/svn/gnunet/doc/testbed_test.c} 468\url{https://gnunet.org/git/gnunet.git/tree/doc/testbed_test.c}
451or in the doc folder of your repository check-out. 469or in the {\tt doc/} folder of your repository check-out.
452After installing GNUnet, the above source code can be compiled as: 470After installing GNUnet, the above source code can be compiled as:
453\lstset{language=bash} 471\lstset{language=bash}
454\begin{lstlisting} 472\begin{lstlisting}
@@ -504,7 +522,9 @@ disconnect from the service with the provided service handle (\texttt{op\_result
504 Then use the DHT API to store and retrieve values in the 522 Then use the DHT API to store and retrieve values in the
505 network.} 523 network.}
506 524
525
507\section{Developing Applications} 526\section{Developing Applications}
527
508\subsection{gnunet-ext} 528\subsection{gnunet-ext}
509To develop a new peer-to-peer application or to extend GNUnet we provide 529To develop a new peer-to-peer application or to extend GNUnet we provide
510a template build system for writing GNUnet extensions in C. It can be 530a template build system for writing GNUnet extensions in C. It can be
@@ -512,7 +532,7 @@ obtained as follows:
512 532
513\lstset{language=bash} 533\lstset{language=bash}
514\begin{lstlisting} 534\begin{lstlisting}
515$ svn checkout https://gnunet.org/svn/gnunet-ext/ 535$ git clone https://gnunet.org/git/gnunet-ext
516$ cd gnunet-ext/ 536$ cd gnunet-ext/
517$ ./bootstrap 537$ ./bootstrap
518$ ./configure --prefix=$PREFIX --with-gnunet=$PREFIX 538$ ./configure --prefix=$PREFIX --with-gnunet=$PREFIX
@@ -678,15 +698,26 @@ with the service, a connection must be created:
678 698
679\lstset{language=c} 699\lstset{language=c}
680\begin{lstlisting} 700\begin{lstlisting}
681 struct GNUNET_CLIENT_Connection *client; 701 struct GNUNET_MQ_MessageHandlers handlers[] = {
682 client = GNUNET_CLIENT_connect ("service-name", cfg); 702 // ...
703 GNUNET_MQ_handler_end ()
704 };
705 struct GNUNET_MQ_Handle *mq;
706
707 mq = GNUNET_CLIENT_connect (cfg, "service-name", handlers, &error_cb, NULL);
683\end{lstlisting} 708\end{lstlisting}
684 709
685As a result a {\tt GNUNET\_CLIENT\_Connection} handle is returned 710As a result a {\tt GNUNET\_MQ\_Handle} is returned
686which has to used in later API calls related to this service. 711which can to used henceforth to transmit messages to
687The complete client API can be found in {\tt gnunet\_client\_lib.h} 712the service.
713The complete MQ API can be found in {\tt gnunet\_mq\_lib.h}.
714The {\tt hanlders} array in the example above is incomplete.
715Here is where you will define which messages you expect to
716receive from the service, and which functions handle them.
717The {\tt error_cb} is a function that is to be called whenever
718there are errors communicating with the service.
688 719
689\subsubsection{GNUnet Messages} 720\subsubsection{Sending messages}
690 721
691In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_MessageHeader} 722In GNUnet, messages are always sent beginning with a {\tt struct GNUNET\_MessageHeader}
692in big endian format. This header defines the size and the type of the 723in big endian format. This header defines the size and the type of the
@@ -712,16 +743,17 @@ struct GNUNET_MessageHeader
712\end{lstlisting} 743\end{lstlisting}
713 744
714Existing message types are defined in {\tt gnunet\_protocols.h}\\ 745Existing message types are defined in {\tt gnunet\_protocols.h}\\
715A common way to create a message is: 746A common way to create a message is with an envelope:
716 747
717\lstset{language=c} 748\lstset{language=c}
718\begin{lstlisting} 749\begin{lstlisting}
719struct GNUNET_MessageHeader *msg = 750struct GNUNET_MQ_Envelope *env;
720 GNUNET_malloc(payload_size + sizeof(struct GNUNET_MessageHeader)); 751struct GNUNET_MessageHeader *msg;
721msg->size = htons(payload_size + sizeof(struct GNUNET_MessageHeader)); 752
722msg->type = htons(GNUNET_MY_MESSAGE_TYPE); 753env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE);
723memcpy(&msg[1], &payload, payload_size); 754memcpy (&msg[1], &payload, payload_size);
724// use 'msg' 755/* Send message via message queue 'mq': */
756GNUNET_mq_send (mq, env);
725\end{lstlisting} 757\end{lstlisting}
726 758
727\exercise{Define a message struct that includes a 32-bit 759\exercise{Define a message struct that includes a 32-bit
@@ -729,52 +761,9 @@ unsigned integer in addition to the standard GNUnet MessageHeader.
729Add a C struct and define a fresh protocol number for your message. 761Add a C struct and define a fresh protocol number for your message.
730(Protocol numbers in gnunet-ext are defined in \lstinline|gnunet-ext/src/include/gnunet_protocols_ext.h|)} 762(Protocol numbers in gnunet-ext are defined in \lstinline|gnunet-ext/src/include/gnunet_protocols_ext.h|)}
731 763
764\exercise{Find out how you can determine the number of messages in a message queue.}
732 765
733\subsubsection{Sending Requests to the Service} 766\exercise{Find out how you can determine when a message you have queued was actually transmitted.}
734
735Any client-service protocol must start with the client sending the
736first message to the service, since services are only notified about
737(new) clients upon receiving a the first message.
738
739Clients can transmit messages to the service using the
740{\tt GNUNET\_CLIENT\_notify\_transmit\_ready} API:
741\lstset{language=c}
742\begin{lstlisting}
743static size_t
744transmit_cb (void *cls, size_t size, void *buf)
745{
746 // ...
747 if (NULL == buf) { /* handle error here */; return 0; }
748 GNUNET_assert (size >= msg_size);
749 memcpy (buf, my_msg, msg_size);
750 // ...
751 return msg_size;
752}
753
754// ...
755th = GNUNET_CLIENT_notify_transmit_ready (client,
756 msg_size,
757 timeout,
758 GNUNET_YES,
759 &transmit_cb, cls);
760// ...
761\end{lstlisting}
762
763The client-service protocoll calls {\tt GNUNET\_CLIENT\_notify\_transmit\_ready}
764to be notified when the client is ready to send data to the service.
765Besides other arguments, you have to pass the client returned
766from the {\tt connect} call, the message size and the callback function to
767call when the client is ready to send.
768
769Only a single transmission request can be queued per client at the
770same time using this API. The handle {\tt th} can be used to cancel
771the request if necessary (for example, during shutdown).
772
773When {\tt transmit\_cb} is called the message is copied in the buffer provided and
774the number of bytes copied into the buffer is returned. {\tt transmit\_cb}
775could also return 0 if for some reason no message
776could be constructed; this is not an error and the connection to the
777service will persist in this case.
778 767
779\exercise{Define a helper function to transmit a 32-bit 768\exercise{Define a helper function to transmit a 32-bit
780unsigned integer (as payload) to a service using some given client 769unsigned integer (as payload) to a service using some given client
@@ -783,42 +772,77 @@ handle.}
783 772
784\subsubsection{Receiving Replies from the Service} 773\subsubsection{Receiving Replies from the Service}
785 774
786Clients can receive messages from the service using the 775Clients can receive messages from the service using the handlers
787{\tt GNUNET\_CLIENT\_receive} API: 776specified in the {\tt handlers} array we specified when connecting
777to the service. Entries in the the array are usually created using
778one of two macros, depending on whether the message is fixed size
779or variable size. Variable size messages are managed using two
780callbacks, one to check that the message is well-formed, the other
781to actually process the message. Fixed size messages are fully
782checked by the MQ-logic, and thus only need to provide the handler
783to process the message. Note that the prefixes {\tt check_}
784and {\tt handle_} are mandatory.
788 785
789\lstset{language=c} 786\lstset{language=c}
790\begin{lstlisting} 787\begin{lstlisting}
791/** 788/**
792 * Function called with messages from stats service. 789 * Function called with MyMessage messages from service.
793 * 790 *
794 * @param cls closure 791 * @param cls closure
795 * @param msg message received, NULL on timeout or fatal error 792 * @param msg message received
796 */ 793 */
797static void 794static void
798receive_message (void *cls, const struct GNUNET_MessageHeader *msg) 795handle_fix (void *cls, const struct MyMessage *msg)
799{ 796{
800 struct MyArg *arg = cls; 797 // process 'msg'
798}
801 799
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
808check_var (void *cls, const struct MyVarMessage *msg)
809{
810 // check 'msg' is well-formed
811 return GNUNET_OK; /* suppose yes */
812}
813
814/**
815 * Function called with MyMessage messages from service.
816 *
817 * @param cls closure
818 * @param msg message received
819 */
820static void
821handle_var (void *cls, const struct MyVarMessage *msg)
822{
802 // process 'msg' 823 // process 'msg'
803} 824}
804 825
805// ... 826struct GNUNET_MQ_MessageHandler handlers[] = {
806 GNUNET_CLIENT_receive (client, 827 GNUNET_MQ_hd_fixed_size (fix,
807 &receive_message, 828 GNUNET_MESSAGE_TYPE_MY_FIX,
808 arg, 829 struct MyMessage,
809 timeout); 830 NULL),
810// ... 831 GNUNET_MQ_hd_fixed_size (var,
832 GNUNET_MESSAGE_TYPE_MY_VAR,
833 struct MyVarMessage,
834 NULL),
835
836 GNUNET_MQ_handler_end ()
837};
811\end{lstlisting} 838\end{lstlisting}
812 839
813It should be noted that this receive call only receives a single 840\exercise{Expand your helper function to receive a response message
814message. To receive additional messages, {\tt 841 (for example, containing just the {\tt struct GNUnet MessageHeader}
815 GNUNET\_CLIENT\_receive} must be called again. 842 without any payload). Upon receiving the service's response, you
843 should call a callback provided to your helper function's API.}
816 844
817\exercise{Expand your helper function to receive a 845\exercise{Figure out where you can pass values to the closures ({\tt cls}).}
818response message (for example, containing just the GNUnet MessageHeader
819without any payload). Upon receiving the service's response, you should
820call a callback provided to your helper function's API. You'll need to
821define a new 'struct' to hold your local context (``closure'').}
822 846
823 847
824\subsection{Writing a user interface} 848\subsection{Writing a user interface}
@@ -827,10 +851,10 @@ Given a client library, all it takes to access a service now is to
827combine calls to the client library with parsing command-line 851combine calls to the client library with parsing command-line
828options. 852options.
829 853
830\exercise{Call your client API from your {\tt run} method 854\exercise{Call your client API from your {\tt run()} method in your
831in your client application to send a request to the service. 855 client application to send a request to the service. For example,
832For example, send a 32-bit integer value based on a number given 856 send a 32-bit integer value based on a number given at the
833at the command-line to the service.} 857 command-line to the service.}
834 858
835 859
836 860
@@ -851,142 +875,103 @@ and configuration files.
851 875
852\subsection{Starting a Service} 876\subsection{Starting a Service}
853 877
854The key API definitions for starting services are: 878The key API definition for creating a service is the {\tt GNUNET\_SERVICE\_MAIN} macro:
855\lstset{language=C} 879\lstset{language=C}
856\begin{lstlisting} 880\begin{lstlisting}
857typedef void (*GNUNET_SERVICE_Main) (void *cls, 881GNUNET_SERVICE_MAIN
858 struct GNUNET_SERVER_Handle *server, 882("service-name",
859 const struct GNUNET_CONFIGURATION_Handle *cfg); 883 GNUNET_SERVICE_OPTION_NONE,
860int GNUNET_SERVICE_run (int argc, 884 &run,
861 char *const *argv, 885 &client_connect_cb,
862 const char *serviceName, 886 &client_disconnect_cb,
863 enum GNUNET_SERVICE_Options opt, 887 NULL,
864 GNUNET_SERVICE_Main task, 888 GNUNET_MQ_hd_fixed_size (...),
865 void *task_cls); 889 GNUNET_MQ_hd_var_size (...),
890 GNUNET_MQ_handler_end ());
866\end{lstlisting} 891\end{lstlisting}
867 892
868Here is a starting point for your main function for your service: 893In addition to the service name and flags, the macro takes three
894functions, typically called {\tt run}, {\tt client\_connect\_cb} and
895{\tt client\_disconnect\_cb} as well as an array of message handlers
896that will be called for incoming messages from clients.
897
898A minimal version of the three central service funtions would look
899like this:
869 900
870\lstset{language=c} 901\lstset{language=c}
871\begin{lstlisting} 902\begin{lstlisting}
872static void my_main (void *cls, 903/**
873 struct GNUNET_SERVER_Handle *server, 904 * Launch service.
874 const struct GNUNET_CONFIGURATION_Handle *cfg) 905 *
906 * @param cls closure
907 * @param c configuration to use
908 * @param service the initialized service
909 */
910static void
911run (void *cls,
912 const struct GNUNET_CONFIGURATION_Handle *c,
913 struct GNUNET_SERVICE_Handle *service)
875{ 914{
876 /* do work */
877} 915}
878 916
879int main (int argc, char *const*argv) 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 *
926client_connect_cb (void *cls,
927 struct GNUNET_SERVICE_Client *c,
928 struct GNUNET_MQ_Handle *mq)
880{ 929{
881 if (GNUNET_OK != 930 return c;
882 GNUNET_SERVICE_run (argc, argv, "my", 931}
883 GNUNET_SERVICE_OPTION_NONE, 932
884 &my_main, NULL); 933/**
885 return 1; 934 * Callback called when a client disconnected from the service
886 return 0; 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
941client_disconnect_cb (void *cls,
942 struct GNUNET_SERVICE_Client *c,
943 void *internal_cls)
944{
945 GNUNET_assert (c == internal_cls);
887} 946}
888\end{lstlisting} 947\end{lstlisting}
889 948
890\exercise{Write a stub service that processes no messages at all 949\exercise{Write a stub service that processes no messages at all
891in your code. Create a default configuration for it, integrate it 950 in your code. Create a default configuration for it, integrate it
892with the build system and start the service from {\tt 951 with the build system and start the service from {\tt
893 gnunet-service-arm} using {\tt gnunet-arm -i NAME}.} 952 gnunet-service-arm} using {\tt gnunet-arm -i NAME}.}
894 953
954\exercise{Figure out how to set the closure ({\tt cls}) for handlers
955 of a service.}
895 956
896\subsection{Receiving Requests from Clients} 957\exercise{Figure out how to send messages from the service back to the
897 958 client.}
898Inside of the {\tt my\_main} method, a service typically registers for
899the various message types from clients that it supports by providing
900a handler function, the message type itself and possibly a fixed
901message size (or 0 for variable-size messages):
902 959
903\lstset{language=c} 960Each handler function in the service {\bf must} eventually (possibly in some
904\begin{lstlisting} 961asynchronous continuation) call {\tt GNUNET\_SERVICE\_client\_continue()}.
905static void
906handle_set (void *cls,
907 struct GNUNET_SERVER_Client *client,
908 const struct GNUNET_MessageHeader *message)
909{
910 GNUNET_SERVER_receive_done (client, GNUNET_OK);
911}
912static void
913handle_get (void *cls,
914 struct GNUNET_SERVER_Client *client,
915 const struct GNUNET_MessageHeader *message)
916{
917 GNUNET_SERVER_receive_done (client, GNUNET_OK);
918}
919
920static void my_main (void *cls,
921 struct GNUNET_SERVER_Handle *server,
922 const struct GNUNET_CONFIGURATION_Handle *cfg)
923{
924 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
925 {&handle_set, NULL, GNUNET_MESSAGE_TYPE_MYNAME_SET, 0},
926 {&handle_get, NULL, GNUNET_MESSAGE_TYPE_MYNAME_GET, 0},
927 {NULL, NULL, 0, 0}
928 };
929 GNUNET_SERVER_add_handlers (server, handlers);
930 /* do more setup work */
931}
932\end{lstlisting}
933
934Each handler function {\bf must} eventually (possibly in some
935asynchronous continuation) call {\tt GNUNET\_SERVER\_receive\_done}.
936Only after this call additional messages from the same client may 962Only after this call additional messages from the same client may
937be processed. This way, the service can throttle processing messages 963be processed. This way, the service can throttle processing messages
938from the same client. By passing {\tt GNUNET\_SYSERR}, the service 964from the same client.
939can close the connection to the client, indicating an error.
940
941Services must check that client requests are well-formed and must not
942crash on protocol violations by the clients. Similarly, client
943libraries must check replies from servers and should gracefully report
944errors via their API.
945
946 965
947\exercise{Change the service to ``handle'' the message from your 966\exercise{Change the service to ``handle'' the message from your
948client (for now, by printing a message). What happens if you 967 client (for now, by printing a message). What happens if you
949forget to call {\tt GNUNET\_SERVER\_receive\_done}?} 968 forget to call {\tt GNUNET\_SERVICE\_client\_continue()}?}
950
951
952\subsection{Responding to Clients}
953
954Servers can send messages to clients using the
955{\tt GNUNET\_SERVER\_notify\_transmit\_ready} API:
956
957\lstset{language=c}
958\begin{lstlisting}
959static size_t
960transmit_cb (void *cls, size_t size, void *buf)
961{
962 // ...
963 if (NULL == buf) { handle_error(); return 0; }
964 GNUNET_assert (size >= msg_size);
965 memcpy (buf, my_msg, msg_size);
966 // ...
967 return msg_size;
968}
969 969
970// ...
971struct GNUNET_SERVER_TransmitHandle *th;
972th = GNUNET_SERVER_notify_transmit_ready (client,
973 msg_size,
974 timeout,
975 &transmit_cb, cls);
976// ...
977\end{lstlisting}
978
979Only a single transmission request can be queued per client
980at the same time using this API.
981Additional APIs for sending messages to clients can be found
982in the {\tt gnunet\_server\_lib.h} header.
983
984
985\exercise{Change the service respond to the request from your
986client. Make sure you handle malformed messages in both directions.}
987 970
988\section{Interacting directly with other Peers using the CORE Service} 971\section{Interacting directly with other Peers using the CORE Service}
989 972
973FIXME: This section still needs to be updated to the lastest API!
974
990One of the most important services in GNUnet is the \texttt{CORE} service 975One of the most important services in GNUnet is the \texttt{CORE} service
991managing connections between peers and handling encryption between peers. 976managing connections between peers and handling encryption between peers.
992 977
@@ -1241,7 +1226,9 @@ If the \lstinline|sync_first| flag is set to \lstinline|GNUNET_YES|, the API wil
1241disconnection until all store requests are received by the PEERSTORE service. Otherwise, 1226disconnection until all store requests are received by the PEERSTORE service. Otherwise,
1242it will disconnect immediately. 1227it will disconnect immediately.
1243 1228
1229
1244\section{Using the DHT} 1230\section{Using the DHT}
1231
1245The DHT allows to store data so other peers in the P2P network can 1232The DHT allows to store data so other peers in the P2P network can
1246access it and retrieve data stored by any peers in the network. 1233access it and retrieve data stored by any peers in the network.
1247This section will explain how to use the DHT. Of course, the first 1234This section will explain how to use the DHT. Of course, the first
@@ -1279,7 +1266,7 @@ message_sent_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1279 1266
1280struct GNUNET_DHT_PutHandle * 1267struct GNUNET_DHT_PutHandle *
1281GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, 1268GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle,
1282 const struct GNUNET_HashCode * key, 1269 const struct GNUNET_HashCode *key,
1283 uint32_t desired_replication_level, 1270 uint32_t desired_replication_level,
1284 enum GNUNET_DHT_RouteOption options, /* Route options, see next call */ 1271 enum GNUNET_DHT_RouteOption options, /* Route options, see next call */
1285 enum GNUNET_BLOCK_Type type, size_t size, const void *data, 1272 enum GNUNET_BLOCK_Type type, size_t size, const void *data,
@@ -1311,7 +1298,7 @@ path and on the GET path.
1311\begin{lstlisting} 1298\begin{lstlisting}
1312static void 1299static void
1313get_result_iterator (void *cls, struct GNUNET_TIME_Absolute expiration, 1300get_result_iterator (void *cls, struct GNUNET_TIME_Absolute expiration,
1314 const struct GNUNET_HashCode * key, 1301 const struct GNUNET_HashCode *key,
1315 const struct GNUNET_PeerIdentity *get_path, 1302 const struct GNUNET_PeerIdentity *get_path,
1316 unsigned int get_path_length, 1303 unsigned int get_path_length,
1317 const struct GNUNET_PeerIdentity *put_path, 1304 const struct GNUNET_PeerIdentity *put_path,
@@ -1360,31 +1347,30 @@ requests. Note that depending on how {\tt evaluate} is called, only
1360some of the possible return values are valid. The specific meaning of 1347some of the possible return values are valid. The specific meaning of
1361the {\tt xquery} argument is application-specific. Applications that 1348the {\tt xquery} argument is application-specific. Applications that
1362do not use an extended query should check that the {\tt xquery\_size} 1349do not use an extended query should check that the {\tt xquery\_size}
1363is zero. The Bloom filter is typically used to filter duplicate 1350is zero. The block group is typically used to filter duplicate
1364replies. 1351replies.
1365 1352
1366\lstset{language=C} 1353\lstset{language=C}
1367\begin{lstlisting} 1354\begin{lstlisting}
1368static enum GNUNET_BLOCK_EvaluationResult 1355static enum GNUNET_BLOCK_EvaluationResult
1369block_plugin_SERVICE_evaluate (void *cls, 1356block_plugin_SERVICE_evaluate (void *cls,
1370 enum GNUNET_BLOCK_Type type, 1357 enum GNUNET_BLOCK_Type type,
1371 const GNUNET_HashCode * query, 1358 struct GNUNET_BlockGroup *bg,
1372 struct GNUNET_CONTAINER_BloomFilter **bf, 1359 const GNUNET_HashCode *query,
1373 int32_t bf_mutator, 1360 const void *xquery,
1374 const void *xquery, 1361 size_t xquery_size,
1375 size_t xquery_size, 1362 const void *reply_block,
1376 const void *reply_block, 1363 size_t reply_block_size)
1377 size_t reply_block_size)
1378{ 1364{
1379 /* Verify type, block and bloomfilter */ 1365 /* Verify type, block and bg */
1380} 1366}
1381\end{lstlisting} 1367\end{lstlisting}
1382 1368
1383Note that it is mandatory to detect duplicate replies in this 1369Note that it is mandatory to detect duplicate replies in this function
1384function and return the respective status code. Duplicate 1370and return the respective status code. Duplicate detection is
1385detection should be done by setting the respective bits in 1371typically done using the Bloom filter block group provided by {\tt
1386the Bloom filter {\tt bf}. Failure to do so may cause replies 1372 libgnunetblockgroup.so}. Failure to do so may cause replies to
1387to circle in the network. 1373circle in the network.
1388 1374
1389\subsubsection{Deriving a key from a reply} 1375\subsubsection{Deriving a key from a reply}
1390 1376
@@ -1400,7 +1386,7 @@ just fine with such blocks).
1400static int 1386static int
1401block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, 1387block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type,
1402 const void *block, size_t block_size, 1388 const void *block, size_t block_size,
1403 GNUNET_HashCode * key) 1389 struct GNUNET_HashCode *key)
1404{ 1390{
1405 /* Store the key in the key argument, return GNUNET_OK on success. */ 1391 /* Store the key in the key argument, return GNUNET_OK on success. */
1406} 1392}
@@ -1426,7 +1412,7 @@ libgnunet_plugin_block_SERVICE_init (void *cls)
1426 }; 1412 };
1427 struct GNUNET_BLOCK_PluginFunctions *api; 1413 struct GNUNET_BLOCK_PluginFunctions *api;
1428 1414
1429 api = GNUNET_malloc (sizeof (struct GNUNET_BLOCK_PluginFunctions)); 1415 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
1430 api->evaluate = &block_plugin_SERICE_evaluate; 1416 api->evaluate = &block_plugin_SERICE_evaluate;
1431 api->get_key = &block_plugin_SERVICE_get_key; 1417 api->get_key = &block_plugin_SERVICE_get_key;
1432 api->types = types; 1418 api->types = types;