aboutsummaryrefslogtreecommitdiff
path: root/doc/documentation/gnunet-c-tutorial.texi
diff options
context:
space:
mode:
Diffstat (limited to 'doc/documentation/gnunet-c-tutorial.texi')
-rw-r--r--doc/documentation/gnunet-c-tutorial.texi1520
1 files changed, 1520 insertions, 0 deletions
diff --git a/doc/documentation/gnunet-c-tutorial.texi b/doc/documentation/gnunet-c-tutorial.texi
new file mode 100644
index 000000000..aca40d2ef
--- /dev/null
+++ b/doc/documentation/gnunet-c-tutorial.texi
@@ -0,0 +1,1520 @@
1\input texinfo
2@c %**start of header
3@setfilename gnunet-c-tutorial.info
4@documentencoding UTF-8
5@settitle GNUnet C Tutorial
6@exampleindent 2
7@c %**end of header
8
9@c including 'version.texi' makes makeinfo throw errors.
10@include version2.texi
11
12@copying
13Copyright @copyright{} 2001-2017 GNUnet e.V.
14
15Permission is granted to copy, distribute and/or modify this document
16under the terms of the GNU Free Documentation License, Version 1.3 or
17any later version published by the Free Software Foundation; with no
18Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
19copy of the license is included in the section entitled ``GNU Free
20Documentation License''.
21
22A copy of the license is also available from the Free Software
23Foundation Web site at @url{http://www.gnu.org/licenses/fdl.html}.
24
25Alternately, this document is also available under the General
26Public License, version 3 or later, as published by the Free Software
27Foundation. A copy of the license is included in the section entitled
28``GNU General Public License''.
29
30A copy of the license is also available from the Free Software
31Foundation Web site at @url{http://www.gnu.org/licenses/gpl.html}.
32@end copying
33
34@dircategory Tutorial
35@direntry
36* GNUnet-C-Tutorial: (gnunet-c-tutorial). C Tutorial for GNunet
37@end direntry
38
39
40@titlepage
41@title GNUnet C Tutorial
42@subtitle A Tutorial for GNUnet @value{VERSION} (C version)
43@author The GNUnet Developers
44
45@page
46@vskip 0pt plus 1filll
47
48@insertcopying
49@end titlepage
50
51@contents
52
53@c **** TODO
54@c 1. Update content?
55@c 2. Either reference main documentation or
56@c 3. Merge this into main documentation
57
58@node Top
59@top Introduction
60
61This tutorials explains how to install GNUnet on a
62GNU/Linux system and gives an introduction on how
63GNUnet can be used to develop a Peer-to-Peer application.
64Detailed installation instructions for
65various operating systems and a detailed list of all
66dependencies can be found on our website at
67@uref{https://gnunet.org/installation} and in our
68Reference Documentation (GNUnet Handbook).
69
70Please read this tutorial carefully since every single step is
71important and do not hesitate to contact the GNUnet team if you have
72any questions or problems! Check here how to contact the GNUnet
73team: @uref{https://gnunet.org/contact_information}
74
75@menu
76
77* Installing GNUnet:: Installing GNUnet
78* Introduction to GNUnet Architecture:: Introduction to GNUnet Architecture
79* First Steps with GNUnet:: First Steps with GNUnet
80* Developing Applications:: Developing Applications
81
82@detailmenu
83 --- The Detailed Node Listing ---
84
85Installing GNUnet
86
87* Obtaining a stable version::
88* Installing Build Tool Chain and Dependencies::
89* Obtaining the latest version from Git::
90* Compiling and Installing GNUnet::
91* Common Issues - Check your GNUnet installation::
92
93Introduction to GNUnet Architecture
94
95First Steps with GNUnet
96
97* Configure your peer::
98* Start a peer::
99* Monitor a peer::
100* Starting Two Peers by Hand::
101* Starting Peers Using the Testbed Service::
102
103Developing Applications
104
105* gnunet-ext::
106* Adapting the Template::
107* Writing a Client Application::
108* Writing a Service::
109* Interacting directly with other Peers using the CORE Service::
110* Storing peer-specific data using the PEERSTORE service::
111* Using the DHT::
112* Debugging with gnunet-arm::
113
114@end detailmenu
115@end menu
116
117@node Installing GNUnet
118@chapter Installing GNUnet
119
120First of all you have to install a current version of GNUnet.
121You can download a tarball of a stable version from GNU FTP mirrors
122or obtain the latest development version from our Git repository.
123
124Most of the time you should prefer to download the stable version
125since with the latest development version things can be broken,
126functionality can be changed or tests can fail. You should only use
127the development version if you know that you require a certain
128feature or a certain issue has been fixed since the last release.
129
130@menu
131* Obtaining a stable version::
132* Installing Build Tool Chain and Dependencies::
133* Obtaining the latest version from Git::
134* Compiling and Installing GNUnet::
135* Common Issues - Check your GNUnet installation::
136@end menu
137
138@node Obtaining a stable version
139@section Obtaining a stable version
140
141Download the tarball from
142@indicateurl{https://ftp.gnu.org/gnu/gnunet/gnunet-@value{VERSION}.tar.gz}.
143
144Make sure to download the associated @file{.sig} file and to verify the
145authenticity of the tarball against it, like this:
146
147@example
148$ wget https://ftp.gnu.org/gnu/gnunet/gnunet-@value{VERSION}.tar.gz.sig
149$ gpg --verify-files gnunet-@value{VERSION}.tar.gz.sig
150@end example
151
152@noindent
153If this command fails because you do not have the required public key,
154then you need to run this command to import it:
155
156@example
157$ gpg --keyserver keys.gnupg.net --recv-keys 48426C7E
158@end example
159
160@noindent
161and rerun the @code{gpg --verify-files} command.
162
163Now you can extract the tarball and rename the resulting
164directory to @i{gnunet} which we will be using in the
165remainder of this document.
166
167@example
168$ tar xvzf gnunet-@value{VERSION}.tar.gz
169$ mv gnunet-@value{VERSION} gnunet
170$ cd gnunet
171@end example
172
173@noindent
174However, please note that stable versions can be very outdated.
175As a developer you are @b{strongly} encouraged to use the version
176from @uref{https://gnunet.org/git/, git}.
177
178@node Installing Build Tool Chain and Dependencies
179@section Installing Build Tool Chain and Dependencies
180
181To successfully compile GNUnet you need the tools to build GNUnet and
182the required dependencies. Please have a look at
183@uref{https://gnunet.org/dependencies} for a list of required dependencies
184and @uref{https://gnunet.org/generic_installation} for specific
185instructions for your operating system. Please check the notes at
186the end of the configure process about required dependencies.
187
188For GNUnet bootstrapping support and the http(s) plugin you should
189install @uref{https://gnunet.org/gnurl, libgnurl}.
190For the filesharing service you should install at least one of the
191datastore backends. MySQL, SQlite and PostgreSQL are supported.
192
193@node Obtaining the latest version from Git
194@section Obtaining the latest version from Git
195
196The latest development version can obtained from our Git repository.
197To obtain the code you need Git installed and checkout the repository
198using:
199
200@example
201$ git clone https://gnunet.org/git/gnunet
202@end example
203
204@noindent
205After cloning the repository you have to execute the @file{bootstrap}
206script in the directory:
207
208@example
209$ cd gnunet ; ./bootstrap
210@end example
211
212@noindent
213The remainder of this tutorial assumes that you have the Git branch
214``master'' checked out.
215
216@node Compiling and Installing GNUnet
217@section Compiling and Installing GNUnet
218
219First, you need to install at least libgnupgerror 1.27 and
220libgcrypt 1.7.6.
221
222@example
223$ export GNUPGFTP="https://www.gnupg.org/ftp/gcrypt"
224$ wget $GNUPGFTP/libgpg-error/libgpg-error-1.27.tar.bz2
225$ tar xf libgpg-error-1.27.tar.bz2
226$ cd libgpg-error-1.27
227$ ./configure
228$ sudo make install
229$ cd ..
230@end example
231
232@example
233$ export GNUPGFTP="https://www.gnupg.org/ftp/gcrypt"
234$ wget $GNUPGFTP/libgcrypt/libgcrypt-1.7.6.tar.bz2
235$ tar xf libgcrypt-1.7.6.tar.bz2
236$ cd libgcrypt-1.7.6
237$ ./configure
238$ sudo make install
239$ cd ..
240@end example
241
242@menu
243* Installation::
244@end menu
245
246@node Installation
247@subsection Installation
248Assuming all dependencies are installed, the following commands will
249compile and install GNUnet in your home directory. You can specify the
250directory where GNUnet will be installed by changing the
251@code{--prefix} value when calling @command{./configure}. If
252you do not specifiy a prefix, GNUnet is installed in the directory
253@file{/usr/local}. When developing new applications you may want
254to enable verbose logging by adding @code{--enable-logging=verbose}:
255
256@example
257$ ./configure --prefix=$PREFIX --enable-logging
258$ make
259$ make install
260@end example
261
262@noindent
263After installing GNUnet you have to add your GNUnet installation
264to your path environmental variable. In addition you have to
265create the @file{.config} directory in your home directory
266(unless it already exists) where GNUnet stores its data and an
267empty GNUnet configuration file:
268
269@example
270$ export PATH=$PATH:$PREFIX/bin
271$ echo export PATH=$PREFIX/bin:\\$PATH >> ~/.bashrc
272$ mkdir ~/.config/
273$ touch ~/.config/gnunet.conf
274@end example
275
276@node Common Issues - Check your GNUnet installation
277@section Common Issues - Check your GNUnet installation
278
279You should check your installation to ensure that installing GNUnet
280was successful up to this point. You should be able to access GNUnet's
281binaries and run GNUnet's self check.
282
283@example
284$ which gnunet-arm
285@end example
286
287@noindent
288should return $PREFIX/bin/gnunet-arm. It should be located in your
289GNUnet installation and the output should not be empty.
290If you see an output like:
291
292@example
293$ which gnunet-arm
294@end example
295
296@noindent
297check your PATH variable to ensure GNUnet's @file{bin} directory is
298included.
299
300GNUnet provides tests for all of its subcomponents. Run
301
302@example
303$ make check
304@end example
305
306@noindent
307to execute tests for all components. @command{make check} traverses all
308subdirectories in @file{src}. For every subdirectory you should
309get a message like this:
310
311@example
312make[2]: Entering directory `/home/$USER/gnunet/contrib'
313PASS: test_gnunet_prefix
314=============
3151 test passed
316=============
317@end example
318
319@node Introduction to GNUnet Architecture
320@chapter Introduction to GNUnet Architecture
321
322GNUnet is organized in layers and services. Each service is composed of a
323main service implementation and a client library for other programs to use
324the service's functionality, described by an API.
325@c This approach is shown in
326@c FIXME: enable this once the commented block below works:
327@c figure~\ref fig:service.
328Some services provide an additional command line tool to enable the user
329to interact with the service.
330
331Very often it is other GNUnet services that will use these APIs to build
332the higher layers of GNUnet on top of the lower ones. Each layer expands
333or extends the functionality of the service below (for instance, to build
334a mesh on top of a DHT).
335@c FXIME: See comment above.
336@c See figure ~\ref fig:interaction for an illustration of this approach.
337
338@c ** @image filename[, width[, height[, alttext[, extension]]]]
339@c FIXME: Texlive (?) 20112 makes the assumption that this means
340@c 'images/OBJECTNAME.txt' but later versions of it (2017) use this
341@c syntax as described below.
342@c TODO: Checkout the makedoc script Guile uses.
343
344@c FIXME!!!
345@c @image{images/gnunet-tutorial-service,,5in,Service with API and network protocol,.png}
346@c @image{images/gnunet-tutorial-system,,5in,The layered system architecture of GNUnet,.png}
347
348@c \begin{figure}[!h]
349@c \begin{center}
350@c % \begin{subfigure}
351@c \begin{subfigure}[b]{0.3\textwidth}
352@c \centering
353@c \includegraphics[width=\textwidth]{figs/Service.pdf}
354@c \caption{Service with API and network protocol}
355@c \label{fig:service}
356@c \end{subfigure}
357@c ~~~~~~~~~~
358@c \begin{subfigure}[b]{0.3\textwidth}
359@c \centering
360@c \includegraphics[width=\textwidth]{figs/System.pdf}
361@c \caption{Service interaction}
362@c \label{fig:interaction}
363@c \end{subfigure}
364@c \end{center}
365@c \caption{GNUnet's layered system architecture}
366@c \end{figure}
367
368The main service implementation runs as a standalone process in the
369operating system and the client code runs as part of the client program,
370so crashes of a client do not affect the service process or other clients.
371The service and the clients communicate via a message protocol to be
372defined and implemented by the programmer.
373
374@node First Steps with GNUnet
375@chapter First Steps with GNUnet
376
377@menu
378* Configure your peer::
379* Start a peer::
380* Monitor a peer::
381* Starting Two Peers by Hand::
382* Starting Peers Using the Testbed Service::
383@end menu
384
385@node Configure your peer
386@section Configure your peer
387
388First of all we need to configure your peer. Each peer is started with
389a configuration containing settings for GNUnet itself and its services.
390This configuration is based on the default configuration shipped with
391GNUnet and can be modified. The default configuration is located in the
392@file{$PREFIX/share/gnunet/config.d} directory. When starting a peer, you
393can specify a customized configuration using the the @command{-c} command
394line switch when starting the ARM service and all other services. When
395using a modified configuration the default values are loaded and only
396values specified in the configuration file will replace the default
397values.
398
399Since we want to start additional peers later, we need some modifications
400from the default configuration. We need to create a separate service
401home and a file containing our modifications for this peer:
402
403@example
404$ mkdir ~/gnunet1/
405$ touch peer1.conf
406@end example
407
408@noindent
409Now add the following lines to @file{peer1.conf} to use this directory.
410For simplified usage we want to prevent the peer to connect to the GNUnet
411network since this could lead to confusing output. This modifications
412will replace the default settings:
413
414@example
415[PATHS]
416# Use this directory to store GNUnet data
417GNUNET_HOME = ~/gnunet1/
418[hostlist]
419# prevent bootstrapping
420SERVERS =
421@end example
422
423@node Start a peer
424@section Start a peer
425Each GNUnet instance (called peer) has an identity (peer ID) based on a
426cryptographic public private key pair. The peer ID is the printable hash
427of the public key.
428
429GNUnet services are controlled by a master service, the so called
430@dfn{Automatic Restart Manager} (ARM). ARM starts, stops and even
431restarts services automatically or on demand when a client connects.
432You interact with the ARM service using the @command{gnunet-arm} tool.
433GNUnet can then be started with @command{gnunet-arm -s} and stopped with
434@command{gnunet-arm -e}. An additional service not automatically started
435can be started using @command{gnunet-arm -i <service name>} and stopped
436using @command{gnunet-arm -k <servicename>}.
437
438Once you have started your peer, you can use many other GNUnet commands
439to interact with it. For example, you can run:
440
441@example
442$ gnunet-peerinfo -s
443@end example
444
445@noindent
446to obtain the public key of your peer.
447
448You should see an output containing the peer ID similar to:
449
450@example
451I am peer `0PA02UVRKQTS2C .. JL5Q78F6H0B1ACPV1CJI59MEQUMQCC5G'.
452@end example
453
454@node Monitor a peer
455@section Monitor a peer
456
457In this section, we will monitor the behaviour of our peer's DHT
458service with respect to a specific key. First we will start
459GNUnet and then start the DHT service and use the DHT monitor tool
460to monitor the PUT and GET commands we issue ussing the
461@command{gnunet-dht-put} and @command{gnunet-dht-get} commands.
462Using the ``monitor'' line given below, you can observe the behavior
463of your own peer's DHT with respect to the specified KEY:
464
465@example
466# start gnunet with all default services:
467$ gnunet-arm -c ~/peer1.conf -s
468# start DHT service:
469$ gnunet-arm -c ~/peer1.conf -i dht
470$ cd ~/gnunet/src/dht;
471$ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY
472@end example
473
474@noindent
475Now open a separate terminal and change again to
476the @file{gnunet/src/dht} directory:
477
478@example
479$ cd ~/gnunet/src/dht
480# put VALUE under KEY in the DHT:
481$ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE
482# get key KEY from the DHT:
483$ ./gnunet/src/dht/gnunet-dht-get -c ~/peer1.conf -k KEY
484# print statistics about current GNUnet state:
485$ gnunet-statistics -c ~/peer1.conf
486# print statistics about DHT service:
487$ gnunet-statistics -c ~/peer1.conf -s dht
488@end example
489
490@node Starting Two Peers by Hand
491@section Starting Two Peers by Hand
492
493This section describes how to start two peers on the same machine by hand.
494The process is rather painful, but the description is somewhat
495instructive. In practice, you might prefer the automated method
496(@pxref{Starting Peers Using the Testbed Service}).
497
498@menu
499* Setup a second peer::
500* Start the second peer and connect the peers::
501* How to connect manually::
502@end menu
503
504@node Setup a second peer
505@subsection Setup a second peer
506We will now start a second peer on your machine.
507For the second peer, you will need to manually create a modified
508configuration file to avoid conflicts with ports and directories.
509A peers configuration file is by default located
510in @file{~/.gnunet/gnunet.conf}. This file is typically very short
511or even empty as only the differences to the defaults need to be
512specified. The defaults are located in many files in the
513@file{$PREFIX/share/gnunet/config.d} directory.
514
515To configure the second peer, use the files
516@file{$PREFIX/share/gnunet/config.d} as a template for your main
517configuration file:
518
519@example
520$ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf
521@end example
522
523@noindent
524Now you have to edit @file{peer2.conf} and change:
525
526@itemize
527@item @code{GNUNET\_TEST\_HOME} under @code{PATHS}
528@item Every (uncommented) value for ``@code{PORT}'' (add 10000) in any
529section (the option may be commented out if @code{PORT} is
530prefixed by "\#", in this case, UNIX domain sockets are used
531and the PORT option does not need to be touched)
532@item Every value for ``@code{UNIXPATH}'' in any section
533(e.g. by adding a "-p2" suffix)
534@end itemize
535
536to a fresh, unique value. Make sure that the PORT numbers stay
537below 65536. From now on, whenever you interact with the second peer,
538you need to specify @command{-c peer2.conf} as an additional
539command line argument.
540
541Now, generate the 2nd peer's private key:
542
543@example
544$ gnunet-peerinfo -s -c peer2.conf
545@end example
546
547@noindent
548This may take a while, generate entropy using your keyboard or mouse
549as needed. Also, make sure the output is different from the
550gnunet-peerinfo output for the first peer (otherwise you made an
551error in the configuration).
552
553@node Start the second peer and connect the peers
554@subsection Start the second peer and connect the peers
555
556Then, you can start a second peer using:
557
558@example
559$ gnunet-arm -c peer2.conf -s
560$ gnunet-arm -c peer2.conf -i dht
561$ ~/gnunet/src/dht/gnunet-dht-put -c peer2.conf -k KEY -d VALUE
562$ ~/gnunet/src/dht/gnunet-dht-get -c peer2.conf -k KEY
563@end example
564
565If you want the two peers to connect, you have multiple options:
566
567@itemize
568@item UDP neighbour discovery (automatic)
569@item Setup a bootstrap server
570@item Connect manually
571@end itemize
572
573To setup peer 1 as bootstrapping server change the configuration of
574the first one to be a hostlist server by adding the following lines to
575@file{peer1.conf} to enable bootstrapping server:
576
577@example
578[hostlist]
579OPTIONS = -p
580@end example
581
582@noindent
583Then change @file{peer2.conf} and replace the ``@code{SERVERS}''
584line in the ``@code{[hostlist]}'' section with
585``@code{http://localhost:8080/}''. Restart both peers using:
586
587@example
588# stop first peer
589$ gnunet-arm -c peer1.conf -e
590# start first peer
591$ gnunet-arm -c peer1.conf -s
592# start second peer
593$ gnunet-arm -c peer2.conf -s
594@end example
595
596@noindent
597Note that if you start your peers without changing these settings, they
598will use the ``global'' hostlist servers of the GNUnet P2P network and
599likely connect to those peers. At that point, debugging might become
600tricky as you're going to be connected to many more peers and would
601likely observe traffic and behaviors that are not explicitly controlled
602by you.
603
604@node How to connect manually
605@subsection How to connect manually
606
607If you want to use the @code{peerinfo} tool to connect your
608peers, you should:
609
610@itemize
611@item Set @code{FORCESTART = NO} in section @code{hostlist}
612(to not connect to the global GNUnet)
613@item Start both peers running @command{gnunet-arm -c peer1.conf -s}
614and @command{gnunet-arm -c peer2.conf -s}
615@item Get @code{HELLO} message of the first peer running
616@command{gnunet-peerinfo -c peer1.conf -g}
617@item Give the output to the second peer by running
618@command{gnunet-peerinfo -c peer2.conf -p '<output>'}
619@end itemize
620
621Check that they are connected using @command{gnunet-core -c peer1.conf},
622which should give you the other peer's peer identity:
623
624@example
625$ gnunet-core -c peer1.conf
626Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG'
627@end example
628
629@node Starting Peers Using the Testbed Service
630@section Starting Peers Using the Testbed Service
631@c \label{sec:testbed}
632
633GNUnet's testbed service is used for testing scenarios where
634a number of peers are to be started. The testbed can manage peers
635on a single host or on multiple hosts in a distributed fashion.
636On a single affordable computer, it should be possible to run
637around tens of peers without drastically increasing the load on the
638system.
639
640The testbed service can be access through its API
641@file{include/gnunet\_testbed\_service.h}. The API provides many
642routines for managing a group of peers. It also provides a helper
643function @code{GNUNET\_TESTBED\_test\_run()} to quickly setup a
644minimalistic testing environment on a single host.
645
646This function takes a configuration file which will be used as a
647template configuration for the peers. The testbed takes care of
648modifying relevant options in the peers' configuration such as
649@code{SERVICEHOME}, @code{PORT}, @code{UNIXPATH} to unique values
650so that peers run without running into conflicts. It also checks
651and assigns the ports in configurations only if they are free.
652
653Additionally, the testbed service also reads its options from the
654same configuration file. Various available options and details
655about them can be found in the testbed default configuration file
656@file{src/testbed/testbed.conf}.
657
658With the testbed API, a sample test case can be structured as follows:
659
660@example
661@verbatiminclude testbed_test.c
662@end example
663
664@noindent
665The source code for the above listing can be found at
666@uref{https://gnunet.org/git/gnunet.git/tree/doc/
667documentation/testbed_test.c}
668or in the @file{doc/documentation/} folder of your repository check-out.
669After installing GNUnet, the above source code can be compiled as:
670
671@example
672$ export CPPFLAGS="-I/path/to/gnunet/headers"
673$ export LDFLAGS="-L/path/to/gnunet/libraries"
674$ gcc $CPPFLAGS $LDFLAGS -o testbed-test testbed_test.c \
675 -lgnunettestbed -lgnunetdht -lgnunetutil
676# Generate (empty) configuration
677$ touch template.conf
678# run it (press CTRL-C to stop)
679$ ./testbed-test
680@end example
681
682@noindent
683The @code{CPPFLAGS} and @code{LDFLAGS} are necessary if GNUnet
684is installed into a different directory other than @file{/usr/local}.
685
686All of testbed API's peer management functions treat management
687actions as operations and return operation handles. It is expected
688that the operations begin immediately, but they may get delayed (to
689balance out load on the system). The program using the API then has
690to take care of marking the operation as ``done'' so that its
691associated resources can be freed immediately and other waiting
692operations can be executed. Operations will be canceled if they are
693marked as ``done'' before their completion.
694
695An operation is treated as completed when it succeeds or fails.
696Completion of an operation is either conveyed as events through
697@i{controller event callback} or through respective operation
698completion callbacks. In functions which support completion
699notification through both controller event callback and operation
700completion callback, first the controller event callback will be
701called. If the operation is not marked as done in that callback
702or if the callback is given as NULL when creating the operation,
703the operation completion callback will be called. The API
704documentation shows which event are to be expected in the
705controller event notifications. It also documents any exceptional
706behaviour.
707
708Once the peers are started, test cases often need to connect
709some of the peers' services. Normally, opening a connect to
710a peer's service requires the peer's configuration. While using
711testbed, the testbed automatically generates per-peer configuration.
712Accessing those configurations directly through file system is
713discouraged as their locations are dynamically created and will be
714different among various runs of testbed. To make access to these
715configurations easy, testbed API provides the function
716@code{GNUNET\_TESTBED\_service\_connect()}. This function fetches
717the configuration of a given peer and calls the @i{Connect Adapter}.
718In the example code, it is the @code{dht\_ca}. A connect adapter is
719expected to open the connection to the needed service by using the
720provided configuration and return the created service connection handle.
721Successful connection to the needed service is signaled through
722@code{service\_connect\_comp\_cb}.
723
724A dual to connect adapter is the @i{Disconnect Adapter}. This callback
725is called after the connect adapter has been called when the operation
726from @code{GNUNET\_TESTBED\_service\_connect()} is marked as ``done''.
727It has to disconnect from the service with the provided service
728handle (@code{op\_result}).
729
730Exercise: Find out how many peers you can run on your system.
731
732Exercise: Find out how to create a 2D torus topology by changing the
733options in the configuration file.
734See @uref{https://gnunet.org/supported-topologies}, then use the
735DHT API to store and retrieve values in the network.
736
737@node Developing Applications
738@chapter Developing Applications
739
740@menu
741* gnunet-ext::
742* Adapting the Template::
743* Writing a Client Application::
744* Writing a Service::
745* Interacting directly with other Peers using the CORE Service::
746* Storing peer-specific data using the PEERSTORE service::
747* Using the DHT::
748* Debugging with gnunet-arm::
749@end menu
750
751@node gnunet-ext
752@section gnunet-ext
753To develop a new peer-to-peer application or to extend GNUnet we provide
754a template build system for writing GNUnet extensions in C. It can be
755obtained as follows:
756
757@example
758$ git clone https://gnunet.org/git/gnunet-ext
759$ cd gnunet-ext/
760$ ./bootstrap
761$ ./configure --prefix=$PREFIX --with-gnunet=$PREFIX
762$ make
763$ make install
764$ make check
765@end example
766
767@noindent
768The GNUnet ext template includes examples and a working buildsystem
769for a new GNUnet service. A common GNUnet service consists of the
770following parts which will be discussed in detail in the remainder
771of this document. The functionality of a GNUnet service is implemented in:
772
773@itemize
774@item the GNUnet service (gnunet-ext/src/ext/gnunet-service-ext.c)
775@item the client API (gnunet-ext/src/ext/ext_api.c)
776@item the client application using the service API
777(gnunet-ext/src/ext/gnunet-ext.c)
778@end itemize
779
780The interfaces for these entities are defined in:
781
782@itemize
783@item client API interface (gnunet-ext/src/ext/ext.h)
784@item the service interface (gnunet-ext/src/include/gnunet_service_SERVICE.h)
785@item the P2P protocol (gnunet-ext/src/include/gnunet_protocols_ext.h)
786@end itemize
787
788
789In addition the ext systems provides:
790
791@itemize
792@item a test testing the API (gnunet-ext/src/ext/test_ext_api.c)
793@item a configuration template for the service
794(gnunet-ext/src/ext/ext.conf.in)
795@end itemize
796
797@node Adapting the Template
798@section Adapting the Template
799
800The first step for writing any extension with a new service is to
801ensure that the @file{ext.conf.in} file contains entries for the
802@code{UNIXPATH}, @code{PORT} and @code{BINARY} for the service in a
803section named after the service.
804
805If you want to adapt the template rename the @file{ext.conf.in} to
806match your services name, you have to modify the @code{AC\_OUTPUT}
807section in @file{configure.ac} in the @file{gnunet-ext} root.
808
809@node Writing a Client Application
810@section Writing a Client Application
811
812When writing any client application (for example, a command-line
813tool), the basic structure is to start with the
814@code{GNUNET\_PROGRAM\_run} function. This function will parse
815command-line options, setup the scheduler and then invoke the
816@code{run} function (with the remaining non-option arguments)
817and a handle to the parsed configuration (and the configuration
818file name that was used, which is typically not needed):
819
820@example
821@verbatiminclude tutorial-examples/001.c
822@end example
823
824@menu
825* Handling command-line options::
826* Writing a Client Library::
827* Writing a user interface::
828@end menu
829
830@node Handling command-line options
831@subsection Handling command-line options
832
833Options can then be added easily by adding global variables and
834expanding the @code{options} array. For example, the following would
835add a string-option and a binary flag (defaulting to @code{NULL} and
836@code{GNUNET\_NO} respectively):
837
838@example
839@verbatiminclude tutorial-examples/002.c
840@end example
841
842Issues such as displaying some helpful text describing options using
843the @code{--help} argument and error handling are taken care of when
844using this approach. Other @code{GNUNET\_GETOPT\_}-functions can be used
845to obtain integer value options, increment counters, etc. You can
846even write custom option parsers for special circumstances not covered
847by the available handlers. To check if an argument was specified by the
848user you initialize the variable with a specific value (e.g. NULL for
849a string and GNUNET\_SYSERR for a integer) and check after parsing
850happened if the values were modified.
851
852Inside the @code{run} method, the program would perform the
853application-specific logic, which typically involves initializing and
854using some client library to interact with the service. The client
855library is supposed to implement the IPC whereas the service provides
856more persistent P2P functions.
857
858Exercise: Add a few command-line options and print them inside
859of @code{run}. What happens if the user gives invalid arguments?
860
861@node Writing a Client Library
862@subsection Writing a Client Library
863
864The first and most important step in writing a client library is to
865decide on an API for the library. Typical API calls include
866connecting to the service, performing application-specific requests
867and cleaning up. Many examples for such service APIs can be found
868in the @file{gnunet/src/include/gnunet\_*\_service.h} files.
869
870Then, a client-service protocol needs to be designed. This typically
871involves defining various message formats in a header that will be
872included by both the service and the client library (but is otherwise
873not shared and hence located within the service's directory and not
874installed by @command{make install}). Each message must start with a
875@code{struct GNUNET\_MessageHeader} and must be shorter than 64k. By
876convention, all fields in IPC (and P2P) messages must be in big-endian
877format (and thus should be read using @code{ntohl} and similar
878functions and written using @code{htonl} and similar functions).
879Unique message types must be defined for each message struct in the
880@file{gnunet\_protocols.h} header (or an extension-specific include
881file).
882
883@menu
884* Connecting to the Service::
885* Sending messages::
886* Receiving Replies from the Service::
887@end menu
888
889@node Connecting to the Service
890@subsubsection Connecting to the Service
891
892Before a client library can implement the application-specific protocol
893with the service, a connection must be created:
894
895@example
896@verbatiminclude tutorial-examples/003.c
897@end example
898
899@noindent
900As a result a @code{GNUNET\_MQ\_Handle} is returned
901which can to used henceforth to transmit messages to the service.
902The complete MQ API can be found in @file{gnunet\_mq\_lib.h}.
903The @code{hanlders} array in the example above is incomplete.
904Here is where you will define which messages you expect to
905receive from the service, and which functions handle them.
906The @code{error\_cb} is a function that is to be called whenever
907there are errors communicating with the service.
908
909@node Sending messages
910@subsubsection Sending messages
911
912In GNUnet, messages are always sent beginning with a
913@code{struct GNUNET\_MessageHeader} in big endian format.
914This header defines the size and the type of the
915message, the payload follows after this header.
916
917@example
918@verbatiminclude tutorial-examples/004.c
919@end example
920
921@noindent
922Existing message types are defined in @file{gnunet\_protocols.h}.
923A common way to create a message is with an envelope:
924
925@example
926@verbatiminclude tutorial-examples/005.c
927@end example
928
929@noindent
930Exercise: Define a message struct that includes a 32-bit
931unsigned integer in addition to the standard GNUnet MessageHeader.
932Add a C struct and define a fresh protocol number for your message.
933Protocol numbers in gnunet-ext are defined
934in @file{gnunet-ext/src/include/gnunet_protocols_ext.h}
935
936Exercise: Find out how you can determine the number of messages
937in a message queue.
938
939Exercise: Find out how you can determine when a message you
940have queued was actually transmitted.
941
942Exercise: Define a helper function to transmit a 32-bit
943unsigned integer (as payload) to a service using some given client
944handle.
945
946@node Receiving Replies from the Service
947@subsubsection Receiving Replies from the Service
948
949Clients can receive messages from the service using the handlers
950specified in the @code{handlers} array we specified when connecting
951to the service. Entries in the the array are usually created using
952one of two macros, depending on whether the message is fixed size
953or variable size. Variable size messages are managed using two
954callbacks, one to check that the message is well-formed, the other
955to actually process the message. Fixed size messages are fully
956checked by the MQ-logic, and thus only need to provide the handler
957to process the message. Note that the prefixes @code{check\_}
958and @code{handle\_} are mandatory.
959
960@example
961@verbatiminclude tutorial-examples/006.c
962@end example
963
964@noindent
965Exercise: Expand your helper function to receive a response message
966(for example, containing just the @code{struct GNUnet MessageHeader}
967without any payload). Upon receiving the service's response, you
968should call a callback provided to your helper function's API.
969
970Exercise: Figure out where you can pass values to the
971closures (@code{cls}).
972
973@node Writing a user interface
974@subsection Writing a user interface
975
976Given a client library, all it takes to access a service now is to
977combine calls to the client library with parsing command-line
978options.
979
980Exercise: Call your client API from your @code{run()} method in your
981client application to send a request to the service. For example,
982send a 32-bit integer value based on a number given at the
983command-line to the service.
984
985@node Writing a Service
986@section Writing a Service
987
988Before you can test the client you've written so far, you'll
989need to also implement the corresponding service.
990
991@menu
992* Code Placement::
993* Starting a Service::
994@end menu
995
996@node Code Placement
997@subsection Code Placement
998
999New services are placed in their own subdirectory under
1000@file{gnunet/src}. This subdirectory should contain the API
1001implementation file @file{SERVICE\_api.c}, the description of
1002the client-service protocol @file{SERVICE.h} and P2P protocol
1003@file{SERVICE\_protocol.h}, the implementation of the service itself
1004@file{gnunet-service-SERVICE.h} and several files for tests,
1005including test code and configuration files.
1006
1007@node Starting a Service
1008@subsection Starting a Service
1009
1010The key API definition for creating a service is the
1011@code{GNUNET\_SERVICE\_MAIN} macro:
1012
1013@example
1014@verbatiminclude tutorial-examples/007.c
1015@end example
1016
1017@noindent
1018In addition to the service name and flags, the macro takes three
1019functions, typically called @code{run}, @code{client\_connect\_cb} and
1020@code{client\_disconnect\_cb} as well as an array of message handlers
1021that will be called for incoming messages from clients.
1022
1023A minimal version of the three central service funtions would look
1024like this:
1025
1026@example
1027@verbatiminclude tutorial-examples/008.c
1028@end example
1029
1030@noindent
1031Exercise: Write a stub service that processes no messages at all
1032in your code. Create a default configuration for it, integrate it
1033with the build system and start the service from
1034@command{gnunet-service-arm} using @command{gnunet-arm -i NAME}.
1035
1036Exercise: Figure out how to set the closure (@code{cls}) for handlers
1037of a service.
1038
1039Exercise: Figure out how to send messages from the service back to the
1040client.
1041
1042Each handler function in the service @b{must} eventually (possibly in some
1043asynchronous continuation) call
1044@code{GNUNET\_SERVICE\_client\_continue()}. Only after this call
1045additional messages from the same client may
1046be processed. This way, the service can throttle processing messages
1047from the same client.
1048
1049Exercise: Change the service to ``handle'' the message from your
1050client (for now, by printing a message). What happens if you
1051forget to call @code{GNUNET\_SERVICE\_client\_continue()}?
1052
1053@node Interacting directly with other Peers using the CORE Service
1054@section Interacting directly with other Peers using the CORE Service
1055
1056FIXME: This section still needs to be updated to the lastest API!
1057
1058One of the most important services in GNUnet is the @code{CORE} service
1059managing connections between peers and handling encryption between peers.
1060
1061One of the first things any service that extends the P2P protocol
1062typically does is connect to the @code{CORE} service using:
1063
1064@example
1065@verbatiminclude tutorial-examples/009.c
1066@end example
1067
1068@menu
1069* New P2P connections::
1070* Receiving P2P Messages::
1071* Sending P2P Messages::
1072* End of P2P connections::
1073@end menu
1074
1075@node New P2P connections
1076@subsection New P2P connections
1077
1078Before any traffic with a different peer can be exchanged, the peer must
1079be known to the service. This is notified by the @code{CORE}
1080@code{connects} callback, which communicates the identity of the new
1081peer to the service:
1082
1083@example
1084@verbatiminclude tutorial-examples/010.c
1085@end example
1086
1087@noindent
1088Note that whatever you return from @code{connects} is given as the
1089@i{cls} argument to the message handlers for messages from
1090the respective peer.
1091
1092Exercise: Create a service that connects to the @code{CORE}. Then
1093start (and connect) two peers and print a message once your connect
1094callback is invoked.
1095
1096@node Receiving P2P Messages
1097@subsection Receiving P2P Messages
1098
1099To receive messages from @code{CORE}, you pass the desired
1100@i{handlers} to the @code{GNUNET\_CORE\_connect()} function,
1101just as we showed for services.
1102
1103It is your responsibility to process messages fast enough or
1104to implement flow control. If an application does not process
1105CORE messages fast enough, CORE will randomly drop messages
1106to not keep a very long queue in memory.
1107
1108Exercise: Start one peer with a new service that has a message
1109handler and start a second peer that only has your ``old'' service
1110without message handlers. Which ``connect'' handlers are invoked when
1111the two peers are connected? Why?
1112
1113@node Sending P2P Messages
1114@subsection Sending P2P Messages
1115
1116You can transmit messages to other peers using the @i{mq} you were
1117given during the @code{connect} callback. Note that the @i{mq}
1118automatically is released upon @code{disconnect} and that you must
1119not use it afterwards.
1120
1121It is your responsibility to not over-fill the message queue, GNUnet
1122will send the messages roughly in the order given as soon as possible.
1123
1124Exercise: Write a service that upon connect sends messages as
1125fast as possible to the other peer (the other peer should run a
1126service that ``processes'' those messages). How fast is the
1127transmission? Count using the STATISTICS service on both ends. Are
1128messages lost? How can you transmit messages faster? What happens if
1129you stop the peer that is receiving your messages?
1130
1131@node End of P2P connections
1132@subsection End of P2P connections
1133
1134If a message handler returns @code{GNUNET\_SYSERR}, the remote
1135peer shuts down or there is an unrecoverable network
1136disconnection, CORE notifies the service that the peer disconnected.
1137After this notification no more messages will be received from the
1138peer and the service is no longer allowed to send messages to the peer.
1139The disconnect callback looks like the following:
1140
1141@example
1142@verbatiminclude tutorial-examples/011.c
1143@end example
1144
1145@noindent
1146Exercise: Fix your service to handle peer disconnects.
1147
1148@node Storing peer-specific data using the PEERSTORE service
1149@section Storing peer-specific data using the PEERSTORE service
1150
1151GNUnet's PEERSTORE service offers a persistorage for arbitrary
1152peer-specific data. Other GNUnet services can use the PEERSTORE
1153to store, retrieve and monitor data records. Each data record
1154stored with PEERSTORE contains the following fields:
1155
1156@itemize
1157@item subsystem: Name of the subsystem responsible for the record.
1158@item peerid: Identity of the peer this record is related to.
1159@item key: a key string identifying the record.
1160@item value: binary record value.
1161@item expiry: record expiry date.
1162@end itemize
1163
1164The first step is to start a connection to the PEERSTORE service:
1165@example
1166@verbatiminclude tutorial-examples/012.c
1167@end example
1168
1169The service handle @code{peerstore_handle} will be needed for
1170all subsequent PEERSTORE operations.
1171
1172@menu
1173* Storing records::
1174* Retrieving records::
1175* Monitoring records::
1176* Disconnecting from PEERSTORE::
1177@end menu
1178
1179@node Storing records
1180@subsection Storing records
1181
1182To store a new record, use the following function:
1183
1184@example
1185@verbatiminclude tutorial-examples/013.c
1186@end example
1187
1188@noindent
1189The @code{options} parameter can either be
1190@code{GNUNET_PEERSTORE_STOREOPTION_MULTIPLE} which means that multiple
1191values can be stored under the same key combination
1192(subsystem, peerid, key), or @code{GNUNET_PEERSTORE_STOREOPTION_REPLACE}
1193which means that PEERSTORE will replace any existing values under the
1194given key combination (subsystem, peerid, key) with the new given value.
1195
1196The continuation function @code{cont} will be called after the store
1197request is successfully sent to the PEERSTORE service. This does not
1198guarantee that the record is successfully stored, only that it was
1199received by the service.
1200
1201The @code{GNUNET_PEERSTORE_store} function returns a handle to the store
1202operation. This handle can be used to cancel the store operation only
1203before the continuation function is called:
1204
1205@example
1206@verbatiminclude tutorial-examples/013.1.c
1207@end example
1208
1209@node Retrieving records
1210@subsection Retrieving records
1211
1212To retrieve stored records, use the following function:
1213
1214@example
1215@verbatiminclude tutorial-examples/014.c
1216@end example
1217
1218@noindent
1219The values of @code{peer} and @code{key} can be @code{NULL}. This
1220allows the iteration over values stored under any of the following
1221key combinations:
1222
1223@itemize
1224@item (subsystem)
1225@item (subsystem, peerid)
1226@item (subsystem, key)
1227@item (subsystem, peerid, key)
1228@end itemize
1229
1230The @code{callback} function will be called once with each retrieved
1231record and once more with a @code{NULL} record to signal the end of
1232results.
1233
1234The @code{GNUNET_PEERSTORE_iterate} function returns a handle to the
1235iterate operation. This handle can be used to cancel the iterate
1236operation only before the callback function is called with a
1237@code{NULL} record.
1238
1239@node Monitoring records
1240@subsection Monitoring records
1241
1242PEERSTORE offers the functionality of monitoring for new records
1243stored under a specific key combination (subsystem, peerid, key).
1244To start the monitoring, use the following function:
1245
1246@example
1247@verbatiminclude tutorial-examples/015.c
1248@end example
1249
1250@noindent
1251Whenever a new record is stored under the given key combination,
1252the @code{callback} function will be called with this new
1253record. This will continue until the connection to the PEERSTORE
1254service is broken or the watch operation is canceled:
1255
1256@example
1257@verbatiminclude tutorial-examples/016.c
1258@end example
1259
1260@node Disconnecting from PEERSTORE
1261@subsection Disconnecting from PEERSTORE
1262
1263When the connection to the PEERSTORE service is no longer needed,
1264disconnect using the following function:
1265
1266@example
1267@verbatiminclude tutorial-examples/017.c
1268@end example
1269
1270@noindent
1271If the @code{sync_first} flag is set to @code{GNUNET_YES},
1272the API will delay the disconnection until all store requests
1273are received by the PEERSTORE service. Otherwise, it will
1274disconnect immediately.
1275
1276@node Using the DHT
1277@section Using the DHT
1278
1279The DHT allows to store data so other peers in the P2P network can
1280access it and retrieve data stored by any peers in the network.
1281This section will explain how to use the DHT. Of course, the first
1282thing to do is to connect to the DHT service:
1283
1284@example
1285@verbatiminclude tutorial-examples/018.c
1286@end example
1287
1288@noindent
1289The second parameter indicates how many requests in parallel to expect.
1290It is not a hard limit, but a good approximation will make the DHT more
1291efficient.
1292
1293@menu
1294* Storing data in the DHT::
1295* Obtaining data from the DHT::
1296* Implementing a block plugin::
1297* Monitoring the DHT::
1298@end menu
1299
1300@node Storing data in the DHT
1301@subsection Storing data in the DHT
1302Since the DHT is a dynamic environment (peers join and leave frequently)
1303the data that we put in the DHT does not stay there indefinitely. It is
1304important to ``refresh'' the data periodically by simply storing it
1305again, in order to make sure other peers can access it.
1306
1307The put API call offers a callback to signal that the PUT request has been
1308sent. This does not guarantee that the data is accessible to others peers,
1309or even that is has been stored, only that the service has requested to
1310a neighboring peer the retransmission of the PUT request towards its final
1311destination. Currently there is no feedback about whether or not the data
1312has been sucessfully stored or where it has been stored. In order to
1313improve the availablilty of the data and to compensate for possible
1314errors, peers leaving and other unfavorable events, just make several
1315PUT requests!
1316
1317@example
1318@verbatiminclude tutorial-examples/019.c
1319@end example
1320
1321@noindent
1322Exercise: Store a value in the DHT periodically to make sure it
1323is available over time. You might consider using the function
1324@code{GNUNET\_SCHEDULER\_add\_delayed} and call
1325@code{GNUNET\_DHT\_put} from inside a helper function.
1326
1327@node Obtaining data from the DHT
1328@subsection Obtaining data from the DHT
1329
1330As we saw in the previous example, the DHT works in an asynchronous mode.
1331Each request to the DHT is executed ``in the background'' and the API
1332calls return immediately. In order to receive results from the DHT, the
1333API provides a callback. Once started, the request runs in the service,
1334the service will try to get as many results as possible (filtering out
1335duplicates) until the timeout expires or we explicitly stop the request.
1336It is possible to give a ``forever'' timeout with
1337@code{GNUNET\_TIME\_UNIT\_FOREVER\_REL}.
1338
1339If we give a route option @code{GNUNET\_DHT\_RO\_RECORD\_ROUTE}
1340the callback will get a list of all the peers the data has travelled,
1341both on the PUT path and on the GET path.
1342
1343@example
1344@verbatiminclude tutorial-examples/020.c
1345@end example
1346
1347@noindent
1348Exercise: Store a value in the DHT and after a while retrieve it.
1349Show the IDs of all the peers the requests have gone through.
1350In order to convert a peer ID to a string, use the function
1351@code{GNUNET\_i2s}. Pay attention to the route option parameters
1352in both calls!
1353
1354@node Implementing a block plugin
1355@subsection Implementing a block plugin
1356
1357In order to store data in the DHT, it is necessary to provide a block
1358plugin. The DHT uses the block plugin to ensure that only well-formed
1359requests and replies are transmitted over the network.
1360
1361The block plugin should be put in a file @file{plugin\_block\_SERVICE.c}
1362in the service's respective directory. The
1363mandatory functions that need to be implemented for a block plugin are
1364described in the following sections.
1365
1366@menu
1367* Validating requests and replies::
1368* Deriving a key from a reply::
1369* Initialization of the plugin::
1370* Shutdown of the plugin::
1371* Integration of the plugin with the build system::
1372@end menu
1373
1374@node Validating requests and replies
1375@subsubsection Validating requests and replies
1376
1377The evaluate function should validate a reply or a request. It returns
1378a @code{GNUNET\_BLOCK\_EvaluationResult}, which is an enumeration. All
1379possible answers are in @file{gnunet\_block\_lib.h}. The function will
1380be called with a @code{reply\_block} argument of @code{NULL} for
1381requests. Note that depending on how @code{evaluate} is called, only
1382some of the possible return values are valid. The specific meaning of
1383the @code{xquery} argument is application-specific. Applications that
1384do not use an extended query should check that the @code{xquery\_size}
1385is zero. The block group is typically used to filter duplicate
1386replies.
1387
1388@example
1389@verbatiminclude tutorial-examples/021.c
1390@end example
1391
1392@noindent
1393Note that it is mandatory to detect duplicate replies in this function
1394and return the respective status code. Duplicate detection is
1395typically done using the Bloom filter block group provided by
1396@file{libgnunetblockgroup.so}. Failure to do so may cause replies to
1397circle in the network.
1398
1399@node Deriving a key from a reply
1400@subsubsection Deriving a key from a reply
1401
1402The DHT can operate more efficiently if it is possible to derive a key
1403from the value of the corresponding block. The @code{get\_key}
1404function is used to obtain the key of a block --- for example, by
1405means of hashing. If deriving the key is not possible, the function
1406should simply return @code{GNUNET\_SYSERR} (the DHT will still work
1407just fine with such blocks).
1408
1409@example
1410@verbatiminclude tutorial-examples/022.c
1411@end example
1412
1413@node Initialization of the plugin
1414@subsubsection Initialization of the plugin
1415
1416The plugin is realized as a shared C library. The library must export
1417an initialization function which should initialize the plugin. The
1418initialization function specifies what block types the plugin cares
1419about and returns a struct with the functions that are to be used for
1420validation and obtaining keys (the ones just defined above).
1421
1422@example
1423@verbatiminclude tutorial-examples/023.c
1424@end example
1425
1426@node Shutdown of the plugin
1427@subsubsection Shutdown of the plugin
1428
1429Following GNUnet's general plugin API concept, the plugin must
1430export a second function for cleaning up. It usually does very
1431little.
1432
1433@example
1434@verbatiminclude tutorial-examples/024.c
1435@end example
1436
1437@node Integration of the plugin with the build system
1438@subsubsection Integration of the plugin with the build system
1439
1440In order to compile the plugin, the @file{Makefile.am} file for the
1441service SERVICE should contain a rule similar to this:
1442@c Actually this is a Makefile not C. But the whole structure of examples
1443@c must be improved.
1444
1445@example
1446@verbatiminclude tutorial-examples/025.c
1447@end example
1448
1449@noindent
1450Exercise: Write a block plugin that accepts all queries
1451and all replies but prints information about queries and replies
1452when the respective validation hooks are called.
1453
1454@node Monitoring the DHT
1455@subsection Monitoring the DHT
1456
1457It is possible to monitor the functioning of the local
1458DHT service. When monitoring the DHT, the service will
1459alert the monitoring program of any events, both started
1460locally or received for routing from another peer.
1461The are three different types of events possible: a
1462GET request, a PUT request or a response (a reply to a GET).
1463
1464Since the different events have different associated data,
1465the API gets 3 different callbacks (one for each message type)
1466and optional type and key parameters, to allow for filtering of
1467messages. When an event happens, the appropiate callback is
1468called with all the information about the event.
1469
1470@example
1471@verbatiminclude tutorial-examples/026.c
1472@end example
1473
1474@node Debugging with gnunet-arm
1475@section Debugging with gnunet-arm
1476
1477Even if services are managed by @command{gnunet-arm}, you can
1478start them with @command{gdb} or @command{valgrind}. For
1479example, you could add the following lines to your
1480configuration file to start the DHT service in a @command{gdb}
1481session in a fresh @command{xterm}:
1482
1483@example
1484[dht]
1485PREFIX=xterm -e gdb --args
1486@end example
1487
1488@noindent
1489Alternatively, you can stop a service that was started via
1490ARM and run it manually:
1491
1492@example
1493$ gnunet-arm -k dht
1494$ gdb --args gnunet-service-dht -L DEBUG
1495$ valgrind gnunet-service-dht -L DEBUG
1496@end example
1497
1498@noindent
1499Assuming other services are well-written, they will automatically
1500re-integrate the restarted service with the peer.
1501
1502GNUnet provides a powerful logging mechanism providing log
1503levels @code{ERROR}, @code{WARNING}, @code{INFO} and @code{DEBUG}.
1504The current log level is configured using the @code{$GNUNET_FORCE_LOG}
1505environmental variable. The @code{DEBUG} level is only available if
1506@command{--enable-logging=verbose} was used when running
1507@command{configure}. More details about logging can be found under
1508@uref{https://gnunet.org/logging}.
1509
1510You should also probably enable the creation of core files, by setting
1511@code{ulimit}, and echo'ing @code{1} into
1512@file{/proc/sys/kernel/core\_uses\_pid}. Then you can investigate the
1513core dumps with @command{gdb}, which is often the fastest method to
1514find simple errors.
1515
1516Exercise: Add a memory leak to your service and obtain a trace
1517pointing to the leak using @command{valgrind} while running the service
1518from @command{gnunet-service-arm}.
1519
1520@bye