gnunet-handbook

The GNUnet Handbook
Log | Files | Refs

commit 41b72759ffc59ba413956bfcf4213bce9c69c6e3
parent 0d1f35d510c6ceee5bdd51b102fd6b371dbca4a2
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Tue,  2 Aug 2022 16:43:42 +0200

makefile; C tutorial

Diffstat:
MMakefile | 6++++--
Mabout.rst | 35++++++++++++++++++-----------------
Mconf.py | 9++++++++-
Mindex.rst | 4+++-
Mman_developers/index.rst | 1+
Aman_developers/tutorial.rst | 2044+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 2078 insertions(+), 21 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,12 +8,14 @@ SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build +all: html + +.PHONY: all help Makefile + # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -.PHONY: help Makefile - # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile diff --git a/about.rst b/about.rst @@ -1,5 +1,6 @@ +************ About GNUnet -============ +************ GNUnet in its current version is the result of almost 20 years of work from many contributors. So far, most contributions were made by @@ -64,7 +65,7 @@ achieve our goal to create a technical foundation for a society we would like to live in. Project governance ------------------- +================== GNUnet, like the GNU project and many other free software projects, follows the governance model of a benevolent dictator. This means that @@ -88,7 +89,7 @@ to remain free software). In 2018 we switched from GPL3 to AGPL3, in practice these changes do not happen very often. Philosophy ----------- +========== The primary goal of the GNUnet project is to provide a reliable, open, non-discriminating and censorship-resistant system for information @@ -101,7 +102,7 @@ Participants are encouraged to contribute at least as much resources participation does not have a negative impact on other users. Design Principles -~~~~~~~~~~~~~~~~~ +----------------- These are the GNUnet design principles, in order of importance: @@ -127,7 +128,7 @@ These are the GNUnet design principles, in order of importance: than they consume. Privacy and Anonymity -~~~~~~~~~~~~~~~~~~~~~ +--------------------- The GNUnet protocols minimize the leakage of personally identifiable information of participants and do not allow adversaries to control, @@ -144,7 +145,7 @@ an increasingly complex protocol stack. The GNUnet architecture encourages many different forms of peer-to-peer applications. Practicality -~~~~~~~~~~~~ +------------ Wherever possible GNUnet allows the peer to adjust its operations and functionalities to specific use cases. A GNUnet peer running on a mobile @@ -157,7 +158,7 @@ However, it is not possible for any user’s efficiency requirements to compromise the anonymity of any other user. Key Concepts ------------- +============ In this section, the fundamental concepts of GNUnet are explained. Most of them are also described in our research papers. First, some of the @@ -165,7 +166,7 @@ concepts used in the GNUnet framework are detailed. The second part describes concepts specific to anonymous file-sharing. Authentication -~~~~~~~~~~~~~~ +-------------- Almost all peer-to-peer communications in GNUnet are between mutually authenticated peers. The authentication works by using ECDHE, that is a @@ -212,7 +213,7 @@ International Symposium on Cluster Computing and the Grid (GRID 2003), 2003. (https://git.gnunet.org/bibliography.git/plain/docs/transport.pdf) Accounting to Encourage Resource Sharing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------- Most distributed P2P networks suffer from a lack of defenses or precautions against attacks in the form of freeloading. While the @@ -247,7 +248,7 @@ Networks. Wirtschaftsinformatik, June 2003. (https://git.gnunet.org/bibliography.git/plain/docs/ebe.pdf) Confidentiality -~~~~~~~~~~~~~~~ +--------------- Adversaries (malicious, bad actors) outside of GNUnet are not supposed to know what kind of actions a peer is involved in. Only the specific @@ -266,7 +267,7 @@ achieves Anonymity <about.md#how-file-sharing-achieves-anonymity>`__, and see `Deniability <about.md#deniability>`__. Anonymity -~~~~~~~~~ +--------- Providing anonymity for users is the central goal for the anonymous file-sharing application. Many other design decisions follow in the @@ -294,7 +295,7 @@ forego anonymity when this is not required. The anonymity level of 0 allows GNUnet to use more efficient, non-anonymous routing. How file-sharing achieves Anonymity -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Contrary to other designs, we do not believe that users achieve strong anonymity just because their requests are obfuscated by a couple of @@ -336,7 +337,7 @@ Proceedings of Designing Privacy Enhancing Technologies, 2003. (https://git.gnunet.org/bibliography.git/plain/docs/aff.pdf) How messaging provided Anonymity -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ While the file-sharing tries to achieve anonymity through hiding actions in other traffic, the messaging service provides a weaker form of @@ -360,7 +361,7 @@ identity. This means to decrease the chance of being identified, it is recommended to enter rooms but you should not open them for others. Deniability -~~~~~~~~~~~ +----------- Even if the user that downloads data and the server that provides data are anonymous, the intermediaries may still be targets. In particular, @@ -383,7 +384,7 @@ Censorship-Resistant Sharing. 2009. (https://git.gnunet.org/bibliography.git/plain/docs/ecrs.pdf) Peer Identities -~~~~~~~~~~~~~~~ +--------------- Peer identities are used to identify peers in the network and are unique for each peer. The identity for a peer is simply its public key, which @@ -399,7 +400,7 @@ might see it in various places: You can find your peer identity by running ``gnunet-peerinfo -s``. Zones in the GNU Name System (GNS Zones) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------- GNS zones are similar to those of DNS zones, but instead of a hierarchy of authorities to governing their use, GNS zones are controlled by a @@ -428,7 +429,7 @@ and Network Security (CANS 2014). 2014. https://git.gnunet.org/bibliography.git/plain/docs/gns2014wachs.pdf Egos -~~~~ +---- Egos are your “identities” in GNUnet. Any user can assume multiple identities, for example to separate their activities online. Egos can diff --git a/conf.py b/conf.py @@ -30,9 +30,16 @@ author = 'GNUnet Project' extensions = [ 'myst_parser', 'sphinx.ext.todo', - 'sphinx_rtd_theme' + 'sphinx_rtd_theme', + 'breathe' ] +breathe_projects = { + "gnunet": "../gnunet/doc/doxygen/xml/", +} + +breathe_default_project = "gnunet" + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/index.rst b/index.rst @@ -1,5 +1,6 @@ +################################## Welcome to GNUnet’s documentation! -================================== +################################## .. toctree:: @@ -11,5 +12,6 @@ Welcome to GNUnet’s documentation! gana guis/index faq + doxygen Bibliography <https://bib.gnunet.org> diff --git a/man_developers/index.rst b/man_developers/index.rst @@ -46,5 +46,6 @@ new chapters, sections or insightful comments. util/index.rst subsystems/index.rst REST API <https://rest.gnunet.org> + tutorial.rst .. _GNU Affero General Public License: https://www.gnu.org/licenses/licenses.html#AGPL diff --git a/man_developers/tutorial.rst b/man_developers/tutorial.rst @@ -0,0 +1,2044 @@ +********** +C Tutorial +********** + +This tutorials explains how to install GNUnet on a GNU/Linux system and +gives an introduction on how GNUnet can be used to develop a +Peer-to-Peer application. Detailed installation instructions for various +operating systems and a detailed list of all dependencies can be found +on our website at https://docs.gnunet.org/#Installation and in our +Reference Documentation (GNUnet Handbook). + +Please read this tutorial carefully since every single step is +important, and do not hesitate to contact the GNUnet team if you have +any questions or problems! Visit this link in your webbrowser to learn +how to contact the GNUnet team: https://gnunet.org/en/contact.html + +.. _Introduction-to-GNUnet-Architecture: + +Introduction to GNUnet Architecture +=================================== + +GNUnet is organized in layers and services. Each service is composed of +a main service implementation and a client library for other programs to +use the service's functionality, described by an API. Some services +provide an additional command line tool to enable the user to interact +with the service. + +Very often it is other GNUnet services that will use these APIs to build +the higher layers of GNUnet on top of the lower ones. Each layer expands +or extends the functionality of the service below (for instance, to +build a mesh on top of a DHT). + +The main service implementation runs as a standalone process in the +Operating System and the client code runs as part of the client program, +so crashes of a client do not affect the service process or other +clients. The service and the clients communicate via a message protocol +to be defined and implemented by the programmer. + +.. _First-Steps-with-GNUnet: + +First Steps with GNUnet +======================= + +.. _Configure-your-peer: + +Configure your peer +------------------- + +First of all we need to configure your peer. Each peer is started with a +configuration containing settings for GNUnet itself and its services. +This configuration is based on the default configuration shipped with +GNUnet and can be modified. The default configuration is located in the +``$PREFIX/share/gnunet/config.d`` directory. When starting a peer, you +can specify a customized configuration using the the ``-c`` command line +switch when starting the ARM service and all other services. When using +a modified configuration the default values are loaded and only values +specified in the configuration file will replace the default values. + +Since we want to start additional peers later, we need some +modifications from the default configuration. We need to create a +separate service home and a file containing our modifications for this +peer: + +:: + + $ mkdir ~/gnunet1/ + $ touch peer1.conf + +Now add the following lines to ``peer1.conf`` to use this directory. For +simplified usage we want to prevent the peer to connect to the GNUnet +network since this could lead to confusing output. This modifications +will replace the default settings: + +:: + + [PATHS] + # Use this directory to store GNUnet data + GNUNET_HOME = ~/gnunet1/ + [hostlist] + # prevent bootstrapping + SERVERS = + +.. _Start-a-peer: + +Start a peer +------------ + +Each GNUnet instance (called peer) has an identity (peer ID) based on a +cryptographic public private key pair. The peer ID is the printable hash +of the public key. + +GNUnet services are controlled by a master service, the so called +Automatic Restart Manager (ARM). ARM starts, stops and even restarts +services automatically or on demand when a client connects. You interact +with the ARM service using the ``gnunet-arm`` tool. GNUnet can then be +started with ``gnunet-arm -s`` and stopped with ``gnunet-arm -e``. An +additional service not automatically started can be started using +``gnunet-arm -i <service name>`` and stopped using +``gnunet-arm -k <servicename>``. + +Once you have started your peer, you can use many other GNUnet commands +to interact with it. For example, you can run: + +:: + + $ gnunet-peerinfo -s + +to obtain the public key of your peer. + +You should see an output containing the peer ID similar to: + +:: + + I am peer `0PA02UVRKQTS2C .. JL5Q78F6H0B1ACPV1CJI59MEQUMQCC5G'. + +.. _Monitor-a-peer: + +Monitor a peer +-------------- + +In this section, we will monitor the behaviour of our peer's DHT service +with respect to a specific key. First we will start GNUnet and then +start the DHT service and use the DHT monitor tool to monitor the PUT +and GET commands we issue ussing the ``gnunet-dht-put`` and +``gnunet-dht-get`` commands. Using the "monitor" line given below, you +can observe the behavior of your own peer's DHT with respect to the +specified KEY: + +:: + + # start gnunet with all default services: + $ gnunet-arm -c ~/peer1.conf -s + # start DHT service: + $ gnunet-arm -c ~/peer1.conf -i dht + $ cd ~/gnunet/src/dht; + $ ./gnunet-dht-monitor -c ~/peer1.conf -k KEY + +Now open a separate terminal and change again to the ``gnunet/src/dht`` +directory: + +:: + + $ cd ~/gnunet/src/dht + # put VALUE under KEY in the DHT: + $ ./gnunet-dht-put -c ~/peer1.conf -k KEY -d VALUE + # get key KEY from the DHT: + $ ./gnunet/src/dht/gnunet-dht-get -c ~/peer1.conf -k KEY + # print statistics about current GNUnet state: + $ gnunet-statistics -c ~/peer1.conf + # print statistics about DHT service: + $ gnunet-statistics -c ~/peer1.conf -s dht + +.. _Starting-Two-Peers-by-Hand: + +Starting Two Peers by Hand +-------------------------- + +This section describes how to start two peers on the same machine by +hand. The process is rather painful, but the description is somewhat +instructive. In practice, you might prefer the automated method (see +`Starting Peers Using the Testbed +Service <#Starting-Peers-Using-the-Testbed-Service>`__). + +.. _Setup-a-second-peer: + +Setup a second peer +~~~~~~~~~~~~~~~~~~~ + +We will now start a second peer on your machine. For the second peer, +you will need to manually create a modified configuration file to avoid +conflicts with ports and directories. A peers configuration file is by +default located in ``~/.gnunet/gnunet.conf``. This file is typically +very short or even empty as only the differences to the defaults need to +be specified. The defaults are located in many files in the +``$PREFIX/share/gnunet/config.d`` directory. + +To configure the second peer, use the files +``$PREFIX/share/gnunet/config.d`` as a template for your main +configuration file: + +:: + + $ cat $PREFIX/share/gnunet/config.d/*.conf > peer2.conf + +Now you have to edit ``peer2.conf`` and change: + +- ``GNUNET\_TEST\_HOME`` under ``PATHS`` + +- Every (uncommented) value for "\ ``PORT``\ " (add 10000) in any + section (the option may be commented out if ``PORT`` is prefixed by + \"\#\", in this case, UNIX domain sockets are used and the PORT + option does not need to be touched) + +- Every value for "\ ``UNIXPATH``\ " in any section (e.g. by adding a + \"-p2\" suffix) + +to a fresh, unique value. Make sure that the PORT numbers stay below +65536. From now on, whenever you interact with the second peer, you need +to specify ``-c peer2.conf`` as an additional command line argument. + +Now, generate the 2nd peer's private key: + +:: + + $ gnunet-peerinfo -s -c peer2.conf + +This may take a while, generate entropy using your keyboard or mouse as +needed. Also, make sure the output is different from the gnunet-peerinfo +output for the first peer (otherwise you made an error in the +configuration). + +.. _Start-the-second-peer-and-connect-the-peers: + +Start the second peer and connect the peers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Then, you can start a second peer using: + +:: + + $ gnunet-arm -c peer2.conf -s + $ gnunet-arm -c peer2.conf -i dht + $ ~/gnunet/src/dht/gnunet-dht-put -c peer2.conf -k KEY -d VALUE + $ ~/gnunet/src/dht/gnunet-dht-get -c peer2.conf -k KEY + +If you want the two peers to connect, you have multiple options: + +- UDP neighbour discovery (automatic) + +- Setup a bootstrap server + +- Connect manually + +To setup peer 1 as bootstrapping server change the configuration of the +first one to be a hostlist server by adding the following lines to +``peer1.conf`` to enable bootstrapping server: + +:: + + [hostlist] + OPTIONS = -p + +Then change ``peer2.conf`` and replace the "\ ``SERVERS``\ " line in the +"\ ``[hostlist]``\ " section with "\ ``http://localhost:8080/``\ ". +Restart both peers using: + +:: + + # stop first peer + $ gnunet-arm -c peer1.conf -e + # start first peer + $ gnunet-arm -c peer1.conf -s + # start second peer + $ gnunet-arm -c peer2.conf -s + +Note that if you start your peers without changing these settings, they +will use the "global" hostlist servers of the GNUnet P2P network and +likely connect to those peers. At that point, debugging might become +tricky as you're going to be connected to many more peers and would +likely observe traffic and behaviors that are not explicitly controlled +by you. + +.. _How-to-connect-manually: + +How to connect manually +~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to use the ``peerinfo`` tool to connect your peers, you +should: + +- Set ``IMMEDIATE_START = NO`` in section ``hostlist`` (to not connect + to the global GNUnet) + +- Start both peers running ``gnunet-arm -c peer1.conf -s`` and + ``gnunet-arm -c peer2.conf -s`` + +- Get ``HELLO`` message of the first peer running + ``gnunet-peerinfo -c peer1.conf -g`` + +- Give the output to the second peer by running + ``gnunet-peerinfo -c peer2.conf -p '<output>'`` + +Check that they are connected using ``gnunet-core -c peer1.conf``, which +should give you the other peer's peer identity: + +:: + + $ gnunet-core -c peer1.conf + Peer `9TVUCS8P5A7ILLBGO6 [...shortened...] 1KNBJ4NGCHP3JPVULDG' + +.. _Starting-Peers-Using-the-Testbed-Service: + +Starting Peers Using the Testbed Service +---------------------------------------- + +GNUnet's testbed service is used for testing scenarios where a number of +peers are to be started. The testbed can manage peers on a single host +or on multiple hosts in a distributed fashion. On a single affordable +computer, it should be possible to run around tens of peers without +drastically increasing the load on the system. + +The testbed service can be access through its API +``include/gnunet\_testbed\_service.h``. The API provides many routines +for managing a group of peers. It also provides a helper function +``GNUNET\_TESTBED\_test\_run()`` to quickly setup a minimalistic testing +environment on a single host. + +This function takes a configuration file which will be used as a +template configuration for the peers. The testbed takes care of +modifying relevant options in the peers' configuration such as +``SERVICEHOME``, ``PORT``, ``UNIXPATH`` to unique values so that peers +run without running into conflicts. It also checks and assigns the ports +in configurations only if they are free. + +Additionally, the testbed service also reads its options from the same +configuration file. Various available options and details about them can +be found in the testbed default configuration file +``src/testbed/testbed.conf``. + +With the testbed API, a sample test case can be structured as follows: + +:: + + #include <unistd.h> + #include <gnunet/platform.h> + #include <gnunet/gnunet_util_lib.h> + #include <gnunet/gnunet_testbed_service.h> + #include <gnunet/gnunet_dht_service.h> + + #define NUM_PEERS 20 + + static struct GNUNET_TESTBED_Operation *dht_op; + + static struct GNUNET_DHT_Handle *dht_handle; + + + struct MyContext + { + int ht_len; + } ctxt; + + + static int result; + + + static void + shutdown_task (void *cls) + { + if (NULL != dht_op) + { + GNUNET_TESTBED_operation_done (dht_op); + dht_op = NULL; + dht_handle = NULL; + } + result = GNUNET_OK; + } + + + static void + service_connect_comp (void *cls, + struct GNUNET_TESTBED_Operation *op, + void *ca_result, + const char *emsg) + { + GNUNET_assert (op == dht_op); + dht_handle = ca_result; + // Do work here... + GNUNET_SCHEDULER_shutdown (); + } + + + static void * + dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) + { + struct MyContext *ctxt = cls; + + dht_handle = GNUNET_DHT_connect (cfg, ctxt->ht_len); + return dht_handle; + } + + + static void + dht_da (void *cls, void *op_result) + { + struct MyContext *ctxt = cls; + + GNUNET_DHT_disconnect ((struct GNUNET_DHT_Handle *) op_result); + dht_handle = NULL; + } + + + static void + test_master (void *cls, + struct GNUNET_TESTBED_RunHandle *h, + unsigned int num_peers, + struct GNUNET_TESTBED_Peer **peers, + unsigned int links_succeeded, + unsigned int links_failed) + { + ctxt.ht_len = 10; + dht_op = GNUNET_TESTBED_service_connect + (NULL, peers[0], "dht", + &service_connect_comp, NULL, + &dht_ca, &dht_da, &ctxt); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); + } + + + int + main (int argc, char **argv) + { + int ret; + + result = GNUNET_SYSERR; + ret = GNUNET_TESTBED_test_run + ("awesome-test", "template.conf", + NUM_PEERS, 0LL, + NULL, NULL, &test_master, NULL); + if ( (GNUNET_OK != ret) || (GNUNET_OK != result) ) + return 1; + return 0; + } + +The source code for the above listing can be found at +https://git.gnunet.org/gnunet.git/tree/doc/documentation/testbed_test.c +or in the ``doc/`` folder of your repository check-out. After installing +GNUnet, the above source code can be compiled as: + +:: + + $ export CPPFLAGS="-I/path/to/gnunet/headers" + $ export LDFLAGS="-L/path/to/gnunet/libraries" + $ gcc $CPPFLAGS $LDFLAGS -o testbed-test testbed_test.c \ + -lgnunettestbed -lgnunetdht -lgnunetutil + # Generate (empty) configuration + $ touch template.conf + # run it (press CTRL-C to stop) + $ ./testbed-test + +The ``CPPFLAGS`` and ``LDFLAGS`` are necessary if GNUnet is installed +into a different directory other than ``/usr/local``. + +All of testbed API's peer management functions treat management actions +as operations and return operation handles. It is expected that the +operations begin immediately, but they may get delayed (to balance out +load on the system). The program using the API then has to take care of +marking the operation as "done" so that its associated resources can be +freed immediately and other waiting operations can be executed. +Operations will be canceled if they are marked as "done" before their +completion. + +An operation is treated as completed when it succeeds or fails. +Completion of an operation is either conveyed as events through +controller event callback or through respective operation completion +callbacks. In functions which support completion notification through +both controller event callback and operation completion callback, first +the controller event callback will be called. If the operation is not +marked as done in that callback or if the callback is given as NULL when +creating the operation, the operation completion callback will be +called. The API documentation shows which event are to be expected in +the controller event notifications. It also documents any exceptional +behaviour. + +Once the peers are started, test cases often need to connect some of the +peers' services. Normally, opening a connect to a peer's service +requires the peer's configuration. While using testbed, the testbed +automatically generates per-peer configuration. Accessing those +configurations directly through file system is discouraged as their +locations are dynamically created and will be different among various +runs of testbed. To make access to these configurations easy, testbed +API provides the function ``GNUNET\_TESTBED\_service\_connect()``. This +function fetches the configuration of a given peer and calls the Connect +Adapter. In the example code, it is the ``dht\_ca``. A connect adapter +is expected to open the connection to the needed service by using the +provided configuration and return the created service connection handle. +Successful connection to the needed service is signaled through +``service\_connect\_comp\_cb``. + +A dual to connect adapter is the Disconnect Adapter. This callback is +called after the connect adapter has been called when the operation from +``GNUNET\_TESTBED\_service\_connect()`` is marked as "done". It has to +disconnect from the service with the provided service handle +(``op\_result``). + +Exercise: Find out how many peers you can run on your system. + +Exercise: Find out how to create a 2D torus topology by changing the +options in the configuration file. See section "The GNUnet Reference +Documentation" in The GNUnet Reference Documentation, then use the DHT +API to store and retrieve values in the network. + +.. _Developing-Applications: + +Developing Applications +======================= + +.. _gnunet_002dext: + +gnunet-ext +---------- + +To develop a new peer-to-peer application or to extend GNUnet we provide +a template build system for writing GNUnet extensions in C. It can be +obtained as follows: + +:: + + $ git clone https://git.gnunet.org/gnunet-ext.git + $ cd gnunet-ext/ + $ ./bootstrap + $ ./configure --prefix=$PREFIX --with-gnunet=$PREFIX + $ make + $ make install + $ make check + +The GNUnet ext template includes examples and a working buildsystem for +a new GNUnet service. A common GNUnet service consists of the following +parts which will be discussed in detail in the remainder of this +document. The functionality of a GNUnet service is implemented in: + +- the GNUnet service (gnunet-ext/src/ext/gnunet-service-ext.c) + +- the client API (gnunet-ext/src/ext/ext_api.c) + +- the client application using the service API + (gnunet-ext/src/ext/gnunet-ext.c) + +The interfaces for these entities are defined in: + +- client API interface (gnunet-ext/src/ext/ext.h) + +- the service interface + (gnunet-ext/src/include/gnunet_service_SERVICE.h) + +- the P2P protocol (gnunet-ext/src/include/gnunet_protocols_ext.h) + +In addition the ext systems provides: + +- a test testing the API (gnunet-ext/src/ext/test_ext_api.c) + +- a configuration template for the service + (gnunet-ext/src/ext/ext.conf.in) + +.. _Adapting-the-Template: + +Adapting the Template +--------------------- + +The first step for writing any extension with a new service is to ensure +that the ``ext.conf.in`` file contains entries for the ``UNIXPATH``, +``PORT`` and ``BINARY`` for the service in a section named after the +service. + +If you want to adapt the template rename the ``ext.conf.in`` to match +your services name, you have to modify the ``AC\_OUTPUT`` section in +``configure.ac`` in the ``gnunet-ext`` root. + +.. _Writing-a-Client-Application: + +Writing a Client Application +---------------------------- + +When writing any client application (for example, a command-line tool), +the basic structure is to start with the ``GNUNET\_PROGRAM\_run`` +function. This function will parse command-line options, setup the +scheduler and then invoke the ``run`` function (with the remaining +non-option arguments) and a handle to the parsed configuration (and the +configuration file name that was used, which is typically not needed): + +:: + + #include <gnunet/platform.h> + #include <gnunet/gnunet_util_lib.h> + + static int ret; + + static void + run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) + { + // main code here + ret = 0; + } + + int + main (int argc, char *const *argv) + { + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + return (GNUNET_OK == + GNUNET_PROGRAM_run (argc, + argv, + "binary-name", + gettext_noop ("binary description text"), + options, &run, NULL)) ? ret : 1; + } + +.. _Handling-command_002dline-options: + +Handling command-line options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Options can then be added easily by adding global variables and +expanding the ``options`` array. For example, the following would add a +string-option and a binary flag (defaulting to ``NULL`` and +``GNUNET\_NO`` respectively): + +:: + + static char *string_option; + static int a_flag; + + // ... + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_string ('s', "name", "SOMESTRING", + gettext_noop ("text describing the string_option NAME"), + &string_option}, + GNUNET_GETOPT_option_flag ('f', "flag", + gettext_noop ("text describing the flag option"), + &a_flag), + GNUNET_GETOPT_OPTION_END + }; + string_option = NULL; + a_flag = GNUNET_SYSERR; + // ... + +Issues such as displaying some helpful text describing options using the +``--help`` argument and error handling are taken care of when using this +approach. Other ``GNUNET\_GETOPT\_``-functions can be used to obtain +integer value options, increment counters, etc. You can even write +custom option parsers for special circumstances not covered by the +available handlers. To check if an argument was specified by the user +you initialize the variable with a specific value (e.g. NULL for a +string and GNUNET\_SYSERR for a integer) and check after parsing +happened if the values were modified. + +Inside the ``run`` method, the program would perform the +application-specific logic, which typically involves initializing and +using some client library to interact with the service. The client +library is supposed to implement the IPC whereas the service provides +more persistent P2P functions. + +Exercise: Add a few command-line options and print them inside of +``run``. What happens if the user gives invalid arguments? + +.. _Writing-a-Client-Library: + +Writing a Client Library +~~~~~~~~~~~~~~~~~~~~~~~~ + +The first and most important step in writing a client library is to +decide on an API for the library. Typical API calls include connecting +to the service, performing application-specific requests and cleaning +up. Many examples for such service APIs can be found in the +``gnunet/src/include/gnunet\_*\_service.h`` files. + +Then, a client-service protocol needs to be designed. This typically +involves defining various message formats in a header that will be +included by both the service and the client library (but is otherwise +not shared and hence located within the service's directory and not +installed by ``make install``). Each message must start with a +``struct GNUNET\_MessageHeader`` and must be shorter than 64k. By +convention, all fields in IPC (and P2P) messages must be in big-endian +format (and thus should be read using ``ntohl`` and similar functions +and written using ``htonl`` and similar functions). Unique message types +must be defined for each message struct in the ``gnunet\_protocols.h`` +header (or an extension-specific include file). + +.. _Connecting-to-the-Service: + +Connecting to the Service +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before a client library can implement the application-specific protocol +with the service, a connection must be created: + +:: + + struct GNUNET_MQ_MessageHandlers handlers[] = { + // ... + GNUNET_MQ_handler_end () + }; + struct GNUNET_MQ_Handle *mq; + + mq = GNUNET_CLIENT_connect (cfg, + "service-name", + handlers, + &error_cb, + NULL); + +As a result a ``GNUNET\_MQ\_Handle`` is returned which can to used +henceforth to transmit messages to the service. The complete MQ API can +be found in ``gnunet\_mq\_lib.h``. The ``handlers`` array in the example +above is incomplete. Here is where you will define which messages you +expect to receive from the service, and which functions handle them. The +``error\_cb`` is a function that is to be called whenever there are +errors communicating with the service. + +.. _Sending-messages: + +Sending messages +^^^^^^^^^^^^^^^^ + +In GNUnet, messages are always sent beginning with a +``struct GNUNET\_MessageHeader`` in big endian format. This header +defines the size and the type of the message, the payload follows after +this header. + +:: + + struct GNUNET_MessageHeader + { + uint16_t size GNUNET_PACKED; + uint16_t type GNUNET_PACKED; + }; + +Existing message types are defined in ``gnunet\_protocols.h``. A common +way to create a message is with an envelope: + +:: + + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; + + env = GNUNET_MQ_msg_extra (msg, payload_size, GNUNET_MY_MESSAGE_TYPE); + GNUNET_memcpy (&msg[1], + &payload, + payload_size); + // Send message via message queue 'mq' + GNUNET_mq_send (mq, env); + +Exercise: Define a message struct that includes a 32-bit unsigned +integer in addition to the standard GNUnet MessageHeader. Add a C struct +and define a fresh protocol number for your message. Protocol numbers in +gnunet-ext are defined in +``gnunet-ext/src/include/gnunet_protocols_ext.h`` + +Exercise: Find out how you can determine the number of messages in a +message queue. + +Exercise: Find out how you can determine when a message you have queued +was actually transmitted. + +Exercise: Define a helper function to transmit a 32-bit unsigned integer +(as payload) to a service using some given client handle. + +.. _Receiving-Replies-from-the-Service: + +Receiving Replies from the Service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Clients can receive messages from the service using the handlers +specified in the ``handlers`` array we specified when connecting to the +service. Entries in the the array are usually created using one of two +macros, depending on whether the message is fixed size or variable size. +Variable size messages are managed using two callbacks, one to check +that the message is well-formed, the other to actually process the +message. Fixed size messages are fully checked by the MQ-logic, and thus +only need to provide the handler to process the message. Note that the +prefixes ``check\_`` and ``handle\_`` are mandatory. + +:: + + static void + handle_fix (void *cls, const struct MyMessage *msg) + { + // process 'msg' + } + + static int + check_var (void *cls, const struct MyVarMessage *msg) + { + // check 'msg' is well-formed + return GNUNET_OK; + } + + static void + handle_var (void *cls, const struct MyVarMessage *msg) + { + // process 'msg' + } + + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_fixed_size (fix, + GNUNET_MESSAGE_TYPE_MY_FIX, + struct MyMessage, + NULL), + GNUNET_MQ_hd_fixed_size (var, + GNUNET_MESSAGE_TYPE_MY_VAR, + struct MyVarMessage, + NULL), + + GNUNET_MQ_handler_end () + }; + +Exercise: Expand your helper function to receive a response message (for +example, containing just the ``struct GNUnet MessageHeader`` without any +payload). Upon receiving the service's response, you should call a +callback provided to your helper function's API. + +Exercise: Figure out where you can pass values to the closures +(``cls``). + +.. _Writing-a-user-interface: + +Writing a user interface +~~~~~~~~~~~~~~~~~~~~~~~~ + +Given a client library, all it takes to access a service now is to +combine calls to the client library with parsing command-line options. + +Exercise: Call your client API from your ``run()`` method in your client +application to send a request to the service. For example, send a 32-bit +integer value based on a number given at the command-line to the +service. + +.. _Writing-a-Service: + +Writing a Service +----------------- + +Before you can test the client you've written so far, you'll need to +also implement the corresponding service. + +.. _Code-Placement: + +Code Placement +~~~~~~~~~~~~~~ + +New services are placed in their own subdirectory under ``gnunet/src``. +This subdirectory should contain the API implementation file +``SERVICE\_api.c``, the description of the client-service protocol +``SERVICE.h`` and P2P protocol ``SERVICE\_protocol.h``, the +implementation of the service itself ``gnunet-service-SERVICE.h`` and +several files for tests, including test code and configuration files. + +.. _Starting-a-Service: + +Starting a Service +~~~~~~~~~~~~~~~~~~ + +The key API definition for creating a service is the +``GNUNET\_SERVICE\_MAIN`` macro: + +:: + + GNUNET_SERVICE_MAIN + ("service-name", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_fixed_size (...), + GNUNET_MQ_hd_var_size (...), + GNUNET_MQ_handler_end ()); + +In addition to the service name and flags, the macro takes three +functions, typically called ``run``, ``client\_connect\_cb`` and +``client\_disconnect\_cb`` as well as an array of message handlers that +will be called for incoming messages from clients. + +A minimal version of the three central service functions would look like +this: + +:: + + static void + run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *service) + { + } + + static void * + client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *c, + struct GNUNET_MQ_Handle *mq) + { + return c; + } + + static void + client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *c, + void *internal_cls) + { + GNUNET_assert (c == internal_cls); + } + +Exercise: Write a stub service that processes no messages at all in your +code. Create a default configuration for it, integrate it with the build +system and start the service from ``gnunet-service-arm`` using +``gnunet-arm -i NAME``. + +Exercise: Figure out how to set the closure (``cls``) for handlers of a +service. + +Exercise: Figure out how to send messages from the service back to the +client. + +Each handler function in the service **must** eventually (possibly in +some asynchronous continuation) call +``GNUNET\_SERVICE\_client\_continue()``. Only after this call additional +messages from the same client may be processed. This way, the service +can throttle processing messages from the same client. + +Exercise: Change the service to "handle" the message from your client +(for now, by printing a message). What happens if you forget to call +``GNUNET\_SERVICE\_client\_continue()``? + +.. _Interacting-directly-with-other-Peers-using-the-CORE-Service: + +Interacting directly with other Peers using the CORE Service +------------------------------------------------------------ + +FIXME: This section still needs to be updated to the latest API! + +One of the most important services in GNUnet is the ``CORE`` service +managing connections between peers and handling encryption between +peers. + +One of the first things any service that extends the P2P protocol +typically does is connect to the ``CORE`` service using: + +:: + + #include <gnunet/gnunet_core_service.h> + + struct GNUNET_CORE_Handle * + GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, + void *cls, + GNUNET_CORE_StartupCallback init, + GNUNET_CORE_ConnectEventHandler connects, + GNUNET_CORE_DisconnectEventHandler disconnects, + const struct GNUNET_MQ_MessageHandler *handlers); + +.. _New-P2P-connections: + +New P2P connections +~~~~~~~~~~~~~~~~~~~ + +Before any traffic with a different peer can be exchanged, the peer must +be known to the service. This is notified by the ``CORE`` ``connects`` +callback, which communicates the identity of the new peer to the +service: + +:: + + void * + connects (void *cls, + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_MQ_Handle *mq) + { + return mq; + } + +Note that whatever you return from ``connects`` is given as the ``cls`` +argument to the message handlers for messages from the respective peer. + +Exercise: Create a service that connects to the ``CORE``. Then start +(and connect) two peers and print a message once your connect callback +is invoked. + +.. _Receiving-P2P-Messages: + +Receiving P2P Messages +~~~~~~~~~~~~~~~~~~~~~~ + +To receive messages from ``CORE``, you pass the desired ``handlers`` to +the ``GNUNET\_CORE\_connect()`` function, just as we showed for +services. + +It is your responsibility to process messages fast enough or to +implement flow control. If an application does not process CORE messages +fast enough, CORE will randomly drop messages to not keep a very long +queue in memory. + +Exercise: Start one peer with a new service that has a message handler +and start a second peer that only has your "old" service without message +handlers. Which "connect" handlers are invoked when the two peers are +connected? Why? + +.. _Sending-P2P-Messages: + +Sending P2P Messages +~~~~~~~~~~~~~~~~~~~~ + +You can transmit messages to other peers using the ``mq`` you were given +during the ``connect`` callback. Note that the ``mq`` automatically is +released upon ``disconnect`` and that you must not use it afterwards. + +It is your responsibility to not over-fill the message queue, GNUnet +will send the messages roughly in the order given as soon as possible. + +Exercise: Write a service that upon connect sends messages as fast as +possible to the other peer (the other peer should run a service that +"processes" those messages). How fast is the transmission? Count using +the STATISTICS service on both ends. Are messages lost? How can you +transmit messages faster? What happens if you stop the peer that is +receiving your messages? + +.. _End-of-P2P-connections: + +End of P2P connections +~~~~~~~~~~~~~~~~~~~~~~ + +If a message handler returns ``GNUNET\_SYSERR``, the remote peer shuts +down or there is an unrecoverable network disconnection, CORE notifies +the service that the peer disconnected. After this notification no more +messages will be received from the peer and the service is no longer +allowed to send messages to the peer. The disconnect callback looks like +the following: + +:: + + void + disconnects (void *cls, + const struct GNUNET_PeerIdentity * peer) + { + /* Remove peer's identity from known peers */ + /* Make sure no messages are sent to peer from now on */ + } + +Exercise: Fix your service to handle peer disconnects. + +.. _Storing-peer_002dspecific-data-using-the-PEERSTORE-service: + +Storing peer-specific data using the PEERSTORE service +------------------------------------------------------ + +GNUnet's PEERSTORE service offers a persistorage for arbitrary +peer-specific data. Other GNUnet services can use the PEERSTORE to +store, retrieve and monitor data records. Each data record stored with +PEERSTORE contains the following fields: + +- subsystem: Name of the subsystem responsible for the record. + +- peerid: Identity of the peer this record is related to. + +- key: a key string identifying the record. + +- value: binary record value. + +- expiry: record expiry date. + +The first step is to start a connection to the PEERSTORE service: + +:: + + #include "gnunet_peerstore_service.h" + + peerstore_handle = GNUNET_PEERSTORE_connect (cfg); + +The service handle ``peerstore_handle`` will be needed for all +subsequent PEERSTORE operations. + +.. _Storing-records: + +Storing records +~~~~~~~~~~~~~~~ + +To store a new record, use the following function: + +:: + + struct GNUNET_PEERSTORE_StoreContext * + GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h, + const char *sub_system, + const struct GNUNET_PeerIdentity *peer, + const char *key, + const void *value, + size_t size, + struct GNUNET_TIME_Absolute expiry, + enum GNUNET_PEERSTORE_StoreOption options, + GNUNET_PEERSTORE_Continuation cont, + void *cont_cls); + +The ``options`` parameter can either be +``GNUNET_PEERSTORE_STOREOPTION_MULTIPLE`` which means that multiple +values can be stored under the same key combination (subsystem, peerid, +key), or ``GNUNET_PEERSTORE_STOREOPTION_REPLACE`` which means that +PEERSTORE will replace any existing values under the given key +combination (subsystem, peerid, key) with the new given value. + +The continuation function ``cont`` will be called after the store +request is successfully sent to the PEERSTORE service. This does not +guarantee that the record is successfully stored, only that it was +received by the service. + +The ``GNUNET_PEERSTORE_store`` function returns a handle to the store +operation. This handle can be used to cancel the store operation only +before the continuation function is called: + +:: + + void + GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext + *sc); + +.. _Retrieving-records: + +Retrieving records +~~~~~~~~~~~~~~~~~~ + +To retrieve stored records, use the following function: + +:: + + struct GNUNET_PEERSTORE_IterateContext * + GNUNET_PEERSTORE_iterate (struct GNUNET_PEERSTORE_Handle *h, + const char *sub_system, + const struct GNUNET_PeerIdentity *peer, + const char *key, + GNUNET_PEERSTORE_Processor callback, + void *callback_cls); + +The values of ``peer`` and ``key`` can be ``NULL``. This allows the +iteration over values stored under any of the following key +combinations: + +- (subsystem) + +- (subsystem, peerid) + +- (subsystem, key) + +- (subsystem, peerid, key) + +The ``callback`` function will be called once with each retrieved record +and once more with a ``NULL`` record to signal the end of results. + +The ``GNUNET_PEERSTORE_iterate`` function returns a handle to the +iterate operation. This handle can be used to cancel the iterate +operation only before the callback function is called with a ``NULL`` +record. + +.. _Monitoring-records: + +Monitoring records +~~~~~~~~~~~~~~~~~~ + +PEERSTORE offers the functionality of monitoring for new records stored +under a specific key combination (subsystem, peerid, key). To start the +monitoring, use the following function: + +:: + + struct GNUNET_PEERSTORE_WatchContext * + GNUNET_PEERSTORE_watch (struct GNUNET_PEERSTORE_Handle *h, + const char *sub_system, + const struct GNUNET_PeerIdentity *peer, + const char *key, + GNUNET_PEERSTORE_Processor callback, + void *callback_cls); + +Whenever a new record is stored under the given key combination, the +``callback`` function will be called with this new record. This will +continue until the connection to the PEERSTORE service is broken or the +watch operation is canceled: + +:: + + void + GNUNET_PEERSTORE_watch_cancel (struct GNUNET_PEERSTORE_WatchContext + *wc); + +.. _Disconnecting-from-PEERSTORE: + +Disconnecting from PEERSTORE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the connection to the PEERSTORE service is no longer needed, +disconnect using the following function: + +:: + + void + GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, + int sync_first); + +If the ``sync_first`` flag is set to ``GNUNET_YES``, the API will delay +the disconnection until all store requests are received by the PEERSTORE +service. Otherwise, it will disconnect immediately. + +.. _Using-the-DHT: + +Using the DHT +------------- + +The DHT allows to store data so other peers in the P2P network can +access it and retrieve data stored by any peers in the network. This +section will explain how to use the DHT. Of course, the first thing to +do is to connect to the DHT service: + +:: + + dht_handle = GNUNET_DHT_connect (cfg, parallel_requests); + +The second parameter indicates how many requests in parallel to expect. +It is not a hard limit, but a good approximation will make the DHT more +efficient. + +.. _Storing-data-in-the-DHT: + +Storing data in the DHT +~~~~~~~~~~~~~~~~~~~~~~~ + +Since the DHT is a dynamic environment (peers join and leave frequently) +the data that we put in the DHT does not stay there indefinitely. It is +important to "refresh" the data periodically by simply storing it again, +in order to make sure other peers can access it. + +The put API call offers a callback to signal that the PUT request has +been sent. This does not guarantee that the data is accessible to others +peers, or even that is has been stored, only that the service has +requested to a neighboring peer the retransmission of the PUT request +towards its final destination. Currently there is no feedback about +whether or not the data has been successfully stored or where it has +been stored. In order to improve the availablilty of the data and to +compensate for possible errors, peers leaving and other unfavorable +events, just make several PUT requests! + +:: + + message_sent_cont (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) + { + // Request has left local node + } + + struct GNUNET_DHT_PutHandle * + GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, + const struct GNUNET_HashCode *key, + uint32_t desired_replication_level, + enum GNUNET_DHT_RouteOption options, + enum GNUNET_BLOCK_Type type, + size_t size, + const void *data, + struct GNUNET_TIME_Absolute exp, + struct GNUNET_TIME_Relative timeout, + GNUNET_DHT_PutContinuation cont, void *cont_cls) + +Exercise: Store a value in the DHT periodically to make sure it is +available over time. You might consider using the function +``GNUNET\_SCHEDULER\_add\_delayed`` and call ``GNUNET\_DHT\_put`` from +inside a helper function. + +.. _Obtaining-data-from-the-DHT: + +Obtaining data from the DHT +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As we saw in the previous example, the DHT works in an asynchronous +mode. Each request to the DHT is executed "in the background" and the +API calls return immediately. In order to receive results from the DHT, +the API provides a callback. Once started, the request runs in the +service, the service will try to get as many results as possible +(filtering out duplicates) until the timeout expires or we explicitly +stop the request. It is possible to give a "forever" timeout with +``GNUNET\_TIME\_UNIT\_FOREVER\_REL``. + +If we give a route option ``GNUNET\_DHT\_RO\_RECORD\_ROUTE`` the +callback will get a list of all the peers the data has travelled, both +on the PUT path and on the GET path. + +:: + + static void + get_result_iterator (void *cls, struct GNUNET_TIME_Absolute expiration, + const struct GNUNET_HashCode *key, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + enum GNUNET_BLOCK_Type type, size_t size, + const void *data) + { + // Optionally: + GNUNET_DHT_get_stop (get_handle); + } + + get_handle = + GNUNET_DHT_get_start (dht_handle, + block_type, + &key, + replication, + GNUNET_DHT_RO_NONE, + NULL, + 0, + &get_result_iterator, + cls) + +Exercise: Store a value in the DHT and after a while retrieve it. Show +the IDs of all the peers the requests have gone through. In order to +convert a peer ID to a string, use the function ``GNUNET\_i2s``. Pay +attention to the route option parameters in both calls! + +.. _Implementing-a-block-plugin: + +Implementing a block plugin +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order to store data in the DHT, it is necessary to provide a block +plugin. The DHT uses the block plugin to ensure that only well-formed +requests and replies are transmitted over the network. + +The block plugin should be put in a file ``plugin\_block\_SERVICE.c`` in +the service's respective directory. The mandatory functions that need to +be implemented for a block plugin are described in the following +sections. + +.. _Validating-requests-and-replies: + +Validating requests and replies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The evaluate function should validate a reply or a request. It returns a +``GNUNET\_BLOCK\_EvaluationResult``, which is an enumeration. All +possible answers are in ``gnunet\_block\_lib.h``. The function will be +called with a ``reply\_block`` argument of ``NULL`` for requests. Note +that depending on how ``evaluate`` is called, only some of the possible +return values are valid. The specific meaning of the ``xquery`` argument +is application-specific. Applications that do not use an extended query +should check that the ``xquery\_size`` is zero. The block group is +typically used to filter duplicate replies. + +:: + + static enum GNUNET_BLOCK_EvaluationResult + block_plugin_SERVICE_evaluate (void *cls, + enum GNUNET_BLOCK_Type type, + struct GNUNET_BlockGroup *bg, + const GNUNET_HashCode *query, + const void *xquery, + size_t xquery_size, + const void *reply_block, + size_t reply_block_size) + { + // Verify type, block and bg + } + +Note that it is mandatory to detect duplicate replies in this function +and return the respective status code. Duplicate detection is typically +done using the Bloom filter block group provided by +``libgnunetblockgroup.so``. Failure to do so may cause replies to circle +in the network. + +.. _Deriving-a-key-from-a-reply: + +Deriving a key from a reply +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The DHT can operate more efficiently if it is possible to derive a key +from the value of the corresponding block. The ``get\_key`` function is +used to obtain the key of a block --- for example, by means of hashing. +If deriving the key is not possible, the function should simply return +``GNUNET\_SYSERR`` (the DHT will still work just fine with such blocks). + +:: + + static int + block_plugin_SERVICE_get_key (void *cls, enum GNUNET_BLOCK_Type type, + const void *block, size_t block_size, + struct GNUNET_HashCode *key) + { + // Store the key in the key argument, return GNUNET_OK on success. + } + +.. _Initialization-of-the-plugin: + +Initialization of the plugin +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The plugin is realized as a shared C library. The library must export an +initialization function which should initialize the plugin. The +initialization function specifies what block types the plugin cares +about and returns a struct with the functions that are to be used for +validation and obtaining keys (the ones just defined above). + +:: + + void * + libgnunet_plugin_block_SERVICE_init (void *cls) + { + static enum GNUNET_BLOCK_Type types[] = + { + GNUNET_BLOCK_TYPE_SERVICE_BLOCKYPE, + GNUNET_BLOCK_TYPE_ANY + }; + struct GNUNET_BLOCK_PluginFunctions *api; + + api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); + api->evaluate = &block_plugin_SERICE_evaluate; + api->get_key = &block_plugin_SERVICE_get_key; + api->types = types; + return api; + } + +.. _Shutdown-of-the-plugin: + +Shutdown of the plugin +^^^^^^^^^^^^^^^^^^^^^^ + +Following GNUnet's general plugin API concept, the plugin must export a +second function for cleaning up. It usually does very little. + +:: + + void * + libgnunet_plugin_block_SERVICE_done (void *cls) + { + struct GNUNET_TRANSPORT_PluginFunctions *api = cls; + + GNUNET_free (api); + return NULL; + } + +.. _Integration-of-the-plugin-with-the-build-system: + +Integration of the plugin with the build system +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In order to compile the plugin, the ``Makefile.am`` file for the service +SERVICE should contain a rule similar to this: + +:: + + plugindir = $(libdir)/gnunet + + plugin_LTLIBRARIES = \ + libgnunet_plugin_block_ext.la + libgnunet_plugin_block_ext_la_SOURCES = \ + plugin_block_ext.c + libgnunet_plugin_block_ext_la_LIBADD = \ + $(prefix)/lib/libgnunethello.la \ + $(prefix)/lib/libgnunetblock.la \ + $(prefix)/lib/libgnunetutil.la + libgnunet_plugin_block_ext_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) + libgnunet_plugin_block_ext_la_DEPENDENCIES = \ + $(prefix)/lib/libgnunetblock.la + +Exercise: Write a block plugin that accepts all queries and all replies +but prints information about queries and replies when the respective +validation hooks are called. + +.. _Monitoring-the-DHT: + +Monitoring the DHT +~~~~~~~~~~~~~~~~~~ + +It is possible to monitor the functioning of the local DHT service. When +monitoring the DHT, the service will alert the monitoring program of any +events, both started locally or received for routing from another peer. +The are three different types of events possible: a GET request, a PUT +request or a response (a reply to a GET). + +Since the different events have different associated data, the API gets +3 different callbacks (one for each message type) and optional type and +key parameters, to allow for filtering of messages. When an event +happens, the appropriate callback is called with all the information +about the event. + +:: + + static void + get_callback (void *cls, + enum GNUNET_DHT_RouteOption options, + enum GNUNET_BLOCK_Type type, + uint32_t hop_count, + uint32_t desired_replication_level, + unsigned int path_length, + const struct GNUNET_PeerIdentity *path, + const struct GNUNET_HashCode * key) + { + } + + + static void + get_resp_callback (void *cls, + enum GNUNET_BLOCK_Type type, + const struct GNUNET_PeerIdentity *get_path, + unsigned int get_path_length, + const struct GNUNET_PeerIdentity *put_path, + unsigned int put_path_length, + struct GNUNET_TIME_Absolute exp, + const struct GNUNET_HashCode * key, + const void *data, + size_t size) + { + } + + + static void + put_callback (void *cls, + enum GNUNET_DHT_RouteOption options, + enum GNUNET_BLOCK_Type type, + uint32_t hop_count, + uint32_t desired_replication_level, + unsigned int path_length, + const struct GNUNET_PeerIdentity *path, + struct GNUNET_TIME_Absolute exp, + const struct GNUNET_HashCode * key, + const void *data, + size_t size) + { + } + + + monitor_handle = GNUNET_DHT_monitor_start (dht_handle, + block_type, + key, + &get_callback, + &get_resp_callback, + &put_callback, + cls); + +.. _Debugging-with-gnunet_002darm: + +Debugging with gnunet-arm +------------------------- + +Even if services are managed by ``gnunet-arm``, you can start them with +``gdb`` or ``valgrind``. For example, you could add the following lines +to your configuration file to start the DHT service in a ``gdb`` session +in a fresh ``xterm``: + +:: + + [dht] + PREFIX=xterm -e gdb --args + +Alternatively, you can stop a service that was started via ARM and run +it manually: + +:: + + $ gnunet-arm -k dht + $ gdb --args gnunet-service-dht -L DEBUG + $ valgrind gnunet-service-dht -L DEBUG + +Assuming other services are well-written, they will automatically +re-integrate the restarted service with the peer. + +GNUnet provides a powerful logging mechanism providing log levels +``ERROR``, ``WARNING``, ``INFO`` and ``DEBUG``. The current log level is +configured using the ``$GNUNET_FORCE_LOG`` environmental variable. The +``DEBUG`` level is only available if ``--enable-logging=verbose`` was +used when running ``configure``. More details about logging can be found +under https://docs.gnunet.org/#Logging. + +You should also probably enable the creation of core files, by setting +``ulimit``, and echo'ing ``1`` into +``/proc/sys/kernel/core\_uses\_pid``. Then you can investigate the core +dumps with ``gdb``, which is often the fastest method to find simple +errors. + +Exercise: Add a memory leak to your service and obtain a trace pointing +to the leak using ``valgrind`` while running the service from +``gnunet-service-arm``. + +.. _GNU-Free-Documentation-License: + +GNU Free Documentation License +============================== + +license, GNU Free Documentation License +Version 1.3, 3 November 2008 +:: + + Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + http://fsf.org/ + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +1. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document free in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the author + and publisher a way to get credit for their work, while not being + considered responsible for modifications made by others. + + This License is a kind of "copyleft", which means that derivative + works of the document must themselves be free in the same sense. It + complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to software + manuals; it can be used for any textual work, regardless of subject + matter or whether it is published as a printed book. We recommend + this License principally for works whose purpose is instruction or + reference. + +2. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice grants + a world-wide, royalty-free license, unlimited in duration, to use + that work under the conditions stated herein. The "Document", below, + refers to any such manual or work. Any member of the public is a + licensee, and is addressed as "you". You accept the license if you + copy, modify or distribute the work in a way requiring permission + under copyright law. + + A "Modified Version" of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A "Secondary Section" is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document's overall + subject (or to related matters) and contains nothing that could fall + directly within that overall subject. (Thus, if the Document is in + part a textbook of mathematics, a Secondary Section may not explain + any mathematics.) The relationship could be a matter of historical + connection with the subject or with related matters, or of legal, + commercial, philosophical, ethical or political position regarding + them. + + The "Invariant Sections" are certain Secondary Sections whose titles + are designated, as being those of Invariant Sections, in the notice + that says that the Document is released under this License. If a + section does not fit the above definition of Secondary then it is + not allowed to be designated as Invariant. The Document may contain + zero Invariant Sections. If the Document does not identify any + Invariant Sections then there are none. + + The "Cover Texts" are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice that + says that the Document is released under this License. A Front-Cover + Text may be at most 5 words, and a Back-Cover Text may be at most 25 + words. + + A "Transparent" copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has been + arranged to thwart or discourage subsequent modification by readers + is not Transparent. An image format is not Transparent if used for + any substantial amount of text. A copy that is not "Transparent" is + called "Opaque". + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, SGML + or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and the + machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The "Title Page" means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, "Title + Page" means the text near the most prominent appearance of the + work's title, preceding the beginning of the body of the text. + + The "publisher" means any person or entity that distributes copies + of the Document to the public. + + A section "Entitled XYZ" means a named subunit of the Document whose + title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + "Acknowledgements", "Dedications", "Endorsements", or "History".) To + "Preserve the Title" of such a section when you modify the Document + means that it remains a section "Entitled XYZ" according to this + definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and has + no effect on the meaning of this License. + +3. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You may + not use technical measures to obstruct or control the reading or + further copying of the copies you make or distribute. However, you + may accept compensation in exchange for copies. If you distribute a + large enough number of copies you must also follow the conditions in + section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + +4. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly have + printed covers) of the Document, numbering more than 100, and the + Document's license notice requires Cover Texts, you must enclose the + copies in covers that carry, clearly and legibly, all these Cover + Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on + the back cover. Both covers must also clearly and legibly identify + you as the publisher of these copies. The front cover must present + the full title with all words of the title equally prominent and + visible. You may add other material on the covers in addition. + Copying with changes limited to the covers, as long as they preserve + the title of the Document and satisfy these conditions, can be + treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto adjacent + pages. + + If you publish or distribute Opaque copies of the Document numbering + more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will remain + thus accessible at the stated location until at least one year after + the last time you distribute an Opaque copy (directly or through + your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + +5. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document under + the conditions of sections 2 and 3 above, provided that you release + the Modified Version under precisely this License, with the Modified + Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in the + Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title as a + previous version if the original publisher of that version gives + permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in the + Modified Version, together with at least five of the principal + authors of the Document (all of its principal authors, if it has + fewer than five), unless they release you from this requirement. + + C. State on the Title page the name of the publisher of the Modified + Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified Version + under the terms of this License, in the form shown in the + Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document's license + notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled "History", Preserve its Title, and + add to it an item stating at least the title, year, new authors, + and publisher of the Modified Version as given on the Title Page. + If there is no section Entitled "History" in the Document, create + one stating the title, year, authors, and publisher of the + Document as given on its Title Page, then add an item describing + the Modified Version as stated in the previous sentence. + + J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. + + K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered in + their text and in their titles. Section numbers or the equivalent + are not considered part of the section titles. + + M. Delete any section Entitled "Endorsements". Such a section may + not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version's + license notice. These titles must be distinct from any other section + titles. + + You may add a section Entitled "Endorsements", provided it contains + nothing but endorsements of your Modified Version by various + parties---for example, statements of peer review or that the text + has been approved by an organization as the authoritative definition + of a standard. + + You may add a passage of up to five words as a Front-Cover Text, and + a passage of up to 25 words as a Back-Cover Text, to the end of the + list of Cover Texts in the Modified Version. Only one passage of + Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old one, + on explicit permission from the previous publisher that added the + old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + +6. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your combined + work in its license notice, and that you preserve all their Warranty + Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the original + author or publisher of that section if known, or else a unique + number. Make the same adjustment to the section titles in the list + of Invariant Sections in the license notice of the combined work. + + In the combination, you must combine any sections Entitled "History" + in the various original documents, forming one section Entitled + "History"; likewise combine any sections Entitled + "Acknowledgements", and any sections Entitled "Dedications". You + must delete all sections Entitled "Endorsements." + +7. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert a + copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + +8. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other separate + and independent documents or works, in or on a volume of a storage + or distribution medium, is called an "aggregate" if the copyright + resulting from the compilation is not used to limit the legal rights + of the compilation's users beyond what the individual works permit. + When the Document is included in an aggregate, this License does not + apply to the other works in the aggregate which are not themselves + derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document's Cover Texts may be placed on + covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket the + whole aggregate. + +9. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled "Acknowledgements", + "Dedications", or "History", the requirement (section 4) to Preserve + its Title (section 1) will typically require changing the actual + title. + +10. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, and + will automatically terminate your rights under this License. + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the + copyright holder fails to notify you of the violation by some + reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from + that copyright holder, and you cure the violation prior to 30 days + after your receipt of the notice. + + Termination of your rights under this section does not terminate the + licenses of parties who have received copies or rights from you + under this License. If your rights have been terminated and not + permanently reinstated, receipt of a copy of some or all of the same + material does not give you any rights to use it. + +11. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation License from time to time. Such new + versions will be similar in spirit to the present version, but may + differ in detail to address new problems or concerns. See + http://www.gnu.org/copyleft/. + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered version + of this License "or any later version" applies to it, you have the + option of following the terms and conditions either of that + specified version or of any later version that has been published + (not as a draft) by the Free Software Foundation. If the Document + does not specify a version number of this License, you may choose + any version ever published (not as a draft) by the Free Software + Foundation. If the Document specifies that a proxy can decide which + future versions of this License can be used, that proxy's public + statement of acceptance of a version permanently authorizes you to + choose that version for the Document. + +12. RELICENSING + + "Massive Multiauthor Collaboration Site" (or "MMC Site") means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. A + "Massive Multiauthor Collaboration" (or "MMC") contained in the site + means any set of copyrightable works thus published on the MMC site. + + "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + "Incorporate" means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is "eligible for relicensing" if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently incorporated + in whole or in part into the MMC, (1) had no cover texts or + invariant sections, and (2) were thus incorporated prior to November + 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +**ADDENDUM: How to use this License for your documents** + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + +:: + + Copyright (C) year your name. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + +:: + + with the Invariant Sections being list their titles, with + the Front-Cover Texts being list, and with the Back-Cover Texts + being list. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software.