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