Provided by: gnunet_0.17.4-1_amd64 bug

NAME

       gnunet - GNUnet

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 volunteers  or  people  paid  to  do
       fundamental  research.  At  this  stage,  GNUnet  remains  an  experimental  system  where
       significant parts of the software lack a  reasonable  degree  of  professionalism  in  its
       implementation.  Furthermore,  we  are  aware of a significant number of existing bugs and
       critical design flaws, as some unfortunate early design decisions remain to be  rectified.
       There are still known open problems; GNUnet remains an active research project.

       The  project  was  started  in  2001  when  some  initial  ideas  for  improving Freenet’s
       file-sharing turned out to be too radical to be easily realized within the  scope  of  the
       existing  Freenet  project.  We lost our first contributor on 11.9.2001 as the contributor
       realized that privacy may help terrorists. The rest of the team concluded that it was  now
       even  more  important  to fight for civil liberties. The first release was called “GNet” –
       already with the name GNUnet in mind, but without the blessing of GNU we did not  dare  to
       call  it  GNUnet  immediately.  A  few months after the first release we contacted the GNU
       project, happily agreed to their governance model and became an official GNU package.

       Within the first year, we created  GNU  libextractor,  a  helper  library  for  meta  data
       extraction  which has been used by a few other projects as well. 2003 saw the emergence of
       pluggable  transports,  the  ability  for  GNUnet  to   use   different   mechanisms   for
       communication,  starting  with TCP, UDP and SMTP (support for the latter was later dropped
       due to a lack of maintenance). In 2005, the project first started  to  evolve  beyond  the
       original  file-sharing  application  with a first simple P2P chat. In 2007, we created GNU
       libmicrohttpd to support a pluggable transport based on HTTP. In  2009,  the  architecture
       was radically modularized into the multi-process system that exists today. Coincidentally,
       the first version of the ARM service (ARM: Automatic Restart Manager)  was  implemented  a
       day  before  systemd  was announced. From 2009 to 2014 work progressed rapidly thanks to a
       significant research grant from the  Deutsche  Forschungsgesellschaft.  This  resulted  in
       particular  in  the  creation of the R5N DHT, CADET, ATS and the GNU Name System. In 2010,
       GNUnet was selected as the basis for the secushare online social network, resulting  in  a
       significant  growth  of  the  core  team.  In  2013,  we launched GNU Taler to address the
       challenge of convenient and privacy-preserving online payments. In 2015, the  pretty  Easy
       privacy  (pEp)  project  announced  that  they will use GNUnet as the technology for their
       meta-data protection layer, ultimately resulting in GNUnet e.V.  entering  into  a  formal
       long-term  collaboration  with  the  pEp  Foundation.   In 2016, Taler Systems SA, a first
       startup using GNUnet technology, was founded with support from the community.

       GNUnet is not merely a technical project, but also  a  political  mission:  like  the  GNU
       project as a whole, we are writing software to achieve political goals with a focus on the
       human right of  informational  self-determination.  Putting  users  in  control  of  their
       computing  has  been  the  core  driver of the GNU project. With GNUnet we are focusing on
       informational  self-determination  for  collaborative  computing  and  communication  over
       networks.

       The  Internet is shaped as much by code and protocols as it is by its associated political
       processes (IETF, ICANN, IEEE, etc.). Similarly its flaws are not limited to  the  protocol
       design.  Thus, technical excellence by itself will not suffice to create a better network.
       We also need to build a community that is wise, humble and has a sense of humor to 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 ultimately, the GNU project  appoints  the
       GNU  maintainer  and  can overrule decisions made by the GNUnet maintainer. Similarly, the
       GNUnet maintainer can overrule any decisions made by  individual  developers.   Still,  in
       practice neither has happened in the last 20 years for GNUnet, and we hope to keep it that
       way.

       The current maintainers of GNUnet are:

       • Christian GrothoffMartin Schanzenbach

       The GNUnet project is supported by GNUnet e.V., a German association where  any  developer
       can  become  a  member.  GNUnet  e.V.  serves  as a legal entity to hold the copyrights to
       GNUnet. GNUnet e.V. may also  choose  to  pay  for  project  resources,  and  can  collect
       donations  as  well  as  choose to adjust the license of the software (with the constraint
       that it has 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 exchange. We value free speech above state
       interests  and intellectual monopoly. GNUnet’s long-term goal is to serve as a development
       platform for the next generation of Internet protocols.

       Participants are encouraged to contribute at least as much resources (storage,  bandwidth)
       to  the  network  as  they  consume,  so that their participation does not have a negative
       impact on other users.

   Design Principles
       These are the GNUnet design principles, in order of importance:

       • GNUnet must be implemented as Free  Software  —  This  means  that  you  have  the  four
         essential  freedoms:  to run the program, to study and change the program in source code
         form,  to  redistribute  exact  copies,  and  to  distribute  modified   versions.    (‐
         https://www.gnu.org/philosophy/free-sw.html).

       • GNUnet must minimize the amount of personally identifiable information exposed.

       • GNUnet   must  be  fully  distributed  and  resilient  to  external  attacks  and  rogue
         participants.

       • GNUnet  must  be  self-organizing  and  not  depend  on  administrators  or  centralized
         infrastructure.

       • GNUnet  must  inform  the  user  which  other  participants  have  to  be  trusted  when
         establishing private communications.

       • GNUnet must be open and permit new peers to join.

       • GNUnet must support a diverse range of applications and devices.

       • GNUnet must use compartmentalization to protect sensitive information.

       • The GNUnet architecture must be resource efficient.

       • GNUnet must provide incentives for peers to contribute more resources 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, track, monitor or censor users
       activities. The GNUnet protocols also make it as hard as possible to disrupt operations by
       participating in the network with malicious intent.

       Analyzing  participant’s  activities  becomes  more  difficult  as the number of peers and
       applications that generate traffic on the network grows, even if  the  additional  traffic
       generated is not related to anonymous communication. This is one of the reasons why GNUnet
       is developed as a peer-to-peer framework where many applications share the lower layers of
       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 device with limited battery for
       example might choose not to relay traffic for other participants.

       For certain applications like file-sharing GNUnet allows participants to trade degrees  of
       anonymity  in  exchange  for  increased  efficiency.   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 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 DH (Diffie—Hellman) key exchange using
       ephemeral elliptic curve cryptography. The ephemeral  ECC  (Elliptic  Curve  Cryptography)
       keys  are  signed  using  ECDSA.  The shared secret from ECDHE is used to create a pair of
       session keys (using HKDF) which are then used to encrypt the communication between the two
       peers  using  both  256-bit  AES  (Advanced Encryption Standard) and 256-bit Twofish (with
       independently derived secret keys). As only the two participating hosts  know  the  shared
       secret, this authenticates each packet without requiring signatures each time. GNUnet uses
       SHA-512 (Secure Hash Algorithm) hash codes to verify the integrity of messages.

       In GNUnet, the identity of a host is its public key. For  that  reason,  man-in-the-middle
       attacks  will  not  break the authentication or accounting goals. Essentially, for GNUnet,
       the IP of the host has nothing to do with the identity of the host. As the public  key  is
       the  only  thing  that  truly  matters,  faking an IP, a port or any other property of the
       underlying transport protocol is irrelevant. In fact, GNUnet peers can  use  multiple  IPs
       (IPv4  and  IPv6)  on  multiple ports — or even not use the IP protocol at all (by running
       directly on layer 2).

       GNUnet uses a special type of message to communicate a binding between public  (ECC)  keys
       to  their  current  network  address.  These  messages  are commonly called HELLOs or peer
       advertisements. They contain the public key of the peer and its current network  addresses
       for  various  transport  services. A transport service is a special kind of shared library
       that provides (possibly unreliable, out-of-order) message delivery between peers. For  the
       UDP and TCP transport services, a network address is an IP and a port. GNUnet can also use
       other transports (HTTP, HTTPS, WLAN, etc.) which use various  other  forms  of  addresses.
       Note that any node can have many different active transport services at the same time, and
       each of these can have a different addresses. Binding messages expire after at most a week
       (the  timeout  can  be  shorter  if  the  user  configures  the  node appropriately). This
       expiration ensures that the network will eventually get rid of outdated advertisements.

       For more information, refer to the following paper:

       Ronaldo A. Ferreira, Christian Grothoff, and Paul Ruth. A Transport Layer Abstraction  for
       Peer-to-Peer  Networks Proceedings of the 3rd 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 intentions of an attacker and  a  freeloader
       are  different, their effect on the network is the same; they both render it useless. Most
       simple attacks on networks such as Gnutella involve flooding  the  network  with  traffic,
       particularly with queries that are, in the worst case, multiplied by the network.

       In  order  to  ensure  that freeloaders or attackers have a minimal impact on the network,
       GNUnet’s file-sharing implementation (FS) tries to distinguish good  (contributing)  nodes
       from  malicious (freeloading) nodes. In GNUnet, every file-sharing node keeps track of the
       behavior of every other node it has been in contact with. Many requests (depending on  the
       application)  are transmitted with a priority (or importance) level. That priority is used
       to establish how important the sender believes this request is. If a peer responds  to  an
       important  request,  the recipient will increase its trust in the responder: the responder
       contributed resources. If a peer  is  too  busy  to  answer  all  requests,  it  needs  to
       prioritize.  For  that,  peers do not take the priorities of the requests received at face
       value. First, they check how much they trust the sender, and depending on that  amount  of
       trust  they  assign the request a (possibly lower) effective priority. Then, they drop the
       requests with the lowest effective priority to satisfy their  resource  constraints.  This
       way,  GNUnet’s economic model ensures that nodes that are not currently considered to have
       a surplus in contributions will not be served if the network load is high.

       For more information, refer to the following paper: Christian Grothoff.   An  Excess-Based
       Economic  Model  for  Resource Allocation in Peer-to-Peer 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 neighbor of a peer that is the
       corresponding sender or recipient of a message  may  know  its  contents,  and  even  then
       application protocols may place further restrictions on that knowledge. In order to ensure
       confidentiality, GNUnet uses link encryption, that is each message exchanged  between  two
       peers  is encrypted using a pair of keys only known to these two peers. Encrypting traffic
       like  this  makes  any  kind  of  traffic  analysis  much  harder.  Naturally,  for   some
       applications,  it  may  still be desirable if even neighbors cannot determine the concrete
       contents  of  a  message.  In  GNUnet,  this  problem  is  addressed   by   the   specific
       application-level  protocols.  See  for example the following sections: Anonymity, see How
       file-sharing achieves Anonymity, and see Deniability.

   Anonymity
       Providing anonymity  for  users  is  the  central  goal  for  the  anonymous  file-sharing
       application.  Many  other  design  decisions  follow in the footsteps of this requirement.
       Anonymity is never absolute. While there are various  scientific  metrics  (Claudia  Díaz,
       Stefaan  Seys,  Joris  Claessens, and Bart Preneel. Towards measuring anonymity. 2002.  (‐
       https://git.gnunet.org/bibliography.git/plain/docs/article-89.pdf)) that can help quantify
       the  level  of  anonymity  that  a  given  mechanism  provides,  there is no such thing as
       “complete anonymity”.

       GNUnet’s file-sharing implementation allows users to select for each  operation  (publish,
       search,  download) the desired level of anonymity.  The metric used is based on the amount
       of cover traffic needed to hide the request.

       While there is no clear way to relate the amount of available cover traffic to traditional
       scientific  metrics  such  as the anonymity set or information leakage, it is probably the
       best metric available to a peer with a purely local view of the world, in that it does not
       rely on unreliable external information or a particular adversary model.

       The  default  anonymity  level  is  1, which uses anonymous routing but imposes no minimal
       requirements on cover traffic. It is  possible  to  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 indirections. This is not sufficient
       if the adversary uses traffic analysis. The threat model used for anonymous  file  sharing
       in  GNUnet assumes that the adversary is quite powerful. In particular, we assume that the
       adversary can see all the traffic on the Internet. And while we assume that the  adversary
       can not break our encryption, we assume that the adversary has many participating nodes in
       the network and that it can thus see  many  of  the  node-to-node  interactions  since  it
       controls some of the nodes.

       The  system  tries  to  achieve anonymity based on the idea that users can be anonymous if
       they can hide their actions in the traffic created by other users. Hiding actions  in  the
       traffic  of  other  users  requires  participating  in  the  traffic,  bringing  back  the
       traditional technique of using indirection  and  source  rewriting.  Source  rewriting  is
       required to gain anonymity since otherwise an adversary could tell if a message originated
       from a host by looking at the source address. If all packets look like they originate from
       one  node,  the  adversary can not tell which ones originate from that node and which ones
       were routed. Note that in this mindset, any node can decide to break the  source-rewriting
       paradigm without violating the protocol, as this only reduces the amount of traffic that a
       node can hide its own traffic in.

       If we want to hide our actions in the traffic of other nodes, we  must  make  our  traffic
       indistinguishable  from  the traffic that we route for others. As our queries must have us
       as the receiver of the reply (otherwise they would be useless), we must put  ourselves  as
       the  receiver of replies that actually go to other hosts; in other words, we must indirect
       replies. Unlike other systems, in anonymous file-sharing as implemented on top  of  GNUnet
       we  do not have to indirect the replies if we don’t think we need more traffic to hide our
       own actions.

       This increases the efficiency of the network as we can indirect less  under  higher  load.
       Refer  to  the  following  paper  for  more:  Krista Bennett and Christian Grothoff. GAP —
       practical  anonymous  networking.  In   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 protection against identification.

       The messaging service allows the use of an anonymous ego for the signing and  verification
       process  of  messages  instead of a unique ego. This anonymous ego is a publicly known key
       pair which is shared between all peers in GNUnet.

       Using this ego only ensures that individual  messages  alone  can’t  identify  its  sender
       inside  of a messenger room. It should be clarified that the route of the traffic for each
       message can still be tracked to identify the senders peer inside of a  messenger  room  if
       the threat agent controls certain peers hosting the room.

       Also  opening  a  room  in the messenger service will potentially match your peer identity
       with the internal member identity  from  the  messenger  service.  So  despite  using  the
       anonymous  ego  you  can  reveal  your peer 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, if the  intermediaries  can  find  out
       which  queries or which content they are processing, a strong adversary could try to force
       them to censor certain materials.

       With the file-encoding used by GNUnet’s anonymous  file-sharing,  this  problem  does  not
       arise.  The reason is that queries and replies are transmitted in an encrypted format such
       that intermediaries cannot tell what the query is for or what the content is  about.  Mind
       that  this is not the same encryption as the link-encryption between the nodes. GNUnet has
       encryption on the network layer (link  encryption,  confidentiality,  authentication)  and
       again on the application layer (provided by gnunet-publish, gnunet-download, gnunet-search
       and gnunet-fs-gtk).

       Refer to the following paper  for  more:  Christian  Grothoff,  Krista  Grothoff,  Tzvetan
       Horozov,  and  Jussi  T. Lindgren. An Encoding for 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 is generated along with a private
       key when the peer is started for the first time. While the identity is binary data, it  is
       often  expressed  as an ASCII string. For example, the following is a peer identity as you
       might see it in various places:

          UAT1S6PMPITLBKSJ2DGV341JI6KF7B66AC4JVCN9811NNEGQLUN0

       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 private key. When you create a record
       in a DNS zone, that information is stored in your nameserver.  Anyone  trying  to  resolve
       your domain then gets pointed (hopefully) by the centralised authority to your nameserver.
       Whereas GNS, being fully decentralized by design, stores  that  information  in  DHT.  The
       validity of the records is assured cryptographically, by signing them with the private key
       of the respective zone.

       Anyone trying to resolve records in a zone of your domain can then verify the signature of
       the  records they get from the DHT and be assured that they are indeed from the respective
       zone. To  make  this  work,  there  is  a  1:1  correspondence  between  zones  and  their
       public-private key pairs. So when we talk about the owner of a GNS zone, that’s really the
       owner of the private key. And a user  accessing  a  zone  needs  to  somehow  specify  the
       corresponding public key first.

       For more information, refer to the following paper:

       Matthias  Wachs,  Martin  Schanzenbach,  and  Christian  Grothoff. A Censorship-Resistant,
       Privacy-Enhancing  and  Fully  Decentralized  Name  System.   In   proceedings   of   13th
       International   Conference   on   Cryptology  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 correspond to “pseudonyms” or “real-world
       identities”. Technically an ego is first of all a key pair of a public- and private-key.

INSTALLATION

       This guide is intended for those who want to install GNUnet from source.  For instructions
       on how to install GNUnet as a binary package please refer to the official documentation of
       your operating system or package manager.

       For understanding this guide properly it is important to know that there are two different
       ways of running GNUnet:

       • the single-user setup

       • the multi-user setup

       The  latter  variant  has  a  better  security model and requires extra preparation before
       running make install and a different configuration.  Beginners who want to quickly try out
       GNUnet can use the single-user setup.

   Dependencies
       GNUnet needs few libraries and applications for being able to run and another few optional
       ones for using certain features. Preferably  they  should  be  installed  with  a  package
       manager.

       The mandatory libraries and applications are

       • autoconf 2.59 or above (when building from git)

       • automake 1.11.1 or above (when building from git)

       • recutils 1.0 or above (when building from git)

       • gettext

       • glibc (read below, other libcs work)

       • GnuTLS 3.2.12 or above, recommended to be linked against libunbound

       • GNU make 4.0 or higher (other make implementations do work)

       • iptables (on Linux systems)

       • libtool 2.2 or above

       • libltdl (part of libtool)

       • libgcrypt 1.6 or above

       • libidn2 or libidn

       • libmicrohttpd 0.9.63 or above

       • libunistring

       • libjansson

       • libjose (optional, for reclaimID)

       • libgmp

       • libgnurl or libcurl (libcurl has to be linked to GnuTLS) 7.35.0 or above

       • Texinfo 5.2 or above (for building the documentation)

       • Texlive 2012 or above (for building the documentation, and for gnunet-bcd)

       • makeinfo 4.8 or above

       • pkgconf (or pkg-config)

       • zlib

       Glibc is required for certain NSS features:

          One mechanism of integrating GNS with legacy applications via NSS is
          not available if this is disabled. But applications that don't use the
          glibc for NS resolution won't work anyway with this, so little is lost
          on *BSD systems.
          GNS via direct use or via the HTTP or DNS proxies is unaffected.

       Other  libcs  should  work, the resulting builds just don’t include the glibc NSS specific
       code.   One   example   is   the   build   against   NetBSD’s   libc   as   detailed    in
       https://bugs.gnunet.org/view.php?id=5605.

       In addition GNUnet needs at least one of these three databases (at the minimum sqlite3)

       • sqlite + libsqlite 3.8 or above (the default, requires no further configuration)

       • postgres + libpq

       • mysql + libmysqlclient

       These are the dependencies only required for certain features

       • miniupnpc (for traversing NAT boxes more reliably)

       • libnss

       • libopus (for running the GNUnet conversation telephony application)

       • libogg (for running the GNUnet conversation telephony application)

       • gstreamer OR libpulse (for running the GNUnet conversation telephony application)

       • bluez (for bluetooth support)

       • libextractor (optional but highly recommended, read below)

       • texi2mdoc (for automatic mdoc generation)

       • perl5 for some utilities (which are not installed)

       About libextractor being optional:

          While libextractor ("LE") is optional, it is recommended to build gnunet
          against it. If you install it later, you won't benefit from libextractor.
          If you are a distributor, we recommend to split LE into basis + plugins
          rather than making LE an option as an afterthought by the user.  LE
          itself is very small, but its dependency chain on first, second, third
          etc level can be big.  There is a small effect on privacy if your LE
          build differs from one which includes all plugins (plugins are build as
          shared objects): if users publish a directory with a mixture of file
          types (for example mpeg, jpeg, png, gif) the configuration of LE could
          leak which plugins are installed for which filetypes are not providing
          more details.  However, this leak is just a minor concern.

       These are the test-suite requirements:

       • python3.6 or higher

       • gnunet (installation first)

       • some core-utils: which(1), bc(1), curl(1), sed(1), awk(1), etc.

       • a shell (very few Bash scripts, the majority are POSIX sh scripts)

       These are runtime requirements:

       • nss (the certutil binary, for gnunet-gns-proxy-setup-ca)

       • openssl (openssl binary, for gnunet-gns-proxy-setup-ca)

   Getting the Source Code
       You can either download the source code using git (you obviously need git installed) or as
       an archive.

       Using git type

          $ git clone https://git.gnunet.org/gnunet.git

       The archive can be found at https://ftpmirror.gnu.org/gnu/gnunet/.   Extract  it  using  a
       graphical archive tool or tar:

          tar xf gnunet-0.17.1-26-g233ec6111.tar.gz

       In the next chapter we will assume that the source code is available in the home directory
       at ~/gnunet.

   Create user and groups for the system services
       For single-user setup this section can be skipped

       The multi-user setup means that there are system services, which are run once per  machine
       as a dedicated system user (called gnunet) and user services which can be started by every
       user who wants to use GNUnet applications. The user services communicate with  the  system
       services over unix domain sockets. To gain permissions to read and write those sockets the
       users running GNUnet applications will need to be in the gnunet  group.  In  addition  the
       group gnunetdns may be needed (see below).

       Create user gnunet who is member of the group gnunet (automatically created) and specify a
       home directory where the GNUnet services will store persistent data  such  as  information
       about peers.

          $ sudo useradd --system --home-dir /var/lib/gnunet --create-home gnunet

       Now add your own user to the gnunet group:

          $ sudo usermod -aG gnunet <user>

       Create  a group gnunetdns. This allows using setgid in a way that only the DNS service can
       run the gnunet-helper-dns binary. This is only needed if system-wide DNS interception will
       be used. For more information see Configuring system-wide DNS interception.

          $ sudo groupadd gnunetdns

   Preparing and Compiling the Source Code
       For  preparing  the source code for compilation a bootstrap script and configure has to be
       run from the source code directory. When running configure, options can  be  specified  to
       customize the compilation and installation process. For details execute:

          $ ./configure --help

       The  following example configures the installation prefix /usr/local and disables building
       the documentation

          $ cd ~/gnunet
          $ ./bootstrap
          $ ./configure --prefix=/usr/local --disable-documentation

       After running the bootstrap script and configure  successfully  the  source  code  can  be
       compiled and the compiled binaries can be installed using:

          $ make
          $ make install

       The  latter  command  may need to be run as root (or with sudo) because some binaries need
       the suid bit set. Without that  some  features  (e.g. the  VPN  service,  system-wide  DNS
       interception, NAT traversal using ICMP) will not work.

   NSS plugin (optional)
       NOTE: The installation of the NSS plugin is only necessary if GNS resolution shall be used
       with legacy applications (that only support DNS) and if you cannot do not want to use  the
       DNS2GNS service.

       One  important  library  is the GNS plugin for NSS (the name services switch) which allows
       using GNS (the GNU name system) in the normal DNS resolution  process.  Unfortunately  NSS
       expects  it  in a specific location (probably /lib) which may differ from the installation
       prefix (see --prefix option in the previous section). This is why the  plugin  has  to  be
       installed manually.

       Find the directory where nss plugins are installed on your system, e.g.:

          $ ls -l /lib/libnss_*
          /lib/libnss_mymachines.so.2
          /lib/libnss_resolve.so.2
          /lib/libnss_myhostname.so.2
          /lib/libnss_systemd.so.2

       Copy the GNS NSS plugin to that directory:

          cp ~/gnunet/src/gns/nss/.libs/libnss_gns.so.2 /lib

       Now,  to  activate  the  plugin, you need to edit your /etc/nsswitch.conf where you should
       find a line like this:

          hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4

       The exact details may differ a bit, which is fine.  Add  the  text  gns  [NOTFOUND=return]
       after files:

          hosts: files gns [NOTFOUND=return] mdns4_minimal [NOTFOUND=return] dns mdns4

   Installing the GNS Certificate Authority (Optional)
       NOTE: Installing the GNS certificate authority is only necessary if GNS shall be used in a
       browser and if you cannot or do not want to use the DNS2GNS service.

       The GNS Certificate authority can provide TLS certificates for GNS names while downloading
       webpages  from  legacy  webservers. This allows browsers to use HTTPS in combinations with
       GNS name resolution.

       To install it execute the GNS CA-setup script. So far Firefox and Chromium are supported.

          $ gnunet-gns-proxy-setup-ca

       A local proxy server, that takes care of the name  resolution  and  provides  certificates
       on-the-fly needs to be started:

          $ /usr/lib/gnunet/libexec/gnunet-gns-proxy

       Now   GNS  should  work  in  browsers  that  are  configured  to  use  a  SOCKS  proxy  on
       localhost:7777.

   Minimal configuration
       GNUnet needs a configuration file to start (see Config file format). For  the  single-user
       setup an empty file is sufficient:

          $ touch ~/.config/gnunet.conf

       For the multi-user setup we need an extra config file for the system services. The default
       location is /etc/gnunet.conf. The minimal content of that file which activates the  system
       services roll is:

          [arm]
          START_SYSTEM_SERVICES = YES
          START_USER_SERVICES = NO

       The  config  file  for  the  user  services  (~/.config/gnunet.conf)  needs  the  opposite
       configuration to activate the user services roll:

          [arm]
          START_SYSTEM_SERVICES = NO
          START_USER_SERVICES = YES

USER MANUAL

       This tutorial is supposed to give a first introduction for users trying  to  do  something
       real  with GNUnet. Installation and configuration are specifically outside of the scope of
       this tutorial. Instead, we start by briefly checking that the installation works, and then
       dive  into  uncomplicated,  concrete  practical things that can be done with the framework
       provided by GNUnet.

       In short, this chapter of the “GNUnet Reference Documentation” will show you  how  to  use
       the various peer-to-peer applications of the GNUnet system. As GNUnet evolves, we will add
       new sections for the various applications that are being created.

       Comments on the content of this chapter, and extensions of it are always welcome.

   Starting and stopping
       Prior to using any GNUnet-based application, one has to start a node:

          $ gnunet-arm -s

       To stop GNUnet:

          $ gnunet-arm -e

       You can usually find the logs under ~/.cache/gnunet and all files such  as  databases  and
       private keys in ~/.local/share/gnunet.

       The list of running services can be displayed using the -I option.  It should look similar
       to this example:

          $ gnunet-arm -I
          Running services:
          topology (gnunet-daemon-topology)
          nat (gnunet-service-nat)
          vpn (gnunet-service-vpn)
          gns (gnunet-service-gns)
          cadet (gnunet-service-cadet)
          namecache (gnunet-service-namecache)
          hostlist (gnunet-daemon-hostlist)
          revocation (gnunet-service-revocation)
          ats (gnunet-service-ats)
          peerinfo (gnunet-service-peerinfo)
          zonemaster (gnunet-service-zonemaster)
          zonemaster-monitor (gnunet-service-zonemaster-monitor)
          dht (gnunet-service-dht)
          namestore (gnunet-service-namestore)
          set (gnunet-service-set)
          statistics (gnunet-service-statistics)
          nse (gnunet-service-nse)
          fs (gnunet-service-fs)
          peerstore (gnunet-service-peerstore)
          core (gnunet-service-core)
          rest (gnunet-rest-server)
          transport (gnunet-service-transport)
          datastore (gnunet-service-datastore)

       For the multi-user setup first the system services need to be started as the system  user,
       i.e. the  user  gnunet needs to execute gnunet-arm -s. This should be done by the system’s
       init system. Then the user who wants to start GNUnet applications has  to  run  gnunet-arm
       -s, too. It is recommended to automate this, e.g. using the user’s crontab.

       First,  you should launch the peer information tool. You can do this from the command-line
       by typing:

          $ gnunet-peerinfo

       Once you have done this, you will see a list of known  peers.  If  hardly  any  peers  are
       listed,  there  is  likely  a  problem with your network configuration. You can also check
       directly connected peers with:

          $ gnunet-core

       This should return (at least) one established connection peer.  Otherwise, again, there is
       likely a problem with your network configuration.

   The GNU Name System
       The  GNU  Name System (GNS) is secure and decentralized naming system. It allows its users
       to register names as top-level domains (TLDs) and resolve other  namespaces  within  their
       TLDs.

       GNS is designed to provide:

       • Censorship resistance

       • Query privacy

       • Secure name resolution

       • Compatibility with DNS

       For  the  initial configuration and population of your GNS installation, please follow the
       GNS setup instructions. The remainder of this chapter will provide some background on  GNS
       and then describe how to use GNS in more detail.

       Unlike  DNS,  GNS  does  not  rely on central root zones or authorities.  Instead any user
       administers their own root and can can create arbitrary name value  mappings.  Furthermore
       users can delegate resolution to other users’ zones just like DNS NS records do. Zones are
       uniquely  identified  via  public  keys  and  resource  records  are  signed   using   the
       corresponding  public  key.  Delegation  to another user’s zone is done using special PKEY
       records and petnames. A petname is a name that can be freely  chosen  by  the  user.  This
       results  in  non-unique name-value mappings as www.bob to one user might be www.friend for
       someone else.

   Start Zones
       In the default configuration, there are two zones defined and shipped with GNUnet:

       The first is “gnunet.org”, which points to the authoritate zone of the GNUnet project.  It
       can be used to resolve, for example, “www.gnunet.org”.

       “.pin”  is another default zone which points to a special zone also managed by gnunet.org.
       Users   may   register   submodomains    on    a    first-come    first-served-basis    at
       https://fcfs.gnunet.org.

       Use  gnunet-config  -s  gns  to view the GNS configuration, including all configured zones
       that are operated by other users. The respective configuration entry names  start  with  a
       “.”, e.g. “.pin”.

       You  can configure any number of top-level domains, and point them to the respective zones
       of your friends! For this, simply obtain the respective public key  (you  will  learn  how
       below) and extend the configuration:

          $ gnunet-config -s gns -o .myfriend -V PUBLIC_KEY

   Zones and Egos
       In  GNUnet,  identity management is about managing egos. Egos can correspond to pseudonyms
       or real-world identities. If you value your privacy, you are encouraged  to  use  separate
       egos for separate activities.

       Technically,  an  ego is first of all a public-private key pair, and thus egos also always
       correspond to a GNS zone. Egos are managed by the IDENTITY service. Note that this service
       has  nothing  to  do  with  the peer identity. The IDENTITY service essentially stores the
       private keys under human-readable names, and keeps a mapping of which private  key  should
       be used for particular important system functions.

       You  probably  should  create  at least one zone of your own. You can create any number of
       zones using the gnunet-identity tool using:

          $ gnunet-identity --create="myzone"

       Henceforth, on your system you control the TLD “myzone”.

       All of your zones can be listed (displayed) using the gnunet-identity command line tool as
       well:

          $ gnunet-identity --display

   Maintaining Zones
       Now   you   can   add   (or   edit,  or  remove)  records  in  your  GNS  zone  using  the
       gnunet-namestore-gtk GUI or using the gnunet-namestore command-line tool. In either  case,
       your   records   will   be   stored   in   an   SQL   database   under   control   of  the
       gnunet-service-namestore. Note that if multiple users use one peer, the namestore database
       will  include  the  combined  records of all users. However, users will not be able to see
       each other’s records if they are marked as private.

       To provide a short example for editing your own zone, suppose you have your own web server
       with  the  IP  1.2.3.4.  Then  you  can  put an A record (A records in DNS are for IPv4 IP
       addresses) into your local zone “myzone” using the command:

          $ gnunet-namestore -z myzone -a -n www -t A -V 1.2.3.4 -e 1d

       Similar commands will work for other types of DNS and  GNS  records,  the  syntax  largely
       depending  on  the  type  of  the record. Naturally, most users may find editing the zones
       using the gnunet-namestore-gtk GUI to be easier.

       Each zone in GNS has a public-private key. Usually, gnunet-namestore and gnunet-setup will
       access  your  private  key  as necessary, so you do not have to worry about those. What is
       important is your public key (or rather, the hash of your public key), as you will  likely
       want to give it to others so that they can securely link to you.

       A  central operation in GNS is the ability to securely delegate to other zones. Basically,
       by adding a delegation you make all  of  the  names  from  the  other  zone  available  to
       yourself. This section describes how to create delegations.

       Suppose  you  have  a  friend  who you call ’bob’ who also uses GNS. You can then delegate
       resolution of names to Bob’s zone by adding a PKEY record to their local zone:

          $ gnunet-namestore -a -n bob --type PKEY -V XXXX -e 1d -z myzone

       Note that “XXXX” in the command above must be replaced with the hash of Bob’s  public  key
       (the  output  your  friend  obtained  using  the gnunet-identity command from the previous
       section and told  you,  for  example  by  giving  you  a  business  card  containing  this
       information as a QR code).

       Assuming  Bob has an “A” record for their website under the name of “www” in his zone, you
       can then access Bob’s website under “www.bob.myzone” — as well as any (public) GNS  record
       that  Bob  has  in  their  zone by replacing www with the respective name of the record in
       Bob’s zone.

       Furthermore, if Bob has themselves a (public) delegation to Carol’s  zone  under  “carol”,
       you  can access Carol’s records under “NAME.carol.bob.myzone” (where “NAME” is the name of
       Carol’s record you want to access).

   Resolving GNS records
       Next, you should try resolving your own GNS records. The method we found to  be  the  most
       uncomplicated  is  to do this by explicitly resolving using gnunet-gns. For this exercise,
       we will assume that you used the string “gnu” for the pseudonym (or  label)  of  your  GNS
       zone.  If you used something else, replace “.gnu” with your real pseudonym in the examples
       below.

       In the shell, type:

          $ gnunet-gns -u www.gnunet.org
          www.gnunet.org:
          Got `A' record: ...

       That shows that resolution works, once GNS is integrated with the application.

   Integration with Browsers (DNS2GNS service)
       Most OSes allow you to either modify your /etc/resolv.conf directly or through resolvectl.
       We  are  going  to configure the dns2gns service in order to translate DNS name queries by
       applications to GNS name queries where applicable and else fall back to DNS.

       Optionally, you may want to configure your dns2gns service to  run  on  a  non-priviledged
       port  like 5353. But, in case you are going to edit /etc/resolv.conf directly, the dns2gns
       service MUST run on port 53 as  you  cannot  specify  the  port  number.  A  $FALLBACK_DNS
       variable should be a DNS server you trust such as your local router:

          $ gnunet-config -s dns2gns -o OPTIONS -V "-d $FALLBACK_DNS -p 5252"
          $ gnunet-arm -i dns2gns # Make sure the service is started

       If you edit your resolv.conf directly, it should contain and entry like this:

          nameserver 127.0.0.1

       In  any  case,  it  is  very likely that the method of modification of your resolver is OS
       specific. Recently, the combination of NetworkManager  and  systemd-resolved  is  becoming
       increasingly popular.

       If  you  use  resolvectl  and systemd-resolved you can temporarily set the nameserver like
       this:

          $ resolvectl $INTERFACE 127.0.0.1:5353

       Where $INTERFACE is your network interface such as eth0.

       In order to automatically set the DNS2GNS server if it is  running  already  you  can  use
       NetworkManager-dispatcher. First, enable it:

          $ sudo systemctl enable NetworkManager-dispatcher.service
          $ sudo systemctl start NetworkManager-dispatcher.service

       Then, create a script /etc/NetworkManager/dispatch.h/10-dns2-gns.sh:

          #!/bin/sh
          interface=$1
          status=$2

          if [ "$interface" = "eth0" ]; then
            case $status in
              up)
                if nc -u -z 127.0.0.1 5353; then
                resolvectl dns $interface 127.0.0.1:5353
              fi
              ;;
              down)
              ;;
            esac
          fi

       Make sure the script is owned by root and executable:

          $ sudo root:root /etc/NetworkManager/dispatch.d/10-dns2gns.sh
          $ sudo +x /etc/NetworkManager/dispatch.d/10-dns2gns.sh

       You can test accessing this website using your browser or curl:

          $ curl www.gnunet.org

       Note  that  “gnunet.org”  is  a  domain  that  also exists in DNS and for which the GNUnet
       project webservers can provide trusted TLS certificates. When using non-DNS names with GNS
       or  aliases,  this  may  result  in issues when accessing HTTPS websites with browsers. In
       order learn how to provide relief for this issue, read on.

   Integration with Browsers (SOCKS proxy)
       While we recommend integrating GNS using the DNS2GNS service or the NSSwitch  plugin,  you
       can  also  integrate  GNS directly with your browser via the gnunet-gns-proxy. This method
       can have the advantage that the proxy can validate TLS/X.509 records and  thus  strengthen
       web  security;  however,  the  proxy is still a bit brittle, so expect subtle failures. We
       have had reasonable success with Chromium, and various frustrations with Firefox  in  this
       area recently.

       The  first  step  is to start the proxy. As the proxy is (usually) not started by default,
       this is done as a unprivileged user using gnunet-arm -i gns-proxy. Use gnunet-arm -I as  a
       unprivileged user to check that the proxy was actually started. (The most common error for
       why the proxy may fail to start is that you did not run  gnunet-gns-proxy-setup-ca  during
       installation.)  The  proxy  is a SOCKS5 proxy running (by default) on port 7777. Thus, you
       need to now configure your browser to use this proxy.  With Chromium, you can do  this  by
       starting     the     browser     as     a     unprivileged     user     using     chromium
       –proxy-server=“socks5://localhost:7777” For Firefox (or Icecat), select “Edit-Preferences”
       in the menu, and then select the “Advanced” tab in the dialog and then “Network”:

       Here,  select  “Settings…”  to  open  the  proxy  settings  dialog.  Select  “Manual proxy
       configuration” and enter localhost with port 7777 under SOCKS Host. Furthermore,  set  the
       checkbox “Proxy DNS when using SOCKS v5” at the bottom of the dialog. Finally, push “OK”.

       You  must also go to about:config and change the browser.fixup.alternate.enabled option to
       false, otherwise the browser will autoblunder an address like www.gnu to  www.gnu.com.  If
       you    want   to   resolve   @   in   your   own   TLDs,   you   must   additionally   set
       browser.fixup.dns_first_use_for_single_words to true.

       After configuring your browser, you might want to first confirm that it continues to  work
       as before. (The proxy is still experimental and if you experience “odd” failures with some
       webpages, you might want to disable it again temporarily.) Next, test if  things  work  by
       typing  “http://test.gnu/” into the URL bar of your browser. This currently fails with (my
       version of) Firefox as Firefox is super-smart and tries to resolve  “http://www.test.gnu/”
       instead  of  “test.gnu”. Chromium can be convinced to comply if you explicitly include the
       “http://” prefix — otherwise a Google search might be attempted, which  is  not  what  you
       want. If successful, you should see a simple website.

       Note  that while you can use GNS to access ordinary websites, this is more an experimental
       feature and not really our primary goal at this time. Still, it is a possible use-case and
       we welcome help with testing and development.

   Creating a Business Card
       Before  we  can really use GNS, you should create a business card. Note that this requires
       having LaTeX installed on your system. If you are using a Debian GNU/Linux based operating
       system,  the  following  command should install the required components. Keep in mind that
       this requires 3GB of downloaded data and possibly even more when unpacked. On a  GNU  Guix
       based  system  texlive  2017  has returns a DAG size of 5032.4 MiB. The packages which are
       confirmed to be required are:

       • texlive-units

       • texlive-labels

       • texlive-pst-barcode

       • texlive-luatex85

       • texlive-preview

       • texlive-pdfcrop

       • texlive-koma-script

       We welcome any help in identifying the required components of  the  TexLive  Distribution.
       This  way  we  could  just  state  the  required  components  without  pulling in the full
       distribution of TexLive.

          apt-get install texlive-full

       Start creating a business card by clicking  the  “Copy”  button  in  gnunet-namestore-gtk.
       Next,  you should start the gnunet-bcd program (in the terminal, on the command-line). You
       do not need to pass any options, and please be not surprised if there is no output:

          $ gnunet-bcd # does not return

       Then, start a browser and point it to http://localhost:8888/ where gnunet-bcd is running a
       Web server!

       First,  you  might  want  to  fill  in  the  “GNS  Public Key” field by right-clicking and
       selecting  “Paste”,  filling  in  the   public   key   from   the   copy   you   made   in
       gnunet-namestore-gtk.  Then, fill in all of the other fields, including your GNS NICKname.
       Adding a GPG fingerprint is optional. Once finished, click “Submit Query”. If  your  LaTeX
       installation  is incomplete, the result will be disappointing. Otherwise, you should get a
       PDF containing fancy 5x2 double-sided translated business cards with a QR code  containing
       your public key and a GNUnet logo. We’ll explain how to use those a bit later. You can now
       go back to the shell running gnunet-bcd and press CTRL-C to shut down the Web server.

   Be Social
       Next, you should print out your business card and be social.  Find  a  friend,  help  them
       install  GNUnet  and  exchange business cards with them.  Or, if you’re a desperate loner,
       you might try the next  step  with  your  own  card.  Still,  it’ll  be  hard  to  have  a
       conversation  with  yourself  later, so it would be better if you could find a friend. You
       might also want a camera attached to your computer, so you might need a trip to the  store
       together.

       Before  we  get started, we need to tell gnunet-qr which zone it should import new records
       into. For this, run:

          $ gnunet-identity -s namestore -e NAME

       where NAME is the name of the zone you  want  to  import  records  into.  In  our  running
       example, this would be “gnu”.

       Henceforth, for every business card you collect, simply run:

          $ gnunet-qr

       to  open  a  window showing whatever your camera points at. Hold up your friend’s business
       card and tilt it until the QR code  is  recognized.  At  that  point,  the  window  should
       automatically  close.  At  that  point, your friend’s NICKname and their public key should
       have been automatically imported into your zone.

       Assuming both of your peers are properly integrated in the GNUnet network  at  this  time,
       you  should  thus be able to resolve your friends names. Suppose your friend’s nickname is
       “Bob”. Then, type

          $ gnunet-gns -u test.bob

       to check if your friend was as good at following instructions as you were.

   Backup of Identities and Egos
       One should always backup their files, especially in these SSD days (our team has  suffered
       3  SSD  crashes over a span of 2 weeks). Backing up peer identity and zones is achieved by
       copying the following files:

       The peer identity file can be found in ~/.local/share/gnunet/private_key.ecc.

       The    private    keys    of    your    egos    are    stored     in     the     directory
       ~/.local/share/gnunet/identity/egos/.  They are stored in files whose filenames correspond
       to the zones’ ego names. These are probably the most important files you  want  to  backup
       from a GNUnet installation.

       Note:  All  these  files  contain  cryptographic  keys  and  they  are  stored without any
       encryption. So it is advisable to backup encrypted copies of them.

   Revocation
       Now, in the situation of an attacker gaining access to the private  key  of  one  of  your
       egos,  the  attacker  can create records in the respective GNS zone and publish them as if
       you published them. Anyone resolving your domain will get these new records and when  they
       verify they seem authentic because the attacker has signed them with your key.

       To  address  this  potential  security issue, you can pre-compute a revocation certificate
       corresponding to your ego. This certificate, when published on the P2P network, flags your
       private key as invalid, and all further resolutions or other checks involving the key will
       fail.

       A revocation certificate is thus a useful tool when things go out of control, but  at  the
       same  time  it  should  be stored securely. Generation of the revocation certificate for a
       zone can be done  through  gnunet-revocation.  For  example,  the  following  command  (as
       unprivileged  user)  generates  a  revocation  file  revocation.dat  for  the  zone zone1:
       gnunet-revocation -f revocation.dat -R zone1

       The above command only pre-computes a revocation certificate. It does not revoke the given
       zone.  Pre-computing a revocation certificate involves computing a proof-of-work and hence
       may take up to 4 to 5 days on a modern processor. Note that you can abort and  resume  the
       calculation  at  any time. Also, even if you did not finish the calculation, the resulting
       file will contain the signature, which is sufficient to complete  the  revocation  process
       even without access to the private key. So instead of waiting for a few days, you can just
       abort with CTRL-C, backup the revocation certificate and run the calculation only if  your
       key  actually was compromised. This has the disadvantage of revocation taking longer after
       the incident, but the advantage of saving a significant amount of energy.  So  unless  you
       believe  that  a  key  compromise  will  need  a  rapid response, we urge you to wait with
       generating the revocation certificate. Also, the calculation is deliberately expensive, to
       deter people from doing this just for fun (as the actual revocation operation is expensive
       for the network, not for the peer performing the revocation).

       To avoid TL;DR ones from accidentally revocating their zones, we are not giving  away  the
       command,  but  it  is  uncomplicated:  the  actual revocation is performed by using the -p
       option of gnunet-revocation.

   What’s next?
       This may seem not like much of an application yet, but you have just been one of the first
       to  perform  a decentralized secure name lookup (where nobody could have altered the value
       supplied by your friend) in a privacy-preserving manner (your query on the network and the
       corresponding  response were always encrypted). So what can you really do with this? Well,
       to start with, you can publish your GnuPG fingerprint  in  GNS  as  a  “CERT”  record  and
       replace  the  public web-of-trust with its complicated trust model with explicit names and
       privacy-preserving resolution. Also, you should read the next chapter of the tutorial  and
       learn  how  to  use GNS to have a private conversation with your friend.  Finally, help us
       with the next GNUnet release  for  even  more  applications  using  this  new  public  key
       infrastructure.

   Resource Records
       GNS  supports  the  majority  of the DNS records as defined in RFC 1035. Additionally, GNS
       defines some new record types the are unique to the GNS system. For example,  GNS-specific
       resource  records  are  used  to  give  petnames for zone delegation, revoke zone keys and
       provide some compatibility features.

       For some DNS records, GNS does extended processing to increase their usefulness in GNS. In
       particular,  GNS  introduces  special  names  referred  to  as “zone relative names”. Zone
       relative names are allowed in some resource record types (for example,  in  NS  and  CNAME
       records)  and can also be used in links on webpages. Zone relative names end in “.+” which
       indicates that the name needs to be resolved relative to the current  authoritative  zone.
       The  extended  processing  of those names will expand the “.+” with the correct delegation
       chain to the authoritative zone (replacing “.+” with the name of the  location  where  the
       name was encountered) and hence generate a valid GNS name.

       The GNS currently supports the record types as defined in GANA.  In addition, GNS supports
       DNS record types, such as A, AAAA or TXT.

       For a complete description of the records, please refer to the specification at LSD0001.

       In the following, we discuss GNS records with specific behaviour or  special  handling  in
       GNUnet.

   VPN
       GNS allows easy access to services provided by the GNUnet Virtual Public Network. When the
       GNS resolver encounters a VPN record it will contact the VPN service to try  and  allocate
       an  IPv4/v6  address  (if  the  queries  record type is an IP address) that can be used to
       contact the service.

       Example

       I want to provide access to the VPN service “web.gnu.” on port 80 on  peer  ABC012:  Name:
       www; RRType: VPN; Value: 80 ABC012 web.gnu.

       The  peer ABC012 is configured to provide an exit point for the service “web.gnu.” on port
       80 to it’s server running locally on port 8080  by  having  the  following  lines  in  the
       gnunet.conf configuration file:

          [web.gnunet.]
          TCP_REDIRECTS = 80:localhost4:8080

   Synchronizing with legacy DNS
       If  you  want  to  support  GNS  but  the master database for a zone is only available and
       maintained in DNS, GNUnet includes the gnunet-zoneimport tool to monitor a  DNS  zone  and
       automatically  import  records into GNS.  Today, the tool does not yet support DNS AF(X)R,
       as we initially used it on the “.fr” zone which does not allow us to perform  a  DNS  zone
       transfer.  Instead,  gnunet-zoneimport reads a list of DNS domain names from stdin, issues
       DNS queries for each, converts the obtained records (if possible) and stores the result in
       the namestore.

       The  zonemaster service then takes the records from the namestore, publishes them into the
       DHT which makes the result available to  the  GNS  resolver.  In  the  GNS  configuration,
       non-local  zones  can  be configured to be intercepted by specifying “.tld = PUBLICKEY” in
       the configuration file in the “[gns]” section.

       Note that the namestore by default also populates the namecache.  This  pre-population  is
       cryptographically  expensive. Thus, on systems that only serve to import a large (millions
       of records) DNS zone and that do not have a local gns service in use, it is thus advisable
       to   disable   the  namecache  by  setting  the  option  “DISABLE”  to  “YES”  in  section
       “[namecache]”.

   Migrating an existing DNS zone into GNS
       Ascension is a tool to migrate existing DNS zones into GNS.

       Compared to the gnunet-zoneimport tool it strictly uses AXFR or IXFR depending on  whether
       or not there exists a SOA record for the zone. If that is the case it will take the serial
       as a reference point and request the zone. The server will either answer the IXFR  request
       with  a  correct  incremental  zone  or  with the entire zone, which depends on the server
       configuration.

       Before you can migrate any zone though, you need to start a local GNUnet peer. To  migrate
       the Syrian top level domain - one of the few top level domains that support zone transfers
       - into GNS use the following command:

          $ ascension sy. -n ns1.tld.sy. -p

       The -p flag will tell GNS to put these records on the DHT so that other users may  resolve
       these records by using the public key of the zone.

       Once  the  zone  is  migrated,  Ascension  will output a message telling you, that it will
       refresh the zone after the time has elapsed.  You  can  resolve  the  names  in  the  zone
       directly  using  GNS  or if you want to use it with your browser, check out the GNS manual
       section. Configuring the GNU Name System. To resolve the records from another  system  you
       need  the  respective  zones  PKEY. To get the zones public key, you can run the following
       command:

          $ gnunet-identity -dqe sy

       Where “sy” is the name of the zone you want to migrate.

       You can share the PKEY of the zone with your friends. They can then resolve records in the
       zone by doing a lookup replacing the zone label with your PKEY:

          $ gnunet-gns -t SOA -u "$PKEY"

       The program will continue to run as a daemon and update once the refresh time specified in
       the zones SOA record has elapsed.

       DNSCurve style records are supported in the latest release and they are added  as  a  PKEY
       record  to  be  referred  to  the  respective GNS public key.  Key distribution is still a
       problem but provided someone else has a public key under a given label it  can  be  looked
       up.

       There  is  an  unofficial  Debian package called python3-ascension that adds a system user
       ascension and runs a GNUnet peer in the background.

       Ascension-bind is also an unofficial  Debian  package  that  on  installation  checks  for
       running DNS zones and whether or not they are transferable using DNS zone transfer (AXFR).
       It asks the administrator which zones to migrate into GNS and installs a systemd unit file
       to  keep  the  zone  up  to date. If you want to migrate different zones you might want to
       check the unit file from the package as a guide.

   re:claimID
       The re:claimID Identity Provider (IdP) is a decentralized  IdP  service.   It  allows  its
       users  to  manage  and authorize third parties to access their identity attributes such as
       email or shipping addresses.

       It basically mimics the concepts of centralized IdPs, such as those offered by  Google  or
       Facebook.  Like  other IdPs, reclaimID features an (optional) OpenID Connect 1.0-compliant
       protocol layer that can be used  for  websites  to  integrate  reclaimID  as  an  Identity
       Provider with little effort.

   Managing Attributes
       Before adding attributes to an identity, you must first create an ego:

          $ gnunet-identity --create="user"

       Henceforth, you can manage a new user profile of the user "user".

       To  add  an email address to your user profile, simply use the gnunet-reclaim command line
       tool:

          ::
          $ gnunet-reclaim -e "user" -a "email" -V "username@example.gnunet"

       All of your attributes can be listed using the gnunet-reclaim command line tool as well:

          $ gnunet-reclaim -e "user" -D

       Currently, and by default, attribute values are interpreted as plain text. In  the  future
       there might be more value types such as X.509 certificate credentials.

   Managing Credentials
       Attribute  values  may  reference  a  claim  in  a third party attested credential. Such a
       credential can have a variety of formats such as JSON-Web-Tokens  or  X.509  certificates.
       Currently, reclaimID only supports JSON-Web-Token credentials.

       To  add  a credential to your user profile, invoke the gnunet-reclaim command line tool as
       follows:

          $ gnunet-reclaim -e "user"\
                           --credential-name="email"\
                           --credential-type="JWT"\
                           --value="ey..."

       All of your credentials can be listed using the gnunet-reclaim command line tool as well:

          $ gnunet-reclaim -e "user" --credentials

       In order to add an attribe backed by a credential, specify  the  attribute  value  as  the
       claim name in the credential to reference along with the credential ID:

          $ gnunet-reclaim -e "user"\
                           --add="email"\
                           --value="verified_email"\
                           --credential-id="<CREDENTIAL_ID>"

   Sharing Attributes with Third Parties
       If  you  want  to  allow  a  third  party  such  as  a website or friend to access to your
       attributes (or a subset thereof) execute:

          $ TICKET=$(gnunet-reclaim -e "user"\
                                    -r "$RP_KEY"\
                                    -i "attribute1,attribute2,...")

       The command will return a "ticket" string. You must give $TICKET to the  requesting  third
       party.

       $RP_KEY  is  the  public  key  of  the  third  party  and "attribute1,attribute2,..." is a
       comma-separated list of attribute names, such as "email,name,...", that you want to share.

       The third party may retrieve the key in string format for use  in  the  above  call  using
       "gnunet-identity":

          $ RP_KEY=$(gnunet-identity -d | grep "relyingparty" | awk '{print $3}')

       The third party can then retrieve your shared identity attributes using:

          $ gnunet-reclaim -e "relyingparty" -C "ticket"

       Where "relyingparty" is the name for the identity behind $RP_KEY that the requesting party
       is using. This will retrieve and list the shared identity attributes.  The  above  command
       will  also  work  if the user is currently offline since the attributes are retrieved from
       GNS. Further, $TICKET can be re-used later  to  retrieve  up-to-date  attributes  in  case
       "friend" has changed the value(s). For instance, because his email address changed.

       To list all given authorizations (tickets) you can execute:

          $ gnunet-reclaim -e "user" -T

   Revoking Authorizations of Third Parties
       If you want to revoke the access of a third party to your attributes you can execute:

          $ gnunet-reclaim -e "user" -R $TICKET

       This  will prevent the third party from accessing the attribute in the future. Please note
       that if the third party has previously accessed the attribute, there is not way  in  which
       the  system  could  have  prevented  the  thiry party from storing the data. As such, only
       access to updated data in the future can be revoked. This behaviour is _exactly the  same_
       as with other IdPs.

   OpenID Connect
       There   is  an  https://openid.net/specs/openid-connect-core-1_0.html  API  for  use  with
       re:claimID. However, its use is quite complicated to setup.

          https://api.reclaim/openid/authorize
          http://localhost:7776/openid/token
          http://localhost:7776/openid/userinfo
          http://localhost:7776/openid/login

       The token endpoint is protected using HTTP  basic  authentication.  You  can  authenticate
       using any username and the password configured under:

          $ gnunet-config -s reclaim-rest-plugin -o OIDC_CLIENT_SECRET

       The authorize endpoint is protected using a Cookie which can be obtained through a request
       against the login endpoint. This functionality is meant to be used in the context  of  the
       OpenID Connect authorization flow to collect user consent interactively. Without a Cookie,
       the authorize endpoint redirects to a URI configured under:

          $ gnunet-config -s reclaim-rest-plugin -o ADDRESS

       The token endpoint is protected using OAuth2 and expects the grant which is retrieved from
       the authorization endpoint according to the standard.

       The userinfo endpoint is protected using OAuth2 and expects a bearer access token which is
       retrieved from a token request.

       In order to make use of OpenID Connect flows as a user, you need to  install  the  browser
       plugin:

       • Firefox Add-onChrome Web Store

       In  order  to create and register an OpenID Connect client as a relying party, you need to
       execute the following steps:

          $ gnunet-identity -C <client_name>
          $ gnunet-namestore -z <client_name> -a -n "@" -t RECLAIM_OIDC_REDIRECT -V <redirect_uri> -e 1d -p
          $ gnunet-namestore -z <client_name> -a -n "@" -t RECLAIM_OIDC_CLIENT -V "My OIDC Client" -e 1d -p

       The "client_id" for use in OpenID Connect is the public key of  the  client  as  displayed
       using:

          $ gnunet-identity -d grep "relyingparty" | awk '{print $3}'

       The  RECLAIM_OIDC_REDIRECT  record  contains  your  website  redirect URI. You may use any
       globally unique DNS or GNS URI.  The  RECLAIM_OIDC_CLIENT  record  represents  the  client
       description which whill be displayed to users in an authorization request.

       Any    website    or    relying    party    must    use    the    authorization   endpoint
       https://api.reclaim/openid/authorize in its authorization redirects, e.g.

          <a href="https://api.reclaim/openid/authorize?client_id=<PKEY>\
                                                       &scope=openid email\
                                                       &redirect_uri=<redirect_uri>\
                                                       &nonce=<random>">Login</a>

       This will direct the user's browser onto  his  local  reclaimID  instance.   After  giving
       consent,  you will be provided with the OpenID Connect authorization code according to the
       specifications at your provided redirect URI.

       The ID Tokens issues by the token endpoints are signed using HS512 with the shared  secret
       configured under:

          $ gnunet-config -s reclaim-rest-plugin -o JWT_SECRET

       The  authorization  code  flow optionally supports Proof Key for Code Exchange. If PKCE is
       used, the client does not need to authenticate against the token endpoint.

   Providing Third Party Attestation
       If you are running an identity provider (IdP) service you may be able to support providing
       credentials  for  re:claimID users. IdPs can issue JWT credentials as long as they support
       OpenID Connect and OpenID Connect Discovery.

       In order to allow users to import attributes through the re:claimID  user  interface,  you
       need to register the following public OAuth2/OIDC client:

       • client_id: reclaimid

       • client_secret: none

       • redirect_uri: https://ui.reclaim (The URI of the re:claimID webextension)

       • grant_type: authorization_code with PKCE (RFC7636)

       • scopes: all you want to offer.

       • id_token: JWT

       When your users add an attribute with name "email" which supports webfinger discovery they
       will be prompted with the option to retrieve the OpenID Connect ID Token through the  user
       interface.

   File-sharing
       This  chapter  documents  the  GNUnet  file-sharing application. The original file-sharing
       implementation for GNUnet was designed to provide anonymous  file-sharing.  However,  over
       time,  we have also added support for non-anonymous file-sharing (which can provide better
       performance).  Anonymous and non-anonymous file-sharing are  quite  integrated  in  GNUnet
       and,  except  for routing, share most of the concepts and implementation.  There are three
       primary file-sharing operations: publishing, searching and downloading. For each of  these
       operations,  the  user  specifies  an  anonymity  level.  If  both  the  publisher and the
       searcher/downloader specify “no anonymity”, non-anonymous file-sharing is used. If  either
       user specifies some desired degree of anonymity, anonymous file-sharing will be used.

       After  a  short  introduction,  we  will  first  look  at the various concepts in GNUnet’s
       file-sharing implementation. Then, we will discuss specifics as to how they  impact  users
       that publish, search or download files.

   Searching
       The command gnunet-search can be used to search for content on GNUnet. The format is:

          $ gnunet-search [-t TIMEOUT] KEYWORD

       The -t option specifies that the query should timeout after approximately TIMEOUT seconds.
       A value of zero (“0”) is interpreted as no timeout, which is the default.  In  this  case,
       gnunet-search will never terminate (unless you press CTRL-C).

       If  multiple  words  are  passed as keywords, they will all be considered optional. Prefix
       keywords with a “+” to make them mandatory.

       Note that searching using:

          $ gnunet-search Das Kapital

       is not the same as searching for

          $ gnunet-search "Das Kapital"

       as the first will match files shared under the keywords “Das”  or  “Kapital”  whereas  the
       second will match files shared under the keyword “Das Kapital”.

       Search results are printed like this:

          #15:
          gnunet-download -o "COPYING" gnunet://fs/chk/PGK8M...3EK130.75446

       The  whole  line  is  the  command you would have to enter to download the file. The first
       argument passed to -o is the suggested filename (you may change it to whatever you  like).
       It  is  followed  by  the key for decrypting the file, the query for searching the file, a
       checksum (in hexadecimal) finally the size of the file in bytes.

   Downloading
       In order to download a file, you need the whole line returned by  gnunet-search.  You  can
       then use the tool gnunet-download to obtain the file:

          $ gnunet-download -o <FILENAME> <GNUNET-URL>

       FILENAME  specifies  the  name  of  the file where GNUnet is supposed to write the result.
       Existing files are overwritten. If the existing file contains blocks that are identical to
       the desired download, those blocks will not be downloaded again (automatic resume).

       If you want to download the GPL from the previous example, you do the following:

          $ gnunet-download -o "COPYING" gnunet://fs/chk/PGK8M...3EK130.75446

       If  you  ever  have  to  abort  a  download, you can continue it at any time by re-issuing
       gnunet-download with the same filename. In that case,  GNUnet  will  not  download  blocks
       again that are already present.

       GNUnet’s file-encoding mechanism will ensure file integrity, even if the existing file was
       not downloaded from GNUnet in the first place.

       You may want  to  use  the  -V  switch  to  turn  on  verbose  reporting.  In  this  case,
       gnunet-download  will  print  the current number of bytes downloaded whenever new data was
       received.

   Publishing
       The command gnunet-publish can be used to add content to the network. The basic format  of
       the command is:

          $ gnunet-publish [-n] [-k KEYWORDS]* [-m TYPE:VALUE] FILENAME

       For example:

          $ gnunet-publish -m "description:GNU License" -k gpl -k test -m "mimetype:text/plain" COPYING

       The  option  -k  is used to specify keywords for the file that should be inserted. You can
       supply any number of keywords, and each of the keywords will be sufficient to  locate  and
       retrieve  the  file.  Please note that you must use the -k option more than once – one for
       each expression you use as a keyword for the filename.

       The -m option is used to specify meta-data, such as descriptions.  You can use -m multiple
       times. The TYPE passed must be from the list of meta-data types known to libextractor. You
       can obtain this list by running  extract  -L.  Use  quotes  around  the  entire  meta-data
       argument if the value contains spaces. The meta-data is displayed to other users when they
       select which files to download. The meta-data and the keywords are  optional  and  may  be
       inferred using GNU libextractor.

       gnunet-publish has a few additional options to handle namespaces and directories. Refer to
       the man-page for details.

   Indexing vs Inserting
       By default, GNUnet indexes a file instead of  making  a  full  copy.  This  is  much  more
       efficient,  but  requires  the file to stay unaltered at the location where it was when it
       was indexed. If you intend to move, delete or alter a file, consider using the  option  -n
       which will force GNUnet to make a copy of the file in the database.

       Since it is much less efficient, this is strongly discouraged for large files. When GNUnet
       indexes a file (default), GNUnet does not create an additional encrypted copy of the  file
       but  just  computes  a  summary  (or index) of the file. That summary is approximately two
       percent of the size of the original file and is stored in GNUnet’s  database.  Whenever  a
       request for a part of an indexed file reaches GNUnet, this part is encrypted on-demand and
       send out. This way, there is no need for an additional encrypted copy of the file to  stay
       anywhere  on the drive.  This is different from other systems, such as Freenet, where each
       file that is put online must be in Freenet’s database in encrypted  format,  doubling  the
       space requirements if the user wants to preserve a directly accessible copy in plaintext.

       Thus  indexing  should  be used for all files where the user will keep using this file (at
       the location given to gnunet-publish) and does not want to retrieve it  back  from  GNUnet
       each time. If you want to remove a file that you have indexed from the local peer, use the
       tool gnunet-unindex to un-index the file.

       The option -n may be used if the user fears that the file might be found  on  their  drive
       (assuming  the  computer  comes  under the control of an adversary). When used with the -n
       flag, the user has a much better chance of denying knowledge of the existence of the file,
       even  if  it  is  still  (encrypted)  on  the drive and the adversary is able to crack the
       encryption (e.g. by guessing the keyword).

   Concepts
       For better results with filesharing it is useful to understand the following concepts.  In
       addition  to  anonymous  routing  GNUnet  attempts  to  give  users a better experience in
       searching for content. GNUnet uses cryptography  to  safely  break  content  into  smaller
       pieces  that  can  be  obtained  from  different  sources without allowing participants to
       corrupt files. GNUnet makes it difficult for  an  adversary  to  send  back  bogus  search
       results.  GNUnet  enables  content  providers  to group related content and to establish a
       reputation. Furthermore, GNUnet allows updates to certain content to  be  made  available.
       This section is supposed to introduce users to the concepts that are used to achieve these
       goals.

   Files
       A file in GNUnet is just a sequence of bytes. Any file-format is allowed and  the  maximum
       file size is theoretically 2^64 - 1 bytes, except that it would take an impractical amount
       of time to share such a file. GNUnet itself never interprets the contents of shared files,
       except when using GNU libextractor to obtain keywords.

   Keywords
       Keywords   are   the  most  simple  mechanism  to  find  files  on  GNUnet.  Keywords  are
       case-sensitive and the search string must always match exactly the  keyword  used  by  the
       person  providing  the file. Keywords are never transmitted in plaintext. The only way for
       an adversary to determine the keyword that you used to search is to guess it  (which  then
       allows the adversary to produce the same search request). Since providing keywords by hand
       for each shared file is tedious, GNUnet  uses  GNU  libextractor  to  help  automate  this
       process.  Starting  a  keyword  search on a slow machine can take a little while since the
       keyword search involves computing a fresh RSA key to formulate the request.

   Directories
       A directory in GNUnet is a list of file identifiers with meta data. The  file  identifiers
       provide  sufficient  information about the files to allow downloading the contents. Once a
       directory has been created, it cannot be changed since it is treated just like an ordinary
       file  by the network. Small files (of a few kilobytes) can be inlined in the directory, so
       that a separate download becomes unnecessary.

       Directories are shared just  like  ordinary  files.  If  you  download  a  directory  with
       gnunet-download,  you  can  use  gnunet-directory  to  list  its  contents.  The canonical
       extension for GNUnet directories when stored as files in your local file-system is ".gnd".
       The  contents  of a directory are URIs and meta data. The URIs contain all the information
       required by gnunet-download to retrieve the file. The meta  data  typically  includes  the
       mime-type,  description, a filename and other meta information, and possibly even the full
       original file (if it was small).

   Egos and File-Sharing
       When sharing files, it is sometimes desirable to  build  a  reputation  as  a  source  for
       quality  information.  With  egos,  publishers can (cryptographically) sign files, thereby
       demonstrating that various files were published by the same entity.  An  ego  thus  allows
       users  to  link  different  publication events, thereby deliberately reducing anonymity to
       pseudonymity.

       Egos used in GNUnet's file-sharing for such pseudonymous publishing also correspond to the
       egos  used  to identify and sign zones in the GNU Name System. However, if the same ego is
       used for file-sharing and for a GNS zone, this will weaken the privacy assurances provided
       by the anonymous file-sharing protocol.

       Note  that  an  ego is NOT bound to a GNUnet peer. There can be multiple egos for a single
       user, and users could (theoretically) share the private keys of  an  ego  by  copying  the
       respective private keys.

   Namespaces
       A  namespace  is  a  set  of files that were signed by the same ego. Today, namespaces are
       implemented independently of GNS zones, but in the future we plan to merge  the  two  such
       that a GNS zone can basically contain files using a file-sharing specific record type.

       Files  (or  directories) that have been signed and placed into a namespace can be updated.
       Updates are identified as authentic if the same secret key was used to sign the update.

   Advertisements
       Advertisements are used to  notify  other  users  about  the  existence  of  a  namespace.
       Advertisements  are  propagated  using the normal keyword search. When an advertisement is
       received (in response to a search), the namespace is  added  to  the  list  of  namespaces
       available in the namespace-search dialogs of gnunet-fs-gtk and printed by gnunet-identity.
       Whenever a namespace is created,  an  appropriate  advertisement  can  be  generated.  The
       default keyword for the advertising of namespaces is "namespace".

   Anonymity level
       The  anonymity  level  determines  how hard it should be for an adversary to determine the
       identity of the publisher or the searcher/downloader. An anonymity  level  of  zero  means
       that  anonymity  is  not required. The default anonymity level of "1" means that anonymous
       routing is desired, but no particular amount of cover traffic  is  necessary.  A  powerful
       adversary  might  thus  still  be  able  to deduce the origin of the traffic using traffic
       analysis. Specifying higher  anonymity  levels  increases  the  amount  of  cover  traffic
       required.

       The  specific  numeric  value (for anonymity levels above 1) is simple: Given an anonymity
       level L (above 1), each request FS makes on your behalf must be hidden in  L-1  equivalent
       requests  of  cover traffic (traffic your peer routes for others) in the same time-period.
       The time-period is twice the average delay by which GNUnet artificially delays traffic.

       While higher anonymity levels may offer better privacy, they can also  significantly  hurt
       performance.

   Content Priority
       Depending on the peer's configuration, GNUnet peers migrate content between peers. Content
       in this sense are individual blocks of a file, not necessarily entire  files.  When  peers
       run  out  of space (due to local publishing operations or due to migration of content from
       other peers), blocks sometimes need to be discarded. GNUnet first always discards  expired
       blocks  (typically,  blocks  are  published  with  an expiration of about two years in the
       future; this is another option). If there is still not enough space, GNUnet  discards  the
       blocks  with the lowest priority. The priority of a block is decided by its popularity (in
       terms of requests from peers we trust) and, in  case  of  blocks  published  locally,  the
       base-priority that was specified by the user when the block was published initially.

   Replication
       When  peers  migrate content to other systems, the replication level of a block is used to
       decide which blocks need to be migrated most urgently.  GNUnet will always push the  block
       with  the  highest  replication level into the network, and then decrement the replication
       level by one. If all blocks reach replication level zero, the selection is simply random.

   Namespace Management
       The gnunet-identity tool can be used to create egos. By default, gnunet-identity --display
       simply lists all locally available egos.

   Creating Egos
       With  the  --create=NICK  option  it  can  also be used to create a new ego. An ego is the
       virtual identity of the entity in control of a namespace or GNS zone.  Anyone  can  create
       any  number of egos. The provided NICK name automatically corresponds to a GNU Name System
       domain name. Thus, henceforth name resolution for any name ending in ".NICK" will use  the
       NICK's zone. You should avoid using NICKs that collide with well-known DNS names.

       Currently, the IDENTITY subsystem supports two types of identity keys: ECDSA and EdDSA. By
       default, ECDSA identities are creates with ECDSA keys. In order to create an identity with
       EdDSA keys, you can use the --eddsa flag.

   Deleting Egos
       With  the  -D  NICK  option  egos  can  be  deleted.  Once  the ego has been deleted it is
       impossible to add content to the corresponding namespace or zone.  However,  the  existing
       GNS zone data is currently not dropped.  This may change in the future.

       Deleting the pseudonym does not make the namespace or any content in it unavailable.

   File-Sharing URIs
       GNUnet  (currently)  uses  four  different types of URIs for file-sharing.  They all begin
       with "gnunet://fs/". This section describes the four different URI types in detail.

       For FS URIs empty KEYWORDs are not  allowed.  Quotes  are  allowed  to  denote  whitespace
       between  words.  Keywords  must contain a balanced number of double quotes. Doubles quotes
       can not be used in the actual keywords.  This means that the string '""foo bar""' will  be
       turned into two OR-ed keywords 'foo' and 'bar', not into '"foo bar"'.

   Encoding of hash values in URIs
       Most URIs include some hash values. Hashes are encoded using base32hex (RFC 2938).

       chk-uri .. _Content-Hash-Key-_0028chk_0029:

   Content Hash Key (chk)
       A  chk-URI  is  used  to  (uniquely)  identify  a  file or directory and to allow peers to
       download the file. Files are stored in GNUnet as a tree of encrypted blocks.  The  chk-URI
       thus  contains  the  information  to  download and decrypt those blocks. A chk-URI has the
       format "gnunet://fs/chk/KEYHASH.QUERYHASH.SIZE". Here, "SIZE" is  the  size  of  the  file
       (which  allows  a  peer  to  determine  the shape of the tree), KEYHASH is the key used to
       decrypt the file (also the hash of the plaintext of the top block) and  QUERYHASH  is  the
       query used to request the top-level block (also the hash of the encrypted block).

       loc-uri .. _Location-identifiers-_0028loc_0029:

   Location identifiers (loc)
       For  non-anonymous  file-sharing,  loc-URIs are used to specify which peer is offering the
       data (in addition to specifying all of the data  from  a  chk-URI).  Location  identifiers
       include a digital signature of the peer to affirm that the peer is truly the origin of the
       data.  The  format  is  "gnunet://fs/loc/KEYHASH.QUERYHASH.SIZE.PEER.SIG.EXPTIME".   Here,
       "PEER"  is  the  public  key  of  the peer (in GNUnet format in base32hex), SIG is the RSA
       signature (in GNUnet format in base32hex) and EXPTIME specifies when the signature expires
       (in milliseconds after 1970).

       ksk-uri .. _Keyword-queries-_0028ksk_0029:

   Keyword queries (ksk)
       A  keyword-URI  is  used  to  specify  that  the  desired  operation is the search using a
       particular keyword. The format is simply "gnunet://fs/ksk/KEYWORD".  Non-ASCII  characters
       can  be  specified using the typical URI-encoding (using hex values) from HTTP. "+" can be
       used to specify multiple keywords (which are then logically "OR"-ed in the search, results
       matching  both  keywords  are  given  a higher rank): "gnunet://fs/ksk/KEYWORD1+KEYWORD2".
       ksk-URIs must not begin or end with the plus ('+') character. Furthermore  they  must  not
       contain '++'.

       sks-uri .. _Namespace-content-_0028sks_0029:

   Namespace content (sks)
       Please  note  that  the  text in this subsection is outdated and needs to be rewritten for
       version 0.10! This especially concerns the terminology of Pseudonym/Ego/Identity.

       Namespaces are sets of files that have been approved by some (usually  pseudonymous)  user
       ---  typically  by  that  user publishing all of the files together. A file can be in many
       namespaces. A file is in a namespace if the owner of the ego (aka the namespace's  private
       key)  signs  the  CHK  of  the  file  cryptographically.  An  SKS-URI  is used to search a
       namespace. The result is a block containing meta data, the CHK and the  namespace  owner's
       signature.  The  format  of  a  sks-URI  is  "gnunet://fs/sks/NAMESPACE/IDENTIFIER". Here,
       "NAMESPACE" is the public key for the namespace. "IDENTIFIER" is a freely  chosen  keyword
       (or  password!).  A  commonly used identifier is "root" which by convention refers to some
       kind of index or other entry point into the namespace.

   Virtual Public Network
       Using the GNUnet Virtual Public Network (VPN) application you can tunnel IP  traffic  over
       GNUnet.  Moreover,  the  VPN comes with built-in protocol translation and DNS-ALG support,
       enabling IPv4-to-IPv6 protocol translation (in both directions).  This  chapter  documents
       how to use the GNUnet VPN.

       The  first  thing  to  note  about  the  GNUnet  VPN  is  that it is a public network. All
       participating peers can participate and there is no  secret  key  to  control  access.  So
       unlike common virtual private networks, the GNUnet VPN is not useful as a means to provide
       a "private" network abstraction over the Internet. The GNUnet VPN is a virtual network  in
       the  sense  that  it is an overlay over the Internet, using its own routing mechanisms and
       can also use an internal addressing scheme. The GNUnet VPN is  an  Internet  underlay  ---
       TCP/IP applications run on top of it.

       The  VPN  is  currently only supported on GNU/Linux systems. Support for operating systems
       that support TUN (such as FreeBSD) should be easy to add (or might not  even  require  any
       coding  at  all --- we just did not test this so far). Support for other operating systems
       would require re-writing the code to create virtual network interfaces  and  to  intercept
       DNS requests.

       The  VPN  does  not  provide  good  anonymity.  While  requests are routed over the GNUnet
       network, other peers can directly see the source and destination of each (encapsulated) IP
       packet.  Finally,  if  you  use  the VPN to access Internet services, the peer sending the
       request to the Internet will be able to observe and even alter the  IP  traffic.  We  will
       discuss additional security implications of using the VPN later in this chapter.

   Setting up an Exit node
       Any  useful  operation  with  the VPN requires the existence of an exit node in the GNUnet
       Peer-to-Peer network. Exit functionality can only be enabled on peers  that  have  regular
       Internet  access.  If  you  want  to  play  around with the VPN or support the network, we
       encourage you to setup exit nodes. This chapter documents how to setup an exit node.

       There are four types of exit functions an exit node can provide, and using the GNUnet  VPN
       to  access  the  Internet  will  only  work  nicely  if the first three types are provided
       somewhere in the network. The four exit functions are:

       • DNS: allow other peers to use your DNS resolver

       • IPv4: allow other peers to access your IPv4 Internet connection

       • IPv6: allow other peers to access your IPv6 Internet connection

       • Local service: allow other peers to access a specific TCP or UDP service  your  peer  is
         providing

       By  enabling  "exit"  in gnunet-setup and checking the respective boxes in the "exit" tab,
       you can easily choose which of the above exit functions you want to support.

       Note, however, that by supporting the first three functions you will allow arbitrary other
       GNUnet users to access the Internet via your system. This is somewhat similar to running a
       Tor exit node. The Torproject has a nice article about what to consider if you want to  do
       this here. We believe that generally running a DNS exit node is completely harmless.

       The  exit node configuration does currently not allow you to restrict the Internet traffic
       that leaves your system. In particular, you cannot exclude SMTP traffic (or block port 25)
       or  limit  to  HTTP traffic using the GNUnet configuration. However, you can use your host
       firewall to restrict outbound connections from  the  virtual  tunnel  interface.  This  is
       highly recommended. In the future, we plan to offer a wider range of configuration options
       for exit nodes.

       Note that  by  running  an  exit  node  GNUnet  will  configure  your  kernel  to  perform
       IP-forwarding (for IPv6) and NAT (for IPv4) so that the traffic from the virtual interface
       can be routed to the Internet. In order to provide an IPv6-exit, you need to have a subnet
       routed  to  your host's external network interface and assign a subrange of that subnet to
       the GNUnet exit's TUN interface.

       When running a local service, you should make sure that the local service is (also)  bound
       to  the  IP  address of your EXIT interface (e.g.  169.254.86.1). It will NOT work if your
       local service is just bound to loopback. You may also want to create  a  "VPN"  record  in
       your  zone  of the GNU Name System to make it easy for others to access your service via a
       name instead of just the full service descriptor. Note that the identifier you assign  the
       service can serve as a passphrase or shared secret, clients connecting to the service must
       somehow learn the service's name. VPN records in the GNU Name System can make this easier.

   Fedora and the Firewall
       When using an exit node on Fedora 15, the standard firewall can create trouble  even  when
       not  really exiting the local system! For IPv4, the standard rules seem fine. However, for
       IPv6 the standard rules prohibit traffic from the network range of the  virtual  interface
       created  by  the  exit  daemon  to  the local IPv6 address of the same interface (which is
       essentially loopback traffic, so you might suspect that a standard  firewall  would  leave
       this  traffic  alone).  However,  as  somehow  for  IPv6  the traffic is not recognized as
       originating from the local system (and as the connection is  not  already  "established"),
       the  firewall  drops  the  traffic.  You  should still get ICMPv6 packets back, but that's
       obviously not very useful.

       Possible ways to fix this include disabling the firewall (do you have a  good  reason  for
       having  it  on?)  or disabling the firewall at least for the GNUnet exit interface (or the
       respective IPv4/IPv6 address range).  The best way to diagnose these kinds of problems  in
       general  involves  setting the firewall to REJECT instead of DROP and to watch the traffic
       using wireshark (or tcpdump) to see if ICMP messages are generated when running some tests
       that should work.

   Setting up VPN node for protocol translation and tunneling
       The GNUnet VPN/PT subsystem enables you to tunnel IP traffic over the VPN to an exit node,
       from where it can then be forwarded to the Internet. This section documents how  to  setup
       VPN/PT  on  a node. Note that you can enable both the VPN and an exit on the same peer. In
       this case, IP traffic from your system may enter your peer's VPN  and  leave  your  peer's
       exit.  This  can  be  useful as a means to do protocol translation. For example, you might
       have an application that supports only IPv4 but needs to access an IPv6-only site. In this
       case,  GNUnet  would perform 4to6 protocol translation between the VPN (IPv4) and the Exit
       (IPv6). Similarly, 6to4 protocol translation is also possible.  However, the  primary  use
       for  GNUnet  would be to access an Internet service running with an IP version that is not
       supported by your ISP. In this case, your IP traffic would be routed via GNUnet to a  peer
       that has access to the Internet with the desired IP version.

       Setting up an entry node into the GNUnet VPN primarily requires you to enable the "VPN/PT"
       option in "gnunet-setup". This will launch the "gnunet-service-vpn",  "gnunet-service-dns"
       and "gnunet-daemon-pt" processes. The "gnunet-service-vpn" will create a virtual interface
       which will be used as the target for your IP traffic that enters the VPN. Additionally,  a
       second virtual interface will be created by the "gnunet-service-dns" for your DNS traffic.
       You will then need to specify which traffic you want to tunnel over GNUnet.  If  your  ISP
       only provides you with IPv4 or IPv6-access, you may choose to tunnel the other IP protocol
       over the GNUnet VPN. If you do not have an ISP (and are connected to  other  GNUnet  peers
       via  WLAN),  you  can  also  choose  to tunnel all IP traffic over GNUnet. This might also
       provide you with some anonymity. After you enable the respective options and restart  your
       peer, your Internet traffic should be tunneled over the GNUnet VPN.

       The  GNUnet VPN uses DNS-ALG to hijack your IP traffic. Whenever an application resolves a
       hostname   (like    'gnunet.org'),    the    "gnunet-daemon-pt"    will    instruct    the
       "gnunet-service-dns"  to intercept the request (possibly route it over GNUnet as well) and
       replace  the  normal  answer  with  an  IP  in  the  range   of   the   VPN's   interface.
       "gnunet-daemon-pt"  will then tell "gnunet-service-vpn" to forward all traffic it receives
       on the TUN interface via the VPN to the original destination.

       For applications that do not use DNS, you can also manually create such  a  mapping  using
       the  gnunet-vpn  command-line  tool.  Here,  you specify the desired address family of the
       result (e.g. "-4"), and the intended target IP on the Internet (e.g.  "-i  131.159.74.67")
       and  "gnunet-vpn"  will  tell  you  which  IP  address in the range of your VPN tunnel was
       mapped.

       gnunet-vpn can also be used to access "internal" services offered by GNUnet nodes.  So  if
       you  happen to know a peer and a service offered by that peer, you can create an IP tunnel
       to that peer by specifying the peer's identity, service name and protocol (--tcp or --udp)
       and  you  will  again  receive  an IP address that will terminate at the respective peer's
       service.

   Messenger
       The GNUnet Messenger subsystem allows decentralized message-based communication inside  of
       so  called rooms. Each room can be hosted by a variable amount of peers. Every member of a
       room has the possibility to host the room on its own peer. A peer  allows  any  amount  of
       members to join a room. The amount of members in a room is not restricted.

       Messages  in  a  room  will  be  distributed  between  all peers hosting the room or being
       internally (in context of the messenger service) connected to a hosting peer. All received
       or  sent  messages will be stored on any peer locally which is hosting the respective room
       or is internally connected to such a hosting peer.

       The Messenger service is built on the CADET subsystem to make internal connections between
       peers  using  a  reliable  and  encrypted  transmission.   Additionally the service uses a
       discrete padding to few different sizes.  So kinds of messages and potential content can't
       be  identified  by  the  size  of  traffic  from  any  attacker  being unable to break the
       encryption of the transmission layer.

       Another feature is additional end-to-end encryption for selected messages which  uses  the
       public  key  of  another  member  (the  receiver)  to encrypt the message. Therefore it is
       ensured that only the selected member can read its content. This will also use  additional
       padding.

   Current state
       Currently  there  is  only  a  simplistic  CLI  application available to use the messenger
       service. You can use this application with the gnunet-messenger command.

       This application  was  designed  for  testing  purposes  and  it  does  not  provide  full
       functionality in the current state. It is planned to replace this CLI application in later
       stages with a fully featured one  using  a  client-side  library  designed  for  messenger
       applications.

   Entering a room
       You  can  enter any room by its ROOMKEY and any PEERIDENTITY of a hosting peer. Optionally
       you can provide any IDENTITY which can represent a local ego by its name.

          $ gnunet-messenger [-e IDENTITY] -d PEERIDENTITY -r ROOMKEY

       A PEERIDENTITY gets entered in encoded form. You can get your own peer  ID  by  using  the
       gnunet-peerinfo command:

          $ gnunet-peerinfo -s

       A  ROOMKEY  gets  entered  in  readable  text form. The service will then hash the entered
       ROOMKEY and use the result as shared secret for transmission through the CADET  submodule.
       You  can  also  optionally  leave out the '-r' parameter and the ROOMKEY to use the zeroed
       hash instead.

       If no IDENTITY is provided you will not send any name to others, you will be  referred  as
       "anonymous"  instead and use the anonymous ego. If you provide any IDENTITY a matching ego
       will be used to sign your messages. If there is no matching ego you will use the anonymous
       ego instead. The provided IDENTITY will be distributed as your name for the service in any
       case.

   Opening a room
       You can open any room in a similar way to entering it. You just have to leave out the '-d'
       parameter and the PEERIDENTITY of the hosting peer.

          $ gnunet-messenger [-e IDENTITY] -r ROOMKEY

       Providing  ROOMKEY  and IDENTITY is identical to entering a room. Opening a room will also
       make your peer to a host of this room. So others can enter the room through your  peer  if
       they have the required ROOMKEY and your peer ID.

       If you want to use the zeroed hash as shared secret key for the room you can also leave it
       out as well:

          $ gnunet-messenger

   Messaging in a room
       Once joined a room by entering it or opening it you can write  text-based  messages  which
       will  be  distributed  between  all internally conntected peers. All sent messages will be
       displayed in the same way as received messages.

       This relates to the internal handling of sent and received messages being mostly identical
       on  application layer. Every handled message will be represented visually depending on its
       kind, content and sender. A sender can usually be identified by the encoded member  ID  or
       their name.

          [17X37K] * 'anonymous' says: "hey"

   Private messaging
       As  referred  in  the  introduction  the  service  allows  sending  private  messages with
       additional end-to-end encryption. These messages will be visually represented by  messages
       of  the  kind  'PRIVATE'  in  case they can't be decrypted with your used ego. Members who
       can't decrypt the message can potentially only identify its sender but they can't identify
       its receiver.

          [17X37K] ~ message: PRIVATE

       If  they  can  be  decrypted  they  will appear as their secret message instead but marked
       visually.

          [17X37K] ** 'anonymous' says: "hey"

       Currently you can only activate sending such encrypted text messages instead of usual text
       messages by adding the '-p' parameter:

          $ gnunet-messenger [-e IDENTITY] -d PEERIDENTITY -r ROOMKEY -p

       Notice  that  you can only send such encrypted messages to members who use an ego which is
       not publicly known as the anonymous ego to ensure transparency. If any user could  decrypt
       these  messages they would not be private. So as receiver of such messages the IDENTITY is
       required and it has to match a local ego.

   Advanced Configuration
   Config file format
       In GNUnet realm, all components  obey  the  same  pattern  to  get  configuration  values.
       According to this pattern, once the component has been installed, the installation deploys
       default values in $prefix/share/gnunet/config.d/, in .conf files.  In  order  to  override
       these defaults, the user can write a custom .conf file and either pass it to the component
       at execution time, or name it gnunet.conf and place it under $HOME/.config/.

       A config file is a text file containing sections, and each section  contains  its  values.
       The right format follows:

          [section1]
          value1 = string
          value2 = 23

          [section2]
          value21 = string
          value22 = /path22

       Throughout  any configuration file, it is possible to use $-prefixed variables, like $VAR,
       especially when they represent filenames in in the filesystem.  It  is  also  possible  to
       provide defaults values for those variables that are unset, by using the following syntax:

          ${VAR:-default}

       However,  there  are  two ways a user can set $-prefixable variables: (a) by defining them
       under a [paths] section

          [paths]
          GNUNET_DEPLOYMENT_SHARED = ${HOME}/shared-data
          ..
          [section-x]
          path-x = ${GNUNET_DEPLOYMENT_SHARED}/x

       or (b) by setting them in the environment

          $ export VAR=/x

       The configuration loader will give precedence to variables set under [path], though.

       The utility 'gnunet-config', which gets installed along with GNUnet, serves to get and set
       configuration  values  without  directly  editing  the  .conf  file.  The  option  '-f' is
       particularly useful to resolve filenames, when  they  use  several  levels  of  $-expanded
       variables. See 'gnunet-config --help'.

       Note  that,  in  this stage of development, the file $HOME/.config/gnunet.conf can contain
       sections for all the components.  .. _The-Single_002dUser-Setup:

   The Single-User Setup
       For the single-user setup, you do not need to do anything special and can just  start  the
       GNUnet   background   processes   using   gnunet-arm.   By   default,   GNUnet   looks  in
       ~/.config/gnunet.conf    for    a    configuration    (or     $XDG_CONFIG_HOME/gnunet.conf
       if $XDG_CONFIG_HOME  is  defined). If your configuration lives elsewhere, you need to pass
       the -c FILENAME option to all GNUnet commands.

       Assuming the configuration file is called ~/.config/gnunet.conf, you start your peer using
       the gnunet-arm command (say as user gnunet) using:

          gnunet-arm -c ~/.config/gnunet.conf -s

       The  "-s"  option  here is for "start". The command should return almost instantly. If you
       want to stop GNUnet, you can use:

          gnunet-arm -c ~/.config/gnunet.conf -e

       The "-e" option here is for "end".

       Note that this will only start the basic peer, no actual applications will  be  available.
       If you want to start the file-sharing service, use (after starting GNUnet):

          gnunet-arm -c ~/.config/gnunet.conf -i fs

       The  "-i  fs" option here is for "initialize" the "fs" (file-sharing) application. You can
       also selectively kill only file-sharing support using

          gnunet-arm -c ~/.config/gnunet.conf -k fs

       Assuming that you want certain services (like file-sharing)  to  be  always  automatically
       started  whenever you start GNUnet, you can activate them by setting "IMMEDIATE_START=YES"
       in the respective section of the configuration file (for  example,  "[fs]").  Then  GNUnet
       with file-sharing support would be started whenever you enter:

          gnunet-arm -c ~/.config/gnunet.conf -s

       Alternatively, you can combine the two options:

          gnunet-arm -c ~/.config/gnunet.conf -s -i fs

       Using gnunet-arm is also the preferred method for initializing GNUnet from init.

       Finally, you should edit your crontab (using the crontab command) and insert a line

          @reboot gnunet-arm -c ~/.config/gnunet.conf -s

       to automatically start your peer whenever your system boots.

   The Multi-User Setup
       This  requires  you  to  create  a user gnunet and an additional group gnunetdns, prior to
       running  make  install  during  installation.   Then,  you  create  a  configuration  file
       /etc/gnunet.conf which should contain the lines:

          [arm]
          START_SYSTEM_SERVICES = YES
          START_USER_SERVICES = NO

       Then,  perform  the  same  steps to run GNUnet as in the per-user configuration, except as
       user gnunet (including the crontab installation). You may also want to run gnunet-setup to
       configure  your  peer  (databases,  etc.).  Make  sure  to pass -c /etc/gnunet.conf to all
       commands. If you run gnunet-setup as user gnunet, you might need to change permissions  on
       /etc/gnunet.conf so that the gnunet user can write to the file (during setup).

       Afterwards, you need to perform another setup step for each normal user account from which
       you want to access GNUnet. First, grant the normal user ($USER) permission  to  the  group
       gnunet:

          # adduser $USER gnunet

       Then, create a configuration file in ~/.config/gnunet.conf for the $USER with the lines:

          [arm]
          START_SYSTEM_SERVICES = NO
          START_USER_SERVICES = YES

       This  will  ensure  that gnunet-arm when started by the normal user will only run services
       that are per-user, and otherwise rely on the system-wide services. Note  that  the  normal
       user  may  run gnunet-setup, but the configuration would be ineffective as the system-wide
       services will use /etc/gnunet.conf and ignore options set by individual users.

       Again, each user should then start the peer using gnunet-arm -s --- and strongly  consider
       adding logic to start the peer automatically to their crontab.

       Afterwards,   you   should   see   two   (or  more,  if  you  have  more  than  one  USER)
       gnunet-service-arm processes running in your system.

   Access Control for GNUnet
       This chapter documents how we plan to make access control work within  the  GNUnet  system
       for  a  typical peer. It should be read as a best-practice installation guide for advanced
       users and builders of binary distributions. The recommendations in  this  guide  apply  to
       POSIX-systems with full support for UNIX domain sockets only.

       Note  that this is an advanced topic. The discussion presumes a very good understanding of
       users, groups and file permissions. Normal users on hosts with just a single user can just
       install  GNUnet  under  their own account (and possibly allow the installer to use SUDO to
       grant additional permissions for special GNUnet tools that need  additional  rights).  The
       discussion  below largely applies to installations where multiple users share a system and
       to installations where the best possible security is paramount.

       A typical GNUnet system consists of components that fall into four categories:

       User interfaces
              User interfaces are not security sensitive and are supposed to be run and  used  by
              normal  system  users.  The  GTK GUIs and most command-line programs fall into this
              category. Some command-line tools (like gnunet-transport)  should  be  excluded  as
              they offer low-level access that normal users should not need.

       System services and support tools
              System  services  should always run and offer services that can then be accessed by
              the normal users. System services do not require special permissions, but  as  they
              are not specific to a particular user, they probably should not run as a particular
              user. Also, there should typically  only  be  one  GNUnet  peer  per  host.  System
              services  include  the  gnunet-service  and  gnunet-daemon  programs; support tools
              include command-line programs such as gnunet-arm.

       Privileged helpers
              Some GNUnet components require root rights to open raw  sockets  or  perform  other
              special  operations.  These gnunet-helper binaries are typically installed SUID and
              run from services or daemons.

       Critical services
              Some GNUnet services (such as the DNS service) can manipulate the service  in  deep
              and  possibly  highly  security sensitive ways. For example, the DNS service can be
              used to intercept and alter any DNS  query  originating  from  the  local  machine.
              Access  to the APIs of these critical services and their privileged helpers must be
              tightly controlled.

   Todo
       Shorten these subsection titles

   Recommendation - Disable access to services via TCP
       GNUnet services allow two types of access: via TCP socket or via UNIX  domain  socket.  If
       the  service  is  available via TCP, access control can only be implemented by restricting
       connections to a particular range of IP addresses. This  is  acceptable  for  non-critical
       services  that  are  supposed  to  be  available to all users on the local system or local
       network. However, as TCP is generally less efficient and it is  rarely  the  case  that  a
       single GNUnet peer is supposed to serve an entire local network, the default configuration
       should disable TCP access to all GNUnet services on systems with support for  UNIX  domain
       sockets.  Since  GNUnet  0.9.2,  configuration  files  with  TCP access disabled should be
       generated by default. Users can re-enable TCP access  to  particular  services  simply  by
       specifying a non-zero port number in the section of the respective service.

   Recommendation - Run most services as system user gnunet
       GNUnet's  main  services  should  be  run  as  a separate user "gnunet" in a special group
       "gnunet". The user "gnunet" should start the peer  using  "gnunet-arm  -s"  during  system
       startup.  The home directory for this user should be /var/lib/gnunet and the configuration
       file should be /etc/gnunet.conf. Only the gnunet user should  have  the  right  to  access
       /var/lib/gnunet (mode: 700).

   Recommendation - Control access to services using group gnunet
       Users that should be allowed to use the GNUnet peer should be added to the group "gnunet".
       Using GNUnet's access control mechanism for UNIX domain sockets, those services  that  are
       considered   useful   to   ordinary   users   should   be   made   available   by  setting
       "UNIX_MATCH_GID=YES" for those services. Again, as  shipped,  GNUnet  provides  reasonable
       defaults.   Permissions  to access the transport and core subsystems might additionally be
       granted without necessarily causing security concerns.  Some services, such as  DNS,  must
       NOT  be  made  accessible to the "gnunet" group (and should thus only be accessible to the
       "gnunet" user and services running with this UID).

   Recommendation - Limit access to certain SUID binaries by group gnunet
       Most of GNUnet's SUID binaries should be safe even if executed by normal  users.  However,
       it  is possible to reduce the risk a little bit more by making these binaries owned by the
       group "gnunet" and restricting their execution to user  of  the  group  "gnunet"  as  well
       (4750).

   Recommendation - Limit access to critical gnunet-helper-dns to group gnunetdns
       A   special   group   "gnunetdns"   should  be  created  for  controlling  access  to  the
       "gnunet-helper-dns". The binary should then be owned by root and be in  group  "gnunetdns"
       and be installed SUID and only be group-executable (2750). Note that the group "gnunetdns"
       should have no users in it at  all,  ever.  The  "gnunet-service-dns"  program  should  be
       executed  by  user  "gnunet"  (via  gnunet-service-arm)  with the binary owned by the user
       "root" and the group "gnunetdns" and be SGID (2700). This way,  only  "gnunet-service-dns"
       can change its group to "gnunetdns" and execute the helper, and the helper can then run as
       root (as per SUID).  Access  to  the  API  offered  by  "gnunet-service-dns"  is  in  turn
       restricted  to the user "gnunet" (not the group!), which means that only "benign" services
       can manipulate DNS queries using "gnunet-service-dns".

   Differences between make install and these recommendations
       The current build  system  does  not  set  all  permissions  automatically  based  on  the
       recommendations  above.  In  particular,  it  does  not  use the group "gnunet" at all (so
       setting gnunet-helpers other than the gnunet-helper-dns to be owned by group "gnunet" must
       be  done manually). Furthermore, 'make install' will silently fail to set the DNS binaries
       to be owned by group "gnunetdns" unless that group already exists (!). An alternative name
       for  the  "gnunetdns"  group can be specified using the --with-gnunetdns=GRPNAME configure
       option.

   Configuring the Friend-to-Friend (F2F) mode
       GNUnet knows three basic modes of operation:

       • In standard "peer-to-peer" mode, your peer will connect to any peer.

       • In the pure "friend-to-friend" mode, your peer will ONLY connect to peers from a list of
         friends specified in the configuration.

       • Finally, in mixed mode, GNUnet will only connect to arbitrary peers if it has at least a
         specified number of connections to friends.

       When configuring any of the F2F ("friend-to-friend") modes, you first  need  to  create  a
       file with the peer identities of your friends. Ask your friends to run

          $ gnunet-peerinfo -sq

       The  resulting  output  of  this  command needs to be added to your friends file, which is
       simply a plain text file with one line per friend with the output from the above command.

       You then specify the location of your friends file in the FRIENDS option of the "topology"
       section.

       Once  you  have  created  the  friends  file,  you can tell GNUnet to only connect to your
       friends by setting the FRIENDS-ONLY option (again in the "topology" section) to YES.

       If you want to run in mixed-mode, set "FRIENDS-ONLY" to NO and configure a minimum  number
       of  friends  to  have  (before  connecting to arbitrary peers) under the "MINIMUM-FRIENDS"
       option.

       If you want to operate in normal P2P-only mode, simply set  MINIMUM-FRIENDS  to  zero  and
       FRIENDS_ONLY to NO. This is the default.

   Configuring the hostlist to bootstrap
       After  installing  the  software  you  need  to  get  connected to the GNUnet network. The
       configuration file included in your download is already configured to connect you  to  the
       GNUnet network. In this section the relevant configuration settings are explained.

       To  get  an  initial  connection  to  the  GNUnet network and to get to know peers already
       connected to the network you can use the so called "bootstrap servers". These servers  can
       give you a list of peers connected to the network. To use these bootstrap servers you have
       to configure the hostlist daemon to activate bootstrapping.

       To activate bootstrapping, edit the [hostlist]-section in  your  configuration  file.  You
       have to set the argument -b in the options line:

          [hostlist]
          OPTIONS = -b

       Additionally  you  have to specify which server you want to use. The default bootstrapping
       server is "http://v10.gnunet.org/hostlist". [^] To set the server you  have  to  edit  the
       line "SERVERS" in the hostlist section. To use the default server you should set the lines
       to

          SERVERS = http://v10.gnunet.org/hostlist [^]

       To use bootstrapping your configuration file should include these lines:

          [hostlist]
          OPTIONS = -b
          SERVERS = http://v10.gnunet.org/hostlist [^]

       Besides using bootstrap servers you can configure your GNUnet  peer  to  receive  hostlist
       advertisements. Peers offering hostlists to other peers can send advertisement messages to
       peers that connect to them. If you configure your peer to  receive  these  messages,  your
       peer  can  download  these  lists  and  connect  to  the  peers  included. These lists are
       persistent, which means that they are saved to your hard disk  regularly  and  are  loaded
       during startup.

       To  activate  hostlist  learning  you have to add the -e switch to the OPTIONS line in the
       hostlist section:

          [hostlist]
          OPTIONS = -b -e

       Furthermore you can specify in which file the lists are saved. To save the  lists  in  the
       file hostlists.file just add the line:

          HOSTLISTFILE = hostlists.file

       Best  practice  is  to  activate  both  bootstrapping  and  hostlist  learning.   So  your
       configuration file should include these lines:

          [hostlist]
          OPTIONS = -b -e
          HTTPPORT = 8080
          SERVERS = http://v10.gnunet.org/hostlist [^]
          HOSTLISTFILE = $SERVICEHOME/hostlists.file

   Configuration of the HOSTLIST proxy settings
       The hostlist client can be configured to use a proxy to connect to the hostlist server.

       The hostlist client supports the following proxy types at the moment:

       • HTTP and HTTP 1.0 only proxy

       • SOCKS 4/4a/5/5 with hostname

       In addition authentication at the proxy with username and password can be configured.

       To provide these options directly in  the  configuration,  you  can  enter  the  following
       settings in the [hostlist] section of the configuration:

          # Type of proxy server,
          # Valid values: HTTP, HTTP_1_0, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME
          # Default: HTTP
          # PROXY_TYPE = HTTP

          # Hostname or IP of proxy server
          # PROXY =
          # User name for proxy server
          # PROXY_USERNAME =
          # User password for proxy server
          # PROXY_PASSWORD =

   Configuring your peer to provide a hostlist
       If  you  operate a peer permanently connected to GNUnet you can configure your peer to act
       as a hostlist server, providing other peers the list of peers known to him.

       Your server can act as a bootstrap server and peers needing to obtain a list of peers  can
       contact  it  to download this list. To download this hostlist the peer uses HTTP. For this
       reason you have to build your peer with libgnurl (or libcurl) and microhttpd support.

       To configure your peer to act as a bootstrap server you have  to  add  the  -p  option  to
       OPTIONS  in  the  [hostlist]  section of your configuration file. Besides that you have to
       specify a port number for the http server. In conclusion you have  to  add  the  following
       lines:

          [hostlist]
          HTTPPORT = 12980
          OPTIONS = -p

       If  your  peer  acts  as  a  bootstrap  server other peers should know about that. You can
       advertise the hostlist your are providing to other peers.  Peers connecting to  your  peer
       will  get a message containing an advertisement for your hostlist and the URL where it can
       be downloaded.  If this peer is in learning mode, it will test the hostlist  and,  in  the
       case it can obtain the list successfully, it will save it for bootstrapping.

       To  activate  hostlist  advertisement on your peer, you have to set the following lines in
       your configuration file:

          [hostlist]
          EXTERNAL_DNS_NAME = example.org
          HTTPPORT = 12981
          OPTIONS = -p -a

       With this configuration your peer will a act as a  bootstrap  server  and  advertise  this
       hostlist  to  other  peers  connecting  to  it.  The URL used to download the list will be
       http://example.org:12981/.

       Please notice:

       • The hostlist is not human readable, so you should not try  to  download  it  using  your
         webbrowser. Just point your GNUnet peer to the address!

       • Advertising without providing a hostlist does not make sense and will not work.

   Configuring the datastore
       The  datastore  is  what GNUnet uses for long-term storage of file-sharing data. Note that
       long-term does not mean 'forever' since content does  have  an  expiration  date,  and  of
       course storage space is finite (and hence sometimes content may have to be discarded).

       Use  the  QUOTA  option  to  specify  how  many  bytes of storage space you are willing to
       dedicate to GNUnet.

       In addition to specifying the maximum space GNUnet is allowed to use  for  the  datastore,
       you  need  to  specify  which database GNUnet should use to do so. Currently, you have the
       choice between sqLite, MySQL and Postgres.

   Configuring the MySQL database
       This section describes how to setup the MySQL database for GNUnet.

       Note that the mysql plugin does NOT work with mysql before  4.1  since  we  need  prepared
       statements. We are generally testing the code against MySQL 5.1 at this point.

   Reasons for using MySQL
       • On up-to-date hardware where mysql can be used comfortably, this module will have better
         performance than the other database choices (according to our tests).

       • Its often possible to recover the mysql database from internal inconsistencies. Some  of
         the other databases do not support repair.

   Reasons for not using MySQL
       • Memory usage (likely not an issue if you have more than 1 GB)

       • Complex manual setup

   Setup Instructions
       • In gnunet.conf set in section DATASTORE the value for DATABASE to mysql.

       • Access mysql as root:

            $ mysql -u root -p

         and issue the following commands, replacing $USER with the username that will be running
         gnunet-arm (so typically "gnunet"):

            CREATE DATABASE gnunet;
            GRANT select,insert,update,delete,create,alter,drop,create temporary tables ON gnunet.* TO $USER@localhost;
            SET PASSWORD FOR $USER@localhost=PASSWORD('$the_password_you_like');
            FLUSH PRIVILEGES;

       • In the $HOME directory of $USER, create a .my.cnf file with the following lines

            [client]
            user=$USER
            password=$the_password_you_like

       That's it. Note that .my.cnf file  is  a  slight  security  risk  unless  its  on  a  safe
       partition.  The  $HOME/.my.cnf  can  of  course be a symbolic link. Luckily $USER has only
       privileges to mess up GNUnet's tables, which should be pretty harmless.

   Testing
       You should briefly try if the database connection works. First, login as $USER. Then use:

          $ mysql -u $USER
          mysql> use gnunet;

       If you get the message

          Database changed

       it probably works.

       If you get

          ERROR 2002: Can't connect to local MySQL server
          through socket '/tmp/mysql.sock' (2)

       it may be resolvable by

          ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock

       so there may be some additional trouble depending on your mysql setup.

   Performance Tuning
       For GNUnet, you probably want to set the option

   Todo
       Code block not C, set appropriate language

          innodb_flush_log_at_trx_commit = 0

       for a rather dramatic boost in MySQL performance. However, this reduces  the  "safety"  of
       your database as with this options you may loose transactions during a power outage. While
       this is totally harmless for GNUnet, the option applies to all applications  using  MySQL.
       So  you should set it if (and only if) GNUnet is the only application on your system using
       MySQL.

   Setup for running Testcases
       If you want to run the testcases, you must create a second database "gnunetcheck" with the
       same username and password. This database will then be used for testing (make check).

   Configuring the Postgres database
       This text describes how to setup the Postgres database for GNUnet.

       This Postgres plugin was developed for Postgres 8.3 but might work for earlier versions as
       well.

   Reasons to use Postgres
       • Easier to setup than MySQL

       • Real database

   Reasons not to use Postgres
       • Quite slow

       • Still some manual setup required

   Manual setup instructions
       • In gnunet.conf set in section DATASTORE the value for DATABASE to postgres.

       • Access Postgres to create a user:

         with Postgres 8.x, use:

                   # su - postgres
                   $ createuser

                and enter the name of the user running GNUnet for the role  interactively.  Then,
                when  prompted,  do not set it to superuser, allow the creation of databases, and
                do not allow the creation of new roles.

         with Postgres 9.x, use:

                   # su - postgres
                   $ createuser -d $GNUNET_USER

                where $GNUNET_USER is the name of the user running GNUnet.

       • As that user (so typically as user "gnunet"), create a database (or two):

            $ createdb gnunet
            # this way you can run "make check"
            $ createdb gnunetcheck

       Now you should be able to start gnunet-arm.

   Testing the setup manually
       You may want to try if the database connection works. First, again login as the  user  who
       will run gnunet-arm. Then use:

          $ psql gnunet # or gnunetcheck
          gnunet=> \dt

       If,  after  you  have  started  gnunet-arm  at  least once, you get a gn090 table here, it
       probably works.

   Configuring the datacache
       The datacache is what GNUnet uses for storing temporary data. This data is expected to  be
       wiped completely each time GNUnet is restarted (or the system is rebooted).

       You  need  to  specify how many bytes GNUnet is allowed to use for the datacache using the
       QUOTA option in the section [dhtcache].  Furthermore, you need to specify  which  database
       backend  should  be used to store the data. Currently, you have the choice between sqLite,
       MySQL and Postgres.

   Configuring the file-sharing service
       In order to use GNUnet for file-sharing, you first need to make sure that the file-sharing
       service  is  loaded. This is done by setting the START_ON_DEMAND option in section [fs] to
       "YES".  Alternatively, you can run

          $ gnunet-arm -i fs

       to start the file-sharing service by hand.

       Except for configuring the database and  the  datacache  the  only  important  option  for
       file-sharing is content migration.

       Content  migration  allows your peer to cache content from other peers as well as send out
       content stored on your system without explicit  requests.  This  content  replication  has
       positive and negative impacts on both system performance and privacy.

       FIXME: discuss the trade-offs. Here is some older text about it...

       Setting  this  option  to YES allows gnunetd to migrate data to the local machine. Setting
       this option to YES is highly recommended for efficiency. Its also the default. If you  set
       this  value  to  YES,  GNUnet  will store content on your machine that you cannot decrypt.
       While this may protect you from liability if the judge is sane, it may  not  (IANAL).   If
       you put illegal content on your machine yourself, setting this option to YES will probably
       increase your chances to get away with it since you can plausibly deny that  you  inserted
       the content. Note that in either case, your anonymity would have to be broken first (which
       may be possible depending on the size of the  GNUnet  network  and  the  strength  of  the
       adversary).

   Configuring logging
       Since  version 0.9.0, logging in GNUnet is controlled via the -L and -l options. Using -L,
       a log level can be specified. With log level ERROR only serious  errors  are  logged.  The
       default log level is WARNING which causes anything of concern to be logged. Log level INFO
       can be used to log anything that might be interesting information  whereas  DEBUG  can  be
       used  by  developers  to  log  debugging  messages  (but  you need to run ./configure with
       --enable-logging=verbose to get them compiled). The -l option is used to specify  the  log
       file.

       Since  most GNUnet services are managed by gnunet-arm, using the -l or -L options directly
       is not possible. Instead, they can be specified using the OPTIONS configuration  value  in
       the  respective  section  for  the respective service. In order to enable logging globally
       without editing the OPTIONS values for each service, gnunet-arm supports a  GLOBAL_POSTFIX
       option. The value specified here is given as an extra option to all services for which the
       configuration does contain a service-specific OPTIONS field.

       GLOBAL_POSTFIX can contain the special sequence "{}" which is replaced by the name of  the
       service  that  is  being started. Furthermore, GLOBAL_POSTFIX is special in that sequences
       starting with "$" anywhere in the string are expanded (according  to  options  in  PATHS);
       this  expansion  otherwise  is  only  happening for filenames and then the "$" must be the
       first character in the option. Both of these restrictions do not apply to  GLOBAL_POSTFIX.
       Note that specifying % anywhere in the GLOBAL_POSTFIX disables both of these features.

       In  summary,  in  order  to  get  all  services  to  log at level INFO to log-files called
       SERVICENAME-logs, the following global prefix should be used:

          GLOBAL_POSTFIX = -l $SERVICEHOME/{}-logs -L INFO

   Configuring the transport service and plugins
       The transport service in GNUnet is responsible to maintain  basic  connectivity  to  other
       peers. Besides initiating and keeping connections alive it is also responsible for address
       validation.

       The GNUnet transport supports more  than  one  transport  protocol.  These  protocols  are
       configured together with the transport service.

       The  configuration  section  for  the transport service itself is quite similar to all the
       other services

          START_ON_DEMAND = YES
          @UNIXONLY@ PORT = 2091
          HOSTNAME = localhost
          HOME = $SERVICEHOME
          CONFIG = $DEFAULTCONFIG
          BINARY = gnunet-service-transport
          #PREFIX = valgrind
          NEIGHBOUR_LIMIT = 50
          ACCEPT_FROM = 127.0.0.1;
          ACCEPT_FROM6 = ::1;
          PLUGINS = tcp udp
          UNIXPATH = /tmp/gnunet-service-transport.sock

       Different are the settings for the plugins to load PLUGINS. The  first  setting  specifies
       which transport plugins to load.

       • transport-unix  A plugin for local only communication with UNIX domain sockets. Used for
         testing and available on unix systems only. Just set the port

            [transport-unix]
            PORT = 22086
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

       • transport-tcp A plugin for communication with TCP. Set port to 0 for  client  mode  with
         outbound only connections

            [transport-tcp]
            # Use 0 to ONLY advertise as a peer behind NAT (no port binding)
            PORT = 2086
            ADVERTISED_PORT = 2086
            TESTING_IGNORE_KEYS = ACCEPT_FROM;
            # Maximum number of open TCP connections allowed
            MAX_CONNECTIONS = 128

       • transport-udp  A  plugin  for  communication  with  UDP.  Supports  peer discovery using
         broadcasts.

            [transport-udp]
            PORT = 2086
            BROADCAST = YES
            BROADCAST_INTERVAL = 30 s
            MAX_BPS = 1000000
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

       • transport-http HTTP and HTTPS support is split in two part: a client  plugin  initiating
         outbound connections and a server part accepting connections from the client. The client
         plugin just takes the maximum number of connections as an argument.

            [transport-http_client]
            MAX_CONNECTIONS = 128
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

            [transport-https_client]
            MAX_CONNECTIONS = 128
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

         The server has a port configured and the maximum number of connections. The  HTTPS  part
         has two files with the certificate key and the certificate file.

         The  server plugin supports reverse proxies, so a external hostname can be set using the
         EXTERNAL_HOSTNAME setting. The webserver under this address should forward  the  request
         to the peer and the configure port.

            [transport-http_server]
            EXTERNAL_HOSTNAME = fulcrum.net.in.tum.de/gnunet
            PORT = 1080
            MAX_CONNECTIONS = 128
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

            [transport-https_server]
            PORT = 4433
            CRYPTO_INIT = NORMAL
            KEY_FILE = https.key
            CERT_FILE = https.cert
            MAX_CONNECTIONS = 128
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

       • transport-wlan

         The next section describes how to setup the WLAN plugin, so here only the settings. Just
         specify the interface to use:

            [transport-wlan]
            # Name of the interface in monitor mode (typically monX)
            INTERFACE = mon0
            # Real hardware, no testing
            TESTMODE = 0
            TESTING_IGNORE_KEYS = ACCEPT_FROM;

   Configuring the WLAN transport plugin
       The wlan transport plugin enables GNUnet to send and to receive data on a wlan  interface.
       It  has  not  to  be connected to a wlan network as long as sender and receiver are on the
       same channel. This enables you to get connection to GNUnet where  no  internet  access  is
       possible,  for  example  during  catastrophes  or  when  censorship  cuts you off from the
       internet.

   Requirements for the WLAN plugin
       • wlan network card with monitor support and packet injection (see aircrack-ng.org)

       • Linux kernel with mac80211 stack, introduced in 2.6.22, tested with 2.6.35 and 2.6.38

       • Wlantools to create the a monitor interface, tested with airmon-ng  of  the  aircrack-ng
         package

   Configuration
       There  are  the  following  options  for the wlan plugin (they should be like this in your
       default config file, you only need to adjust them if the values  are  incorrect  for  your
       system)

          # section for the wlan transport plugin
          [transport-wlan]
          # interface to use, more information in the
          # "Before starting GNUnet" section of the handbook.
          INTERFACE = mon0
          # testmode for developers:
          # 0 use wlan interface,
          #1 or 2 use loopback driver for tests 1 = server, 2 = client
          TESTMODE = 0

   Before starting GNUnet
       Before starting GNUnet, you have to make sure that your wlan interface is in monitor mode.
       One way to put the wlan interface into monitor mode (if your interface name is  wlan0)  is
       by executing:

          sudo airmon-ng start wlan0

       Here is an example what the result should look like:

          Interface Chipset Driver
          wlan0 Intel 4965 a/b/g/n iwl4965 - [phy0]
          (monitor mode enabled on mon0)

       The monitor interface is mon0 is the one that you have to put into the configuration file.

   Limitations and known bugs
       Wlan  speed is at the maximum of 1 Mbit/s because support for choosing the wlan speed with
       packet injection was removed in newer kernels.  Please pester the kernel developers  about
       fixing this.

       The  interface  channel  depends  on the wlan network that the card is connected to. If no
       connection has been made since the start of the computer, it is usually the first  channel
       of  the  card.  Peers  will  only  find each other and communicate if they are on the same
       channel.  Channels must be set manually, e.g. by using:

          iwconfig wlan0 channel 1

   Configuring HTTP(S) reverse proxy functionality using Apache or nginx
       The HTTP plugin supports data transfer using reverse proxies. A reverse proxy forwards the
       HTTP request he receives with a certain URL to another webserver, here a GNUnet peer.

       So  if  you  have  a running Apache or nginx webserver you can configure it to be a GNUnet
       reverse proxy. Especially if you  have  a  well-known  website  this  improves  censorship
       resistance since it looks as normal surfing behaviour.

       To do so, you have to do two things:

       • Configure your webserver to forward the GNUnet HTTP traffic

       • Configure your GNUnet peer to announce the respective address

       As an example we want to use GNUnet peer running:

       • HTTP server plugin on gnunet.foo.org:1080

       • HTTPS server plugin on gnunet.foo.org:4433

       • A apache or nginx webserver on http://www.foo.org:80/

       • A apache or nginx webserver on https://www.foo.org:443/

       And  we  want  the  webserver  to accept GNUnet traffic under http://www.foo.org/bar/. The
       required steps are described here:

   Reverse Proxy - Configure your Apache2 HTTP webserver
       First of all you need mod_proxy installed.

       Edit your webserver configuration. Edit  /etc/apache2/apache2.conf  or  the  site-specific
       configuration file.

       In the respective server config,virtual host or directory section add the following lines:

          ProxyTimeout 300
          ProxyRequests Off
          <Location /bar/ >
          ProxyPass http://gnunet.foo.org:1080/
          ProxyPassReverse http://gnunet.foo.org:1080/
          </Location>

   Reverse Proxy - Configure your Apache2 HTTPS webserver
       We  assume  that  you  already  have  an  HTTPS server running, if not please check how to
       configure a HTTPS host. An uncomplicated to use example is the example configuration  file
       for Apache2/HTTPD provided in apache2/sites-available/default-ssl.

       In  the respective HTTPS server config,virtual host or directory section add the following
       lines:

          SSLProxyEngine On
          ProxyTimeout 300
          ProxyRequests Off
          <Location /bar/ >
          ProxyPass https://gnunet.foo.org:4433/
          ProxyPassReverse https://gnunet.foo.org:4433/
          </Location>

       More information about the apache mod_proxy configuration  can  be  found  in  the  Apache
       documentation.

   Reverse Proxy - Configure your nginx HTTPS webserver
       Since  nginx  does  not  support  chunked  encoding,  you first of all have to install the
       chunkin module.

       To enable chunkin add:

          chunkin on;
          error_page 411 = @my_411_error;
          location @my_411_error {
          chunkin_resume;
          }

       Edit  your  webserver  configuration.  Edit  /etc/nginx/nginx.conf  or  the  site-specific
       configuration file.

       In the server section add:

          location /bar/ {
          proxy_pass http://gnunet.foo.org:1080/;
          proxy_buffering off;
          proxy_connect_timeout 5; # more than http_server
          proxy_read_timeout 350; # 60 default, 300s is GNUnet's idle timeout
          proxy_http_version 1.1; # 1.0 default
          proxy_next_upstream error timeout invalid_header http_500 http_503 http_502 http_504;
          }

   Reverse Proxy - Configure your nginx HTTP webserver
       Edit  your  webserver  configuration.  Edit  /etc/nginx/nginx.conf  or  the  site-specific
       configuration file.

       In the server section add:

          ssl_session_timeout 6m;
          location /bar/
          {
          proxy_pass https://gnunet.foo.org:4433/;
          proxy_buffering off;
          proxy_connect_timeout 5; # more than http_server
          proxy_read_timeout 350; # 60 default, 300s is GNUnet's idle timeout
          proxy_http_version 1.1; # 1.0 default
          proxy_next_upstream error timeout invalid_header http_500 http_503 http_502 http_504;
          }

   Reverse Proxy - Configure your GNUnet peer
       To have your GNUnet peer announce the address, you have to specify  the  EXTERNAL_HOSTNAME
       option in the [transport-http_server] section:

          [transport-http_server]
          EXTERNAL_HOSTNAME = http://www.foo.org/bar/

       and/or [transport-https_server] section:

          [transport-https_server]
          EXTERNAL_HOSTNAME = https://www.foo.org/bar/

       Now restart your webserver and your peer...

   Blacklisting peers
       Transport  service  supports  to  deny connecting to a specific peer of to a specific peer
       with a specific transport plugin using the blacklisting component  of  transport  service.
       With blacklisting  it  is  possible  to  deny  connections  to  specific peers of to use a
       specific plugin to a specific peer. Peers can be blacklisted using the configuration or  a
       blacklist client can be asked.

       To blacklist peers using the configuration you have to add a section to your configuration
       containing the peer id of the peer to blacklist and the plugin if required.

       Examples:

       To blacklist connections to P565... on peer AG2P... using tcp add:

   Todo
       too long?

   Todo
       verify whether these still produce errors in pdf output

          [transport-blacklist AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520]
          P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = tcp

       To blacklist connections to P565... on peer AG2P... using all plugins add:

          [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520]
          P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G =

       You can also add a blacklist client  using  the  blacklist  API.  On  a  blacklist  check,
       blacklisting  first  checks  internally if the peer is blacklisted and if not, it asks the
       blacklisting clients. Clients are asked if it is OK to connect to a peer ID, the plugin is
       omitted.

       On blacklist check for (peer, plugin)

       • Do we have a local blacklist entry for this peer and this plugin?

       • YES: disallow connection

       • Do we have a local blacklist entry for this peer and all plugins?

       • YES: disallow connection

       • Does one of the clients disallow?

       • YES: disallow connection

   Configuration of the HTTP and HTTPS transport plugins
       The  client parts of the http and https transport plugins can be configured to use a proxy
       to connect to the hostlist server.

       Both the HTTP and HTTPS clients support the following proxy types at the moment:

       • HTTP 1.1 proxy

       • SOCKS 4/4a/5/5 with hostname

       In addition authentication at the proxy with username and password can be configured.

       To configure these options directly in the configuration, you can configure the  following
       settings  in  the  [transport-http_client]  and  [transport-https_client]  section  of the
       configuration:

          # Type of proxy server,
          # Valid values: HTTP, SOCKS4, SOCKS5, SOCKS4A, SOCKS5_HOSTNAME
          # Default: HTTP
          # PROXY_TYPE = HTTP

          # Hostname or IP of proxy server
          # PROXY =
          # User name for proxy server
          # PROXY_USERNAME =
          # User password for proxy server
          # PROXY_PASSWORD =

   Configuring the GNUnet VPN
       Before configuring the GNUnet VPN, please make sure that system-wide DNS  interception  is
       configured  properly  as described in the section on the GNUnet DNS setup. see Configuring
       the GNU Name System, if you haven't done so already.

       The default options for the GNUnet VPN are usually sufficient to use GNUnet as a  Layer  2
       for  your  Internet  connection.  However,  what  you  always  have to specify is which IP
       protocol you want to tunnel: IPv4, IPv6 or both. Furthermore, if you tunnel both, you most
       likely  should  also  tunnel all of your DNS requests. You theoretically can tunnel "only"
       your DNS traffic, but that usually makes little sense.

       The other options as shown on the gnunet-setup tool are:

   IPv4 address for interface
       This is the IPv4 address the VPN interface will get. You  should  pick  a  'private'  IPv4
       network   that   is   not   yet   in   use  for  you  system.  For  example,  if  you  use
       10.0.0.1/255.255.0.0  already,  you   might   use   10.1.0.1/255.255.0.0.   If   you   use
       10.0.0.1/255.0.0.0  already, then you might use 192.168.0.1/255.255.0.0. If your system is
       not in a private IP-network, using any of the above will work fine. You should try to make
       the  mask of the address big enough (255.255.0.0 or, even better, 255.0.0.0) to allow more
       mappings of remote IP Addresses into this range. However, even a 255.255.255.0  mask  will
       suffice for most users.

   IPv6 address for interface
       The  IPv6  address  the  VPN  interface  will get. Here you can specify any non-link-local
       address (the address should not begin with fe80:). A subnet Unique Local Unicast (fd00::/8
       prefix) that you are currently not using would be a good choice.

   Configuring the GNUnet VPN DNS
       To resolve names for remote nodes, activate the DNS exit option.

   Configuring the GNUnet VPN Exit Service
       If  you  want  to  allow  other  users to share your Internet connection (yes, this may be
       dangerous, just as running a Tor exit node) or want to provide access to services on  your
       host  (this  should  be less dangerous, as long as those services are secure), you have to
       enable the GNUnet exit daemon.

       You then get to specify which exit functions you want to provide.  By  enabling  the  exit
       daemon, you will always automatically provide exit functions for manually configured local
       services (this component of the system is under development and not documented further  at
       this  time).  As for those services you explicitly specify the target IP address and port,
       there is no significant security risk in doing so.

       Furthermore, you can serve as a DNS, IPv4 or IPv6 exit to the Internet.  Being a DNS  exit
       is   usually  pretty  harmless.  However,  enabling  IPv4  or  IPv6-exit  without  further
       precautions may enable adversaries to access your local network, send spam,  attack  other
       systems from your Internet connection and do other mischiefs that will appear to come from
       your machine. This may or may not get you into legal trouble. If you want to allow IPv4 or
       IPv6-exit  functionality,  you  should  strongly consider adding additional firewall rules
       manually to protect your local network and to restrict outgoing TCP traffic (e.g.  by  not
       allowing access to port 25). While we plan to improve exit-filtering in the future, you're
       currently on your own here. Essentially, be prepared for any kind of  IP-traffic  to  exit
       the  respective  TUN  interface  (and  GNUnet  will  enable  IP-forwarding and NAT for the
       interface automatically).

       Additional configuration options of the exit as shown by the gnunet-setup tool are:

   IP Address of external DNS resolver
       If DNS traffic is to exit your machine, it will be send to  this  DNS  resolver.  You  can
       specify an IPv4 or IPv6 address.

   IPv4 address for Exit interface
       This  is  the IPv4 address the Interface will get. Make the mask of the address big enough
       (255.255.0.0 or, even better, 255.0.0.0) to allow more mappings of IP addresses into  this
       range. As for the VPN interface, any unused, private IPv4 address range will do.

   IPv6 address for Exit interface
       The public IPv6 address the interface will get. If your kernel is not a very recent kernel
       and you are willing to manually enable IPv6-NAT, the IPv6 address you specify here must be
       a globally routed IPv6 address of your host.

       Suppose  your host has the address 2001:4ca0::1234/64, then using 2001:4ca0::1:0/112 would
       be fine (keep the first 64 bits, then change at least one bit  in  the  range  before  the
       bitmask, in the example above we changed bit 111 from 0 to 1).

       You  may  also  have  to  configure  your  router  to  route traffic for the entire subnet
       (2001:4ca0::1:0/112 for example) through your computer  (this  should  be  automatic  with
       IPv6, but obviously anything can be disabled).

   Bandwidth Configuration
       You can specify how many bandwidth GNUnet is allowed to use to receive and send data. This
       is important for users with limited bandwidth or traffic volume.

   Configuring NAT
       Most hosts today do not have a normal global IP address but instead are  behind  a  router
       performing  Network Address Translation (NAT) which assigns each host in the local network
       a private IP address. As  a  result,  these  machines  cannot  trivially  receive  inbound
       connections  from  the Internet. GNUnet supports NAT traversal to enable these machines to
       receive incoming connections from other peers despite their limitations.

       In an ideal  world,  you  can  press  the  "Attempt  automatic  configuration"  button  in
       gnunet-setup   to  automatically  configure  your  peer  correctly.   Alternatively,  your
       distribution  might  have  already  triggered  this  automatic  configuration  during  the
       installation  process.  However, automatic configuration can fail to determine the optimal
       settings, resulting in your peer either not receiving as many connections as possible,  or
       in the worst case it not connecting to the network at all.

       To  manually  configure  the peer, you need to know a few things about your network setup.
       First, determine if you are behind a NAT in the first place. This is always  the  case  if
       your  IP  address  starts with "10.*"  or "192.168.*". Next, if you have control over your
       NAT router, you may choose to manually configure it to allow GNUnet traffic to your  host.
       If  you  have  configured your NAT to forward traffic on ports 2086 (and possibly 1080) to
       your host, you can  check  the  "NAT  ports  have  been  opened  manually"  option,  which
       corresponds  to  the  "PUNCHED_NAT" option in the configuration file. If you did not punch
       your NAT box, it may  still  be  configured  to  support  UPnP,  which  allows  GNUnet  to
       automatically  configure it. In that case, you need to install the "upnpc" command, enable
       UPnP (or PMP) on your NAT box and set the "Enable NAT traversal via UPnP  or  PMP"  option
       (corresponding to "ENABLE_UPNP" in the configuration file).

       Some  NAT  boxes can be traversed using the autonomous NAT traversal method. This requires
       certain GNUnet components to be installed with "SUID" privileges on  your  system  (so  if
       you're  installing  on  a  system  you do not have administrative rights to, this will not
       work). If you installed as 'root', you can enable autonomous NAT traversal by checking the
       "Enable NAT traversal using ICMP method". The ICMP method requires a way to determine your
       NAT's external (global) IP address. This can be done using  either  UPnP,  DynDNS,  or  by
       manual  configuration.  If  you  have  a DynDNS name or know your external IP address, you
       should enter that name under "External (public) IPv4 address" (which  corresponds  to  the
       "EXTERNAL_ADDRESS"  option  in  the  configuration  file).  If you leave the option empty,
       GNUnet will try to determine your external IP address automatically (which  may  fail,  in
       which case autonomous NAT traversal will then not work).

       Finally,  if you yourself are not behind NAT but want to be able to connect to NATed peers
       using autonomous NAT traversal, you need to check the "Enable connecting  to  NATed  peers
       using ICMP method" box.

   Peer configuration for distributors (e.g. Operating Systems)
       The  "GNUNET_DATA_HOME"  in  "[PATHS]"  in  /etc/gnunet.conf  should  be  manually  set to
       "/var/lib/gnunet/data/" as the  default  "~/.local/share/gnunet/"  is  probably  not  that
       appropriate    in    this    case.   Similarly,   distributors   may   consider   pointing
       "GNUNET_RUNTIME_DIR" to "/var/run/gnunet/" and "GNUNET_HOME" to "/var/lib/gnunet/".  Also,
       should  a  distributor  decide to override system defaults, all of these changes should be
       done in a custom /etc/gnunet.conf and not in the files in the config.d/ directory.

       Given the proposed access permissions, the "gnunet-setup" tool must be run as use "gnunet"
       (and  with  option "-c /etc/gnunet.conf" so that it modifies the system configuration). As
       always, gnunet-setup should be run after the GNUnet peer  was  stopped  using  "gnunet-arm
       -e".   Distributors  might  want  to  include  a  wrapper for gnunet-setup that allows the
       desktop-user to "sudo" (e.g. using gtksudo) to the "gnunet" user  account  and  then  runs
       "gnunet-arm -e", "gnunet-setup" and "gnunet-arm -s" in sequence.

DEVELOPER HANDBOOK

       This book is intended to be an introduction for programmers that want to extend the GNUnet
       framework. GNUnet is more than a simple peer-to-peer application.

       For developers, GNUnet is:

       • developed by a community that believes in the GNU philosophy

       • Free Software (Free as in Freedom), licensed under the GNU Affero General Public License

       • A set of standards, including coding conventions and architectural rules

       • A set of layered protocols, both specifying the communication between peers as  well  as
         the communication between components of a single peer

       • A set of libraries with well-defined APIs suitable for writing extensions

       In  particular,  the  architecture  specifies  that  a  peer  consists  of  many processes
       communicating via protocols. Processes can be written in almost any language.  C, Java and
       Guile  APIs  exist  for  accessing  existing  services  and for writing extensions.  It is
       possible to write  extensions  in  other  languages  by  implementing  the  necessary  IPC
       protocols.

       GNUnet  can be extended and improved along many possible dimensions, and anyone interested
       in Free Software and Freedom-enhancing Networking is welcome  to  join  the  effort.  This
       Developer  Handbook  attempts to provide an initial introduction to some of the key design
       choices and central components of the system.

       This part of the GNUnet documentation is  far  from  complete,  and  we  welcome  informed
       contributions, be it in the form of new chapters, sections or insightful comments.

   Contributing
   Licenses of contributions
       GNUnet  is  a  GNU  package.  All code contributions must thus be put under the GNU Affero
       Public License (AGPL). All documentation should be put under FSF  approved  licenses  (see
       fdl).

       By  submitting  documentation, translations, and other content to GNUnet you automatically
       grant the right to publish code under the  GNU  Public  License  and  documentation  under
       either  or  both  the  GNU  Public  License  or  the  GNU Free Documentation License. When
       contributing to the GNUnet project, GNU standards and the GNU philosophy should be adhered
       to.

   Copyright Assignment
   Todo
       Link to copyright assignment.

       We  require  a  formal  copyright  assignment  for  GNUnet  contributors  to  GNUnet e.V.;
       nevertheless, we do allow pseudonymous contributions. By signing the  copyright  agreement
       and  submitting  your code (or documentation) to us, you agree to share the rights to your
       code with GNUnet e.V.;  GNUnet  e.V.  receives  non-exclusive  ownership  rights,  and  in
       particular  is  allowed  to dual-license the code. You retain non-exclusive rights to your
       contributions, so you can also share your contributions freely with other projects.

       GNUnet e.V. will publish all accepted contributions under the AGPLv3 or any later version.
       The   association   may   decide   to  publish  contributions  under  additional  licenses
       (dual-licensing).

       We do not intentionally  remove  your  name  from  your  contributions;  however,  due  to
       extensive editing it is not always trivial to attribute contributors properly. If you find
       that you significantly contributed to a file (or the project  as  a  whole)  and  are  not
       listed in the respective authors file or section, please do let us know.

   Contributing to the Reference Manual
   Todo
       Move section to contrib.rst?

   Todo
       Update contrib section to reflect move to reStructuredText

       • When  writing documentation, please use gender-neutral wording when referring to people,
         such as singular “they”, “their”, “them”, and so forth.

       • Keep line length below 74 characters, except for URLs. URLs break in the PDF output when
         they contain linebreaks.

       • Do not use tab characters (see chapter 2.1 texinfo manual)

       • Write texts in the third person perspective.

   Contributing testcases
       In  the core of GNUnet, we restrict new testcases to a small subset of languages, in order
       of preference:

       1. C

       2. Portable Shell Scripts

       3. Python (3.7 or later)

       We welcome efforts to remove our existing Python 2.7 scripts to replace them  either  with
       portable shell scripts or, at your choice, Python 3.7 or later.

       If  you  contribute  new  python  based  testcases,  we  advise you to not repeat our past
       misfortunes and write the tests in a standard test framework like for example pytest.

       For writing portable shell scripts, these tools are useful:

       •

         Shellcheck, for static
                analysis of shell scripts.

       • http://www.etalabs.net/sh_tricks.html,

       •

         bash-dash (/bin/sh on Debian) interoperabilitycheckbashisms,

                •

                  `https://wiki.ubuntu.com/DashAsBinSh`__
                  , and

                •

                  `https://mywiki.wooledge.org/Bashism`__

   Style Guide
       This document contains normative rules for writing GNUnet code and naming conventions used
       throughout the project.

   Naming conventions
   Header files
       For header files, the following suffixes should be used:

                             ┌──────────┬──────────────────────────────────┐
                             │Suffix    │ Usage                            │
                             ├──────────┼──────────────────────────────────┤
                             │_lib      │ Libraries   without   associated │
                             │          │ processes                        │
                             ├──────────┼──────────────────────────────────┤
                             │_service  │ Libraries     using      service │
                             │          │ processes                        │
                             ├──────────┼──────────────────────────────────┤
                             │_plugin   │ Plugin definition                │
                             ├──────────┼──────────────────────────────────┤
                             │_protocol │ structs used in network protocol │
                             └──────────┴──────────────────────────────────┘

       There exist a few exceptions to these rules within the codebase:

       • gnunet_config.h and gnunet_directories.h are automatically generated.

       • gnunet_common.h, which defines fundamental routines

       • platform.h, first included.  .. I have no idea what that means

       • gettext.h, an external library.

   Binaries
       For binary files, the following convention should be used:

                    ┌────────────────────────────┬──────────────────────────────────┐
                    │Name format                 │ Usage                            │
                    ├────────────────────────────┼──────────────────────────────────┤
                    │gnunet-service-xxx          │ Service  processes  (with listen │
                    │                            │ sockets)                         │
                    ├────────────────────────────┼──────────────────────────────────┤
                    │gnunet-daemon-xxx           │ Daemon processes (without listen │
                    │                            │ sockets)                         │
                    ├────────────────────────────┼──────────────────────────────────┤
                    │gnunet-helper-xxx[-yyy]     │ SUID helper for module xxx       │
                    ├────────────────────────────┼──────────────────────────────────┤
                    │gnunet-yyy                  │ End-user command line tools      │
                    └────────────────────────────┴──────────────────────────────────┘

                    │libgnunet_plugin_xxx_yyy.so │ Plugin for API xxx               │
                    ├────────────────────────────┼──────────────────────────────────┤
                    │libgnunetxxx.so             │ Library for API xxx              │
                    └────────────────────────────┴──────────────────────────────────┘

   Logging
       The convention is to define a macro on a per-file basis to manage logging:

          #define LOG(kind,...)
          [logging_macro] (kind, "[component_name]", __VA_ARGS__)

       The  table below indicates the substitutions which should be made for [component_name] and
       [logging_macro].

             ┌─────────────────────────┬────────────────────────────────┬─────────────────┐
             │Software category        │ [component_name][logging_macro] │
             ├─────────────────────────┼────────────────────────────────┼─────────────────┤
             │Services and daemons     │ Directory    name     in       │ GNUNET_log      │
             │                         │ GNUNET_log_setup               │                 │
             ├─────────────────────────┼────────────────────────────────┼─────────────────┤
             │Command line tools       │ Full       name       in       │ GNUNET_log      │
             │                         │ GNUNET_log_setup               │                 │
             ├─────────────────────────┼────────────────────────────────┼─────────────────┤
             │Service access libraries │ [directory_name]GNUNET_log_from │
             ├─────────────────────────┼────────────────────────────────┼─────────────────┤
             │Pure libraries           │ Library  name   (without       │ GNUNET_log_from │
             │                         │ lib or .so)                    │                 │
             ├─────────────────────────┼────────────────────────────────┼─────────────────┤
             │Plugins                  │ [directory_name]-[plugin_name]GNUNET_log_from │
             └─────────────────────────┴────────────────────────────────┴─────────────────┘

   Todo
       Clear up terminology within the style guide (_lib, _service mapped to appropriate software
       categories)

   Todo
       Interpret and write configuration style

   Symbols
       Exported   symbols   must  be  prefixed  with  GNUNET_[module_name]_  and  be  defined  in
       [module_name].c. The only exceptions to this rule are symbols defined in gnunet_common.h.

       Private symbols, including structs and macros, must not be prefixed.   In  addition,  they
       must  not  be  exported  in a way that linkers could use them or other libraries might see
       them via headers. This means that they must never be declared  in  src/include,  and  only
       declared or defined in C source files or headers under src/[module_name].

   Tests
       Test    cases    and    performance   tests   should   follow   the   naming   conventions
       test_[module-under-test]_[test_description].c                                          and
       perf_[module-under-test]_[test_description].c, respectively.

       In either case, if there is only a single test, [test_description] may be omitted.

   src subdirectories
       Subdirectories of src

   Coding style
   Todo
       Examples should follow GNU Coding Standards?

       This project follows the GNU Coding Standards.

       Indentation  is  done  with  two  spaces  per  level,  never  with tabs.  Specific (though
       incomplete) indentation rules are defined in an uncrustify configuration file (in contrib)
       and are enforced by Git hooks.

   Todo
       Link to uncrustify config in contrib.

       C99-style struct initialisation is acceptable and generally encouraged.

   Todo
       Clarify whether there are cases where C99-style struct init is discouraged?

       As  in  all good C code, we care about symbol space pollution and thus use static to limit
       the scope where possible, even in the compilation unit that contains main.

       Only one variable should be declared per line:

          // bad
          int i,j;

          // good
          int i;
          int j;

       This helps keep diffs small and forces developers to think precisely  about  the  type  of
       every variable.

       Note  that  char * is different from const char* and int is different from unsigned int or
       uint32_t.  Each variable type should be chosen with care.

   libgnunetutil
       libgnunetutil is the fundamental library that all GNUnet code builds upon.  Ideally,  this
       library should contain most of the platform dependent code (except for user interfaces and
       really special needs that only few applications have). It is also supposed to offer  basic
       services that most if not all GNUnet binaries require. The code of libgnunetutil is in the
       src/util/ directory. The public interface to the library is in the gnunet_util.h header.

       The functions provided by libgnunetutil fall roughly into  the  following  categories  (in
       roughly the order of importance for new developers):

       • logging (common_logging.c)

       • memory allocation (common_allocation.c)

       • endianness conversion (common_endian.c)

       • internationalization (common_gettext.c)

       • String manipulation (string.c)

       • file access (disk.c)

       • buffered disk IO (bio.c)

       • time manipulation (time.c)

       • configuration parsing (configuration.c)

       • command-line handling (getopt*.c)

       • cryptography (crypto_*.c)

       • data structures (container_*.c)

       • CPS-style scheduling (scheduler.c)

       • Program initialization (program.c)

       • Networking (network.c, client.c, server*.c, service.c)

       • message queuing (mq.c)

       • bandwidth calculations (bandwidth.c)

       • Other OS-related (os*.c, plugin.c, signal.c)

       • Pseudonym management (pseudonym.c)

       It should be noted that only developers that fully understand this entire API will be able
       to write good GNUnet code.

       Ideally, porting GNUnet should only require porting the gnunetutil library. More testcases
       for the gnunetutil APIs are therefore a great way to make porting of GNUnet easier.

   System Architecture
   Todo
       FIXME:  For those irritated by the textflow, we are missing images here, in the short term
       we should add them back, in the long term this should work without images or  have  images
       with alt-text.

   Todo
       Adjust image sizes so that they are less obtrusive.

       GNUnet  developers  like  LEGOs. The blocks are indestructible, can be stacked together to
       construct complex buildings and it is generally easy to swap one block for a different one
       that has the same shape. GNUnet’s architecture is based on LEGOs:

       [image: service_lego_block] [image]

       This chapter documents the GNUnet LEGO system, also known as GNUnet’s system architecture.

       The  most  common  GNUnet  component  is  a  service.  Services  offer an API (or several,
       depending on what you count as "an API") which is implemented as a  library.  The  library
       communicates  with  the  main  process  of  the  service  using a service-specific network
       protocol. The main process of the service typically doesn’t fully provide everything  that
       is needed — it has holes to be filled by APIs to other services.

       A  special  kind  of  component in GNUnet are user interfaces and daemons.  Like services,
       they have holes to be filled by APIs of other services.  Unlike services, daemons  do  not
       implement their own network protocol and they have no API:

       [image: daemon_lego_block] [image]

       The  GNUnet  system  provides  a range of services, daemons and user interfaces, which are
       then combined into a layered GNUnet instance (also known as a peer).

       [image: service_stack] [image]

       Note that while it is generally possible  to  swap  one  service  for  another  compatible
       service, there is often only one implementation. However, during development we often have
       a "new" version of a service in parallel with an "old" version. While the "new" version is
       not  working,  developers  working  on  other  parts  of  the  service  can continue their
       development by simply using the "old" service. Alternative design ideas can also be easily
       investigated  by  swapping out individual components. This is typically achieved by simply
       changing the name of the "BINARY" in the respective configuration section.

       Key properties of GNUnet services are that they must be separate processes and  that  they
       must protect themselves by applying tight error checking against the network protocol they
       implement (thereby achieving a certain degree of robustness).

       On the other hand, the APIs are implemented to tolerate failures of the service, isolating
       their  host  process  from  errors  by  the service. If the service process crashes, other
       services and daemons around it should not also fail, but  instead  wait  for  the  service
       process to be restarted by ARM.

   Todo
       Missing subsystems:

              • TOPOLOGY, FRAGMENTATION

              • VPN and support services (DNS, PT, EXIT)

              • DATASTORE (only used by FS?)

              • MULTICAST and social services (PSYC, PSYCSTORE, SOCIAL)

              • GNS support services/applications (GNSRECORD, ZONEMASTER)

              • Set-based applications (SCALARPRODUCT, SECRETSHARING, CONSENSUS, VOTING)

   Internal dependencies
   Todo
       Break out into per-process information?

       This  section  tries to give an overview of what processes a typical GNUnet peer running a
       particular application would consist of. All  of  the  processes  listed  here  should  be
       automatically  started by gnunet-arm -s. The list is given as a rough first guide to users
       for failure diagnostics. Ideally,  end-users  should  never  have  to  worry  about  these
       internal dependencies.

       In terms of internal dependencies, a minimum file-sharing system consists of the following
       GNUnet processes (in order of dependency):

       • gnunet-service-arm

       • gnunet-service-resolver (required by all)

       • gnunet-service-statistics (required by all)

       • gnunet-service-peerinfo

       • gnunet-service-transport (requires peerinfo)

       • gnunet-service-core (requires transport)

       • gnunet-daemon-hostlist (requires core)

       • gnunet-daemon-topology (requires hostlist, peerinfo)

       • gnunet-service-datastore

       • gnunet-service-dht (requires core)

       • gnunet-service-identity

       • gnunet-service-fs (requires identity, mesh, dht, datastore, core)

       A minimum VPN system consists of the following GNUnet processes (in order of dependency):

       • gnunet-service-arm

       • gnunet-service-resolver (required by all)

       • gnunet-service-statistics (required by all)

       • gnunet-service-peerinfo

       • gnunet-service-transport (requires peerinfo)

       • gnunet-service-core (requires transport)

       • gnunet-daemon-hostlist (requires core)

       • gnunet-service-dht (requires core)

       • gnunet-service-mesh (requires dht, core)

       • gnunet-service-dns (requires dht)

       • gnunet-service-regex (requires dht)

       • gnunet-service-vpn (requires regex, dns, mesh, dht)

       A minimum GNS system consists of the following GNUnet processes (in order of dependency):

       • gnunet-service-arm

       • gnunet-service-resolver (required by all)

       • gnunet-service-statistics (required by all)

       • gnunet-service-peerinfo

       • gnunet-service-transport (requires peerinfo)

       • gnunet-service-core (requires transport)

       • gnunet-daemon-hostlist (requires core)

       • gnunet-service-dht (requires core)

       • gnunet-service-mesh (requires dht, core)

       • gnunet-service-dns (requires dht)

       • gnunet-service-regex (requires dht)

       • gnunet-service-vpn (requires regex, dns, mesh, dht)

       • gnunet-service-identity

       • gnunet-service-namestore (requires identity)

       • gnunet-service-gns (requires vpn, dns, dht, namestore, identity)

   Subsystem stability
       This page documents the current stability of the various GNUnet subsystems. Stability here
       describes the expected degree of compatibility with future versions of GNUnet.

       For  each  subsystem  we  distinguish  between  compatibility  on  the  P2P  network level
       (communication protocol between peers), the IPC level (communication between  the  service
       and the service library) and the API level (stability of the API).

       P2P  compatibility  is relevant in terms of which applications are likely going to be able
       to communicate with future versions of the network.  IPC communication is relevant for the
       implementation  of  language  bindings  that  re-implement  the IPC messages. Finally, API
       compatibility is relevant to  developers  that  hope  to  be  able  to  avoid  changes  to
       applications built on top of the APIs of the framework.

       The  following  table  summarizes  our  current  view  of  the stability of the respective
       protocols or APIs:

   Todo
       Make table automatically generated individual pages?

                      ┌──────────────┬──────────────┬──────────────┬──────────────┐
                      │Subsystem     │ P2P          │ IPC          │ C API        │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │util          │ n/a          │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │arm           │ n/a          │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │ats           │ n/a          │ unstable     │ testing      │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │block         │ n/a          │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │cadet         │ testing      │ testing      │ testing      │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │consensus     │ experimental │ experimental │ experimental │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │core          │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │datacache     │ n/a          │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │datastore     │ n/a          │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │dht           │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │dns           │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │dv            │ testing      │ testing      │ n/a          │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │exit          │ testing      │ n/a          │ n/a          │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │fragmentation │ stable       │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │fs            │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │gns           │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │hello         │ n/a          │ n/a          │ testing      │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │hostlist      │ stable       │ stable       │ n/a          │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │identity      │ stable       │ stable       │ n/a          │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │multicast     │ experimental │ experimental │ experimental │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │mysql         │ stable       │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │namestore     │ n/a          │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │nat           │ n/a          │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │nse           │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │peerinfo      │ n/a          │ stable       │ stable       │
                      └──────────────┴──────────────┴──────────────┴──────────────┘

                      │psyc          │ experimental │ experimental │ experimental │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │pt            │ n/a          │ n/a          │ n/a          │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │regex         │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │revocation    │ stable       │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │social        │ experimental │ experimental │ experimental │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │statistics    │ n/a          │ stable       │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │testbed       │ n/a          │ testing      │ testing      │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │testing       │ n/a          │ n/a          │ testing      │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │topology      │ n/a          │ n/a          │ n/a          │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │transport     │ experimental │ experimental │ experimental │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │tun           │ n/a          │ n/a          │ stable       │
                      ├──────────────┼──────────────┼──────────────┼──────────────┤
                      │vpn           │ testing      │ n/a          │ n/a          │
                      └──────────────┴──────────────┴──────────────┴──────────────┘

       Here is a rough explanation of the values:

   Todo
       0.10.x is outdated - rewrite “stable” to reflect a time-independent meaning.

       ‘stable‘
              No incompatible changes are planned at  this  time;  for  IPC/APIs,  if  there  are
              incompatible  changes, they will be minor and might only require minimal changes to
              existing code; for P2P, changes  will  be  avoided  if  at  all  possible  for  the
              0.10.x-series

       ‘testing‘
              No incompatible changes are planned at this time, but the code is still known to be
              in flux; so while we have no concrete plans, our expectation  is  that  there  will
              still  be  minor  modifications;  for  P2P,  changes will likely be extensions that
              should not break existing code

       ‘unstable‘
              Changes are planned and will happen; however, they will not be totally radical  and
              the  result  should  still  resemble  what  is there now; nevertheless, anticipated
              changes will break protocol/API compatibility

       ‘experimental‘
              Changes are planned and the result may look  nothing  like  what  the  API/protocol
              looks like today

       ‘unknown‘
              Someone should think about where this subsystem headed

       ‘n/a‘  This subsystem does not implement a corresponding API/protocol

   Basic Services
       These services comprise a backbone of core services for peer-to-peer applications to use.

   STATISTICS  Runtime statistics publication
       In  GNUnet,  the STATISTICS subsystem offers a central place for all subsystems to publish
       unsigned 64-bit integer run-time statistics.  Keeping  this  information  centrally  means
       that  there is a unified way for the user to obtain data on all subsystems, and individual
       subsystems do not have to always include a  custom  data  export  method  for  performance
       metrics  and other statistics. For example, the TRANSPORT system uses STATISTICS to update
       information about the number of directly connected peers and the bandwidth that  has  been
       consumed by the various plugins.  This information is valuable for diagnosing connectivity
       and performance issues.

       Following the GNUnet service architecture, the STATISTICS subsystem is divided into an API
       which is exposed through the header gnunet_statistics_service.h and the STATISTICS service
       gnunet-service-statistics. The gnunet-statistics command-line tool can be used  to  obtain
       (and change) information about the values stored by the STATISTICS service. The STATISTICS
       service does not communicate with other peers.

       Data is stored in the STATISTICS service in the form of tuples  (subsystem,  name,  value,
       persistence). The subsystem determines to which other GNUnet’s subsystem the data belongs.
       name is the name through which value is associated. It uniquely identifies the record from
       among  other  records belonging to the same subsystem. In some parts of the code, the pair
       (subsystem, name) is called a  statistic  as  it  identifies  the  values  stored  in  the
       STATISTCS service.The persistence flag determines if the record has to be preserved across
       service restarts. A record is said to be persistent if this flag is set for  it;  if  not,
       the  record  is  treated  as a non-persistent record and it is lost after service restart.
       Persistent records are written to and read from the file statistics.data  before  shutdown
       and upon startup. The file is located in the HOME directory of the peer.

       An  anomaly  of  the  STATISTICS  service  is  that it does not terminate immediately upon
       receiving a shutdown signal if it has any clients connected to it. It waits  for  all  the
       clients  that  are not monitors to close their connections before terminating itself. This
       is to prevent the loss of data during peer shutdown  —  delaying  the  STATISTICS  service
       shutdown helps other services to store important data to STATISTICS during shutdown.

   libgnunetstatistics
       libgnunetstatistics  is  the  library containing the API for the STATISTICS subsystem. Any
       process requiring to use STATISTICS should use this API by to open  a  connection  to  the
       STATISTICS  service. This is done by calling the function GNUNET_STATISTICS_create(). This
       function takes the subsystem’s name which is trying to use STATISTICS and a configuration.
       All  values  written  to  STATISTICS  with  this  connection will be placed in the section
       corresponding to the given subsystem’s name. The connection to STATISTICS can be destroyed
       with  the function GNUNET_STATISTICS_destroy(). This function allows for the connection to
       be destroyed immediately or upon transferring all pending write requests to the service.

       Note: STATISTICS subsystem can be disabled by setting DISABLE = YES under the [STATISTICS]
       section    in    the   configuration.   With   such   a   configuration   all   calls   to
       GNUNET_STATISTICS_create() return NULL as the STATISTICS subsystem is unavailable  and  no
       other functions from the API can be used.

   Statistics retrieval
       Once  a  connection  to  the  statistics  service is obtained, information about any other
       system which uses statistics can be retrieved with the  function  GNUNET_STATISTICS_get().
       This  function takes the connection handle, the name of the subsystem whose information we
       are interested in (a NULL value will retrieve  information  of  all  available  subsystems
       using  STATISTICS),  the  name  of  the  statistic we are interested in (a NULL value will
       retrieve all available statistics), a continuation callback which is called  when  all  of
       requested  information  is  retrieved,  an  iterator  callback  which  is  called for each
       parameter in the retrieved information and a closure for the aforementioned callbacks. The
       library then invokes the iterator callback for each value matching the request.

       Call  to  GNUNET_STATISTICS_get()  is  asynchronous  and can be canceled with the function
       GNUNET_STATISTICS_get_cancel(). This is helpful when retrieving statistics takes too  long
       and especially when we want to shutdown and cleanup everything.

   Setting statistics and updating them
       So  far  we  have  seen  how  to  retrieve  statistics,  here we will learn how we can set
       statistics and update them so that other subsystems can retrieve them.

       A new statistic can be set using the function GNUNET_STATISTICS_set(). This function takes
       the  name  of the statistic and its value and a flag to make the statistic persistent. The
       value of the statistic should be of the type uint64_t. The function does not take the name
       of   the   subsystem;  it  is  determined  from  the  previous  GNUNET_STATISTICS_create()
       invocation. If the given statistic is already present, its value is overwritten.

       An existing statistics can be updated, i.e its value can be increased or decreased  by  an
       amount  with the function GNUNET_STATISTICS_update().  The parameters to this function are
       similar to GNUNET_STATISTICS_set(), except that it takes the amount to  be  changed  as  a
       type int64_t instead of the value.

       The  library will combine multiple set or update operations into one message if the client
       performs requests at a rate that is faster than the  available  IPC  with  the  STATISTICS
       service. Thus, the client does not have to worry about sending requests too quickly.

   Watches
       As interesting feature of STATISTICS lies in serving notifications whenever a statistic of
       our interest is modified. This is achieved by registering a  watch  through  the  function
       GNUNET_STATISTICS_watch().   The  parameters  of  this  function  are  similar to those of
       GNUNET_STATISTICS_get(). Changes to the respective statistic’s value will then  cause  the
       given  iterator callback to be called. Note: A watch can only be registered for a specific
       statistic. Hence the subsystem name and the parameter name cannot be NULL  in  a  call  to
       GNUNET_STATISTICS_watch().

       A     registered    watch    will    keep    notifying    any    value    changes    until
       GNUNET_STATISTICS_watch_cancel() is called with the same  parameters  that  are  used  for
       registering the watch.

   The STATISTICS Client-Service Protocol
   Statistics retrieval
       To     retrieve    statistics,    the    client    transmits    a    message    of    type
       GNUNET_MESSAGE_TYPE_STATISTICS_GET containing  the  given  subsystem  name  and  statistic
       parameter  to  the  STATISTICS  service.  The  service  responds  with  a  message of type
       GNUNET_MESSAGE_TYPE_STATISTICS_VALUE for each of the statistics parameters that match  the
       client request for the client. The end of information retrieved is signaled by the service
       by sending a message of type GNUNET_MESSAGE_TYPE_STATISTICS_END.

   Setting and updating statistics
       The subsystem name, parameter name, its value and the persistence flag are communicated to
       the service through the message GNUNET_MESSAGE_TYPE_STATISTICS_SET.

       When  the  service  receives  a  message  of  type  GNUNET_MESSAGE_TYPE_STATISTICS_SET, it
       retrieves the subsystem name and checks for a statistic parameter with matching  the  name
       given  in  the message. If a statistic parameter is found, the value is overwritten by the
       new value from the message; if not found then a new statistic parameter  is  created  with
       the given name and value.

       In addition to just setting an absolute value, it is possible to perform a relative update
       by sending a message  of  type  GNUNET_MESSAGE_TYPE_STATISTICS_SET  with  an  update  flag
       (GNUNET_STATISTICS_SETFLAG_RELATIVE)  signifying  that  the value in the message should be
       treated as an update value.

   Watching for updates
       The  function  registers  the  watch  at  the  service  by  sending  a  message  of   type
       GNUNET_MESSAGE_TYPE_STATISTICS_WATCH.   The   service  then  sends  notifications  through
       messages  of  type  GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE  whenever   the   statistic
       parameter’s value is changed.

   ATS  Automatic transport selection
       ATS  stands  for  "automatic transport selection", and the function of ATS in GNUnet is to
       decide on which address (and thus transport plugin)  should  be  used  for  two  peers  to
       communicate, and what bandwidth limits should be imposed on such an individual connection.

       To  help ATS make an informed decision, higher-level services inform the ATS service about
       their requirements and the quality of the service rendered. The ATS service also interacts
       with  the  transport  service  to be appraised of working addresses and to communicate its
       resource allocation decisions. Finally, the ATS service’s operation can be observed  using
       a monitoring API.

       The main logic of the ATS service only collects the available addresses, their performance
       characteristics and the applications requirements, but does not make the actual allocation
       decision.  This  last  critical  step  is  left  to  an ATS plugin, as we have implemented
       (currently three) different allocation strategies  which  differ  significantly  in  their
       performance  and  maturity,  and it is still unclear if any particular plugin is generally
       superior.

   TRANSPORT  Overlay transport management
       This chapter documents how the GNUnet transport  subsystem  works.  The  GNUnet  transport
       subsystem  consists of three main components: the transport API (the interface used by the
       rest of the system to access the transport service), the transport service itself (most of
       the  interesting  functions,  such as choosing transports, happens here) and the transport
       plugins. A transport plugin  is  a  concrete  implementation  for  how  two  GNUnet  peers
       communicate;  many  plugins exist, for example for communication via TCP, UDP, HTTP, HTTPS
       and others. Finally, the transport subsystem uses supporting code, especially the NAT/UPnP
       library to help with tasks such as NAT traversal.

       Key tasks of the transport service include:

       • Create  our HELLO message, notify clients and neighbours if our HELLO changes (using NAT
         library as necessary)

       • Validate HELLOs from other peers (send PING), allow other peers to validate our  HELLO’s
         addresses (send PONG)

       • Upon  request,  establish  connections  to other peers (using address selection from ATS
         subsystem) and maintain them (again using PINGs and PONGs) as long as desired

       • Accept incoming connections, give ATS service the opportunity  to  switch  communication
         channels

       • Notify clients about peers that have connected to us or that have been disconnected from
         us

       • If a (stateful) connection goes down unexpectedly (without explicit DISCONNECT), quickly
         attempt  to  recover  (without  notifying  clients)  but  do  notify  clients quickly if
         reconnecting fails

       • Send (payload) messages arriving from clients to other peers via transport  plugins  and
         receive messages from other peers, forwarding those to clients

       • Enforce  inbound  traffic  limits  (using  flow-control  if  it is applicable); outbound
         traffic limits are enforced by CORE, not by us (!)

       • Enforce restrictions on P2P connection as specified by the blacklist  configuration  and
         blacklisting clients

       Note  that  the term "clients" in the list above really refers to the GNUnet-CORE service,
       as CORE is typically the only client of the transport service.

   Address validation protocol
       This section documents how the GNUnet transport service validates connections  with  other
       peers.  It is a high-level description of the protocol necessary to understand the details
       of the implementation. It should be noted that when we talk about PING and  PONG  messages
       in  this  section, we refer to transport-level PING and PONG messages, which are different
       from core-level PING and PONG messages (both in implementation and function).

       The goal of transport-level address validation is to minimize the chances of a  successful
       man-in-the-middle attack against GNUnet peers on the transport level. Such an attack would
       not allow the adversary to decrypt the P2P transmissions, but a successful attacker  could
       at  least  measure  traffic volumes and latencies (raising the adversaries capabilities by
       those of a global passive adversary in the worst case).  The scenarios  we  are  concerned
       about  is  an  attacker,  Mallory,  giving a HELLO to Alice that claims to be for Bob, but
       contains Mallory’s IP address instead of Bobs (for some  transport).  Mallory  would  then
       forward  the  traffic to Bob (by initiating a connection to Bob and claiming to be Alice).
       As a further complication, the scheme has to work even  if  say  Alice  is  behind  a  NAT
       without  traversal support and hence has no address of her own (and thus Alice must always
       initiate the connection to Bob).

       An additional constraint is that HELLO messages do not contain a  cryptographic  signature
       since other peers must be able to edit (i.e.  remove) addresses from the HELLO at any time
       (this was not true in GNUnet 0.8.x). A basic assumption is that each peer knows the set of
       possible  network addresses that it might be reachable under (so for example, the external
       IP address of the NAT plus the LAN address(es) with the respective ports).

       The solution is the following. If Alice wants to validate that a given address for Bob  is
       valid  (i.e.  is actually established directly with the intended target), she sends a PING
       message over that connection  to  Bob.  Note  that  in  this  case,  Alice  initiated  the
       connection  so  only Alice knows which address was used for sure (Alice may be behind NAT,
       so whatever address Bob sees may not be an address Alice knows she has).  Bob checks  that
       the  address  given in the PING is actually one of Bob’s addresses (ie: does not belong to
       Mallory), and if it is, sends back a PONG (with a signature that says that  Bob  owns/uses
       the address from the PING). Alice checks the signature and is happy if it is valid and the
       address in the PONG is the address Alice used.  This is  similar  to  the  0.8.x  protocol
       where  the  HELLO  contained  a signature from Bob for each address used by Bob. Here, the
       purpose code for  the  signature  is  GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN.   After
       this, Alice will remember Bob’s address and consider the address valid for a while (12h in
       the current implementation). Note that after this exchange,  Alice  only  considers  Bob’s
       address to be valid, the connection itself is not considered ‘established’. In particular,
       Alice may have many addresses for Bob that Alice considers valid.

       The PONG message is protected with a nonce/challenge against replay attacks  (replay)  and
       uses an expiration time for the signature (but those are almost implementation details).

       NAT library .. _NAT-library:

   NAT library
       The  goal  of the GNUnet NAT library is to provide a general-purpose API for NAT traversal
       without third-party support. So protocols that involve contacting a  third  peer  to  help
       establish  a  connection between two peers are outside of the scope of this API. That does
       not mean that GNUnet doesn’t support involving a third peer  (we  can  do  this  with  the
       distance-vector  transport  or  using application-level protocols), it just means that the
       NAT API is not concerned with this possibility. The API is written so that  it  will  work
       for IPv6-NAT in the future as well as current IPv4-NAT. Furthermore, the NAT API is always
       used, even for peers that are not behind NAT — in  that  case,  the  mapping  provided  is
       simply the identity.

       NAT  traversal  is initiated by calling GNUNET_NAT_register. Given a set of addresses that
       the peer has locally bound to (TCP or UDP), the NAT library will return (via  callback)  a
       (possibly  longer)  list  of  addresses  the  peer  might  be reachable under. Internally,
       depending on the configuration, the NAT library will try to punch a hole (using  UPnP)  or
       just  "know"  that  the  NAT  was manually punched and generate the respective external IP
       address (the one that should be globally visible) based on the given information.

       The NAT library also supports ICMP-based NAT traversal. Here, the other peer  can  request
       connection-reversal  by  this  peer  (in  this  special  case, the peer is even allowed to
       configure a port number of  zero).  If  the  NAT  library  detects  a  connection-reversal
       request,  it  returns  the  respective  target address to the client as well. It should be
       noted that connection-reversal is currently only intended for TCP, so other  plugins  must
       pass  NULL  for the reversal callback. Naturally, the NAT library also supports requesting
       connection reversal from a remote peer (GNUNET_NAT_run_client).

       Once initialized, the NAT handle can be used to test if a  given  address  is  possibly  a
       valid  address  for  this peer (GNUNET_NAT_test_address).  This is used for validating our
       addresses when generating PONGs.

       Finally, the NAT library contains an API to test if  our  NAT  configuration  is  correct.
       Using  GNUNET_NAT_test_start before binding to the respective port, the NAT library can be
       used to test if the configuration  works.  The  test  function  act  as  a  local  client,
       initialize  the  NAT traversal and then contact a gnunet-nat-server (running by default on
       gnunet.org) and ask for a connection to be established. This way, it is easy  to  test  if
       the current NAT configuration is valid.

   Distance-Vector plugin
       The  Distance  Vector  (DV) transport is a transport mechanism that allows peers to act as
       relays for each other, thereby connecting peers that would otherwise be unable to connect.
       This gives a larger connection set to applications that may work better with more peers to
       choose from (for example, File Sharing and/or DHT).

       The Distance Vector transport essentially has two  functions.  The  first  is  "gossiping"
       connection information about more distant peers to directly connected peers. The second is
       taking messages intended for non-directly connected peers and encapsulating them in  a  DV
       wrapper  that contains the required information for routing the message through forwarding
       peers. Via gossiping, optimal routes through the known DV neighborhood are discovered  and
       utilized  and  the  message  encapsulation  provides  some  benefits in addition to simply
       getting the message from the correct source to the proper destination.

       The gossiping function of DV provides an up to  date  routing  table  of  peers  that  are
       available  up  to  some number of hops. We call this a fisheye view of the network (like a
       fish, nearby objects are known while more distant ones unknown). Gossip messages are  sent
       only  to  directly  connected peers, but they are sent about other knowns peers within the
       "fisheye distance". Whenever two peers connect, they  immediately  gossip  to  each  other
       about  their  appropriate other neighbors. They also gossip about the newly connected peer
       to previously connected neighbors.  In order to  keep  the  routing  tables  up  to  date,
       disconnect  notifications are propagated as gossip as well (because disconnects may not be
       sent/received, timeouts are also used remove stagnant routing table entries).

       Routing of messages via DV is straightforward. When the DV  transport  is  notified  of  a
       message  destined  for a non-direct neighbor, the appropriate forwarding peer is selected,
       and the base message is encapsulated in a DV message which contains information about  the
       initial  peer  and  the  intended  recipient.  At each forwarding hop, the initial peer is
       validated (the forwarding peer ensures that it has the initial peer in  its  neighborhood,
       otherwise  the  message is dropped).  Next the base message is re-encapsulated in a new DV
       message for the next hop in the forwarding chain (or delivered to the current peer, if  it
       has arrived at the destination).

       Assume a three peer network with peers Alice, Bob and Carol. Assume that

          Alice <-> Bob and Bob <-> Carol

       are  direct  (e.g. over TCP or UDP transports) connections, but that Alice cannot directly
       connect to Carol. This may be the case due to NAT or  firewall  restrictions,  or  perhaps
       based  on  one of the peers respective configurations. If the Distance Vector transport is
       enabled on all three peers, it will automatically discover (from the gossip protocol) that
       Alice  and  Carol  can connect via Bob and provide a "virtual" Alice <-> Carol connection.
       Routing between Alice and Carol happens as follows; Alice creates a message  destined  for
       Carol  and notifies the DV transport about it. The DV transport at Alice looks up Carol in
       the routing table and finds that the message must be  sent  through  Bob  for  Carol.  The
       message  is  encapsulated  setting Alice as the initiator and Carol as the destination and
       sent to Bob. Bob receives the messages, verifies that both Alice and Carol  are  known  to
       Bob,  and  re-wraps  the  message in a new DV message for Carol. The DV transport at Carol
       receives this message, unwraps the original message, and delivers it to Carol as though it
       came directly from Alice.

       SMTP plugin .. _SMTP-plugin:

   SMTP plugin
   Todo
       Update?

       This  section describes the new SMTP transport plugin for GNUnet as it exists in the 0.7.x
       and 0.8.x branch. SMTP support is currently not available in GNUnet 0.9.x. This page  also
       describes  the  transport  layer  abstraction  (as  it existed in 0.7.x and 0.8.x) in more
       detail and gives some benchmarking results. The performance results  presented  are  quite
       old and maybe outdated at this point. For the readers in the year 2019, you will notice by
       the mention of version 0.7, 0.8, and 0.9 that this section has to be taken with your usual
       grain of salt and be updated eventually.

       • Why use SMTP for a peer-to-peer transport?

       • SMTPHow does it work?

       • How do I configure my peer?

       • How do I test if it works?

       • How fast is it?

       • Is there any additional documentation?

   Why use SMTP for a peer-to-peer transport?
       There are many reasons why one would not want to use SMTP:

       • SMTP is using more bandwidth than TCP, UDP or HTTP

       • SMTP has a much higher latency.

       • SMTP requires significantly more computation (encoding and decoding time) for the peers.

       • SMTP is significantly more complicated to configure.

       • SMTP  may  be  abused  by  tricking  GNUnet into sending mail to non-participating third
         parties.

       So why would anybody want to use SMTP?

       • SMTP can be used to contact peers behind NAT boxes (in virtual private networks).

       • SMTP can be used to circumvent policies that limit or prohibit peer-to-peer  traffic  by
         masking as "legitimate" traffic.

       • SMTP  uses  E-mail addresses which are independent of a specific IP, which can be useful
         to address peers that use dynamic IP addresses.

       • SMTP can be used to initiate a connection (e.g. initial address exchange) and peers  can
         then  negotiate  the  use  of  a  more  efficient  protocol  (e.g.  TCP)  for the actual
         communication.

       In summary, SMTP can for example be used to send a message to a peer behind a NAT box that
       has  a  dynamic IP to tell the peer to establish a TCP connection to a peer outside of the
       private network. Even an extraordinary overhead for this first message would be irrelevant
       in this type of situation.

   How does it work?
       When  a  GNUnet  peer  needs  to send a message to another GNUnet peer that has advertised
       (only) an SMTP transport address, GNUnet base64-encodes the message and  sends  it  in  an
       E-mail  to  the advertised address. The advertisement contains a filter which is placed in
       the E-mail header, such that the receiving host can filter the tagged E-mails and  forward
       it  to  the GNUnet peer process. The filter can be specified individually by each peer and
       be changed over time. This makes  it  impossible  to  censor  GNUnet  E-mail  messages  by
       searching for a generic filter.

   How do I configure my peer?
       First,  you  need  to configure procmail to filter your inbound E-mail for GNUnet traffic.
       The GNUnet messages must be delivered into a pipe, for example /tmp/gnunet.smtp. You  also
       need  to  define a filter that is used by procmail to detect GNUnet messages. You are free
       to choose whichever filter you like, but you should make sure that it does  not  occur  in
       your  other  E-mail.  In  our  example,  we  will  use X-mailer: GNUnet. The ~/.procmailrc
       configuration file then looks like this:

          :0:
          * ^X-mailer: GNUnet
          /tmp/gnunet.smtp
          # where do you want your other e-mail delivered to
          # (default: /var/spool/mail/)
          :0: /var/spool/mail/

       After adding this file, first make sure that your regular  E-mail  still  works  (e.g.  by
       sending  an  E-mail  to yourself). Then edit the GNUnet configuration. In the section SMTP
       you need to specify your E-mail address under EMAIL, your mail server (for outgoing  mail)
       under  SERVER,  the  filter (X-mailer: GNUnet in the example) under FILTER and the name of
       the pipe under PIPE. The completed section could then look like this:

          EMAIL = me@mail.gnu.org MTU = 65000 SERVER = mail.gnu.org:25 FILTER =
          "X-mailer: GNUnet" PIPE = /tmp/gnunet.smtp

   Todo
       set highlighting for this code block properly.

       Finally, you need to add smtp to the list of TRANSPORTS in  the  GNUNETD  section.  GNUnet
       peers  will  use  the  E-mail  address  that  you specified to contact your peer until the
       advertisement times out. Thus, if you are not sure if everything works properly or if  you
       are  not  planning to be online for a long time, you may want to configure this timeout to
       be short, e.g. just one hour. For this, set HELLOEXPIRES to 1 in the GNUNETD section.

       This should be it, but you may probably want to test it first.

   How do I test if it works?
       Any transport can be subjected to some rudimentary tests using the  gnunet-transport-check
       tool. The tool sends a message to the local node via the transport and checks that a valid
       message is received.  While this test does not involve other peers and can  not  check  if
       firewalls  or  other network obstacles prohibit proper operation, this is a great testcase
       for the SMTP transport since it tests pretty much nearly all of the functionality.

       gnunet-transport-check should only be used without running gnunetd at the  same  time.  By
       default,   gnunet-transport-check   tests   all  transports  that  are  specified  in  the
       configuration  file.  But  you  can  specifically  test  SMTP   by   giving   the   option
       --transport=smtp.

       Note  that  this  test  always  checks if a transport can receive and send.  While you can
       configure most transports to only receive or only send messages, this test will only  work
       if you have configured the transport to send and receive messages.

   How fast is it?
       We  have  measured  the  performance of the UDP, TCP and SMTP transport layer directly and
       when used from an application using the GNUnet core.  Measuring just the  transport  layer
       gives  the  better  view  of  the  actual overhead of the protocol, whereas evaluating the
       transport from the application puts the overhead into perspective from a  practical  point
       of view.

       The loopback measurements of the SMTP transport were performed on three different machines
       spanning a range of modern SMTP configurations. We used a PIII-800 running RedHat 7.3 with
       the  Purdue Computer Science configuration which includes filters for spam. We also used a
       Xenon 2 GHZ with a vanilla RedHat 8.0 sendmail configuration. Furthermore, we  used  qmail
       on  a PIII-1000 running Sorcerer GNU Linux (SGL). The numbers for UDP and TCP are provided
       using the SGL configuration. The qmail benchmark uses qmail’s internal  filtering  whereas
       the  sendmail  benchmarks  relies  on procmail to filter and deliver the mail. We used the
       transport layer to send a message  of  b  bytes  (excluding  transport  protocol  headers)
       directly  to the local machine. This way, network latency and packet loss on the wire have
       no impact on the timings. n messages were sent  sequentially  over  the  transport  layer,
       sending  message  i+1 after the i-th message was received. All messages were sent over the
       same connection and the time to establish the connection was not taken into account  since
       this overhead is minuscule in practice — as long as a connection is used for a significant
       number of messages.

            ┌────────────┬───────┬───────┬────────────────┬───────────────┬────────────────┐
            │Transport   │ UDP   │ TCP   │ SMTP (Purdue s │ SMTP (RH 8.0) │ SMTP      (SGL │
            │            │       │       │ endmail)       │               │ qmail)         │
            ├────────────┼───────┼───────┼────────────────┼───────────────┼────────────────┤
            │11 bytes    │ 31 ms │ 55 ms │ 781 s          │ 77 s          │ 24 s           │
            ├────────────┼───────┼───────┼────────────────┼───────────────┼────────────────┤
            │407 bytes   │ 37 ms │ 62 ms │ 789 s          │ 78 s          │ 25 s           │
            ├────────────┼───────┼───────┼────────────────┼───────────────┼────────────────┤
            │1,221 bytes │ 46 ms │ 73 ms │ 804 s          │ 78 s          │ 25 s           │
            └────────────┴───────┴───────┴────────────────┴───────────────┴────────────────┘

       The benchmarks show that UDP and TCP are, as expected, both significantly faster  compared
       with  any  of  the SMTP services. Among the SMTP implementations, there can be significant
       differences depending on the SMTP configuration. Filtering  with  an  external  tool  like
       procmail  that  needs  to  re-parse its configuration for each mail can be very expensive.
       Applying spam filters can also significantly impact the performance of the underlying SMTP
       implementation. The microbenchmark shows that SMTP can be a viable solution for initiating
       peer-to-peer sessions: a couple of seconds to connect to a  peer  are  probably  not  even
       going  to  be  noticed by users. The next benchmark measures the possible throughput for a
       transport. Throughput can be  measured  by  sending  multiple  messages  in  parallel  and
       measuring  packet  loss.  Note  that  not only UDP but also the TCP transport can actually
       loose messages since the TCP implementation drops messages if  the  write  to  the  socket
       would block. While the SMTP protocol never drops messages itself, it is often so slow that
       only a fraction of the messages can be sent and received in  the  given  time-bounds.  For
       this benchmark we report the message loss after allowing t time for sending m messages. If
       messages were not sent (or received) after an overall timeout of t, they  were  considered
       lost.  The  benchmark  was performed using two Xeon 2 GHZ machines running RedHat 8.0 with
       sendmail. The machines were connected with a direct 100 MBit Ethernet  connection. Figures
       udp1200,  tcp1200 and smtp-MTUs show that the throughput for messages of size 1,200 octets
       is 2,343 kbps, 3,310 kbps and 6 kbps  for  UDP,  TCP  and  SMTP  respectively.   The  high
       per-message overhead of SMTP can be improved by increasing the MTU, for example, an MTU of
       12,000 octets improves the throughput to 13 kbps as figure smtp-MTUs shows.  Our  research
       paper [Transport2014] has some more details on the benchmarking results.

       Bluetooth plugin .. _Bluetooth-plugin:

   Bluetooth plugin
       This  page describes the new Bluetooth transport plugin for GNUnet. The plugin is still in
       the testing stage so don’t expect it to work perfectly.  If  you  have  any  questions  or
       problems just post them here or ask on the IRC channel.

       • What do I need to use the Bluetooth plugin transport?

       • BluetoothHow does it work?

       • What possible errors should I be aware of?

       • How do I configure my peer?

       • How can I test it?

   What do I need to use the Bluetooth plugin transport?
       If  you are a GNU/Linux user and you want to use the Bluetooth transport plugin you should
       install  the  BlueZ  development  libraries  (if  they  aren’t  already  installed).   For
       instructions  about  how  to  install the libraries you should check out the BlueZ site (‐
       http://www.bluez.org). If you don’t know if you have the necessary libraries, don’t worry,
       just run the GNUnet configure script and you will be able to see a notification at the end
       which will warn you if you don’t have the necessary libraries.

   Todo
       Change to unique title?

   How does it work2?
       The Bluetooth transport plugin uses virtually the same code as the WLAN  plugin  and  only
       the  helper  binary is different. The helper takes a single argument, which represents the
       interface name and is specified in the configuration file. Here are the basic  steps  that
       are followed by the helper binary used on GNU/Linux:

       • it verifies if the name corresponds to a Bluetooth interface name

       • it verifies if the interface is up (if it is not, it tries to bring it up)

       • it  tries  to  enable the page and inquiry scan in order to make the device discoverable
         and to accept incoming connection requests The above operations require root  access  so
         you should start the transport plugin with root privileges.

       • it finds an available port number and registers a SDP service which will be used to find
         out on which port number is the server listening on and switch the socket  in  listening
         mode

       • it sends a HELLO message with its address

       • finally it forwards traffic from the reading sockets to the STDOUT and from the STDIN to
         the writing socket

       Once in a while the device will make an inquiry scan to discover the nearby devices and it
       will send them randomly HELLO messages for peer discovery.

   What possible errors should I be aware of?
       This section is dedicated for GNU/Linux users

       Well  there  are  many  ways in which things could go wrong but I will try to present some
       tools that you could use to debug and some scenarios.

       • bluetoothd -n -d : use this command to enable logging in the foreground and to print the
         logging messages

       • hciconfig:  can  be  used  to configure the Bluetooth devices. If you run it without any
         arguments it will print information about the state of the interfaces. So if you receive
         an  error that the device couldn’t be brought up you should try to bring it manually and
         to see if it works (use hciconfig -a hciX up). If you can’t and  the  Bluetooth  address
         has  the  form  00:00:00:00:00:00  it means that there is something wrong with the D-Bus
         daemon or with the Bluetooth daemon. Use bluetoothd tool to see the logs

       • sdptool can be used to control and interrogate SDP servers. If  you  encounter  problems
         regarding the SDP server (like the SDP server is down) you should check out if the D-Bus
         daemon is running correctly and to see if the  Bluetooth  daemon  started  correctly(use
         bluetoothd  tool).  Also,  sometimes  the  SDP service could work but somehow the device
         couldn’t register its service. Use sdptool browse [dev-address] to see if the service is
         registered.   There  should  be  a  service with the name of the interface and GNUnet as
         provider.

       • hcitool : another useful tool which can be used to configure the device and to send some
         particular commands to it.

       • hcidump : could be used for low level debugging

   Todo
       Fix name/referencing now that we’re using Sphinx.

   How do I configure my peer2?
       On GNU/Linux, you just have to be sure that the interface name corresponds to the one that
       you want to use. Use the hciconfig tool to check that. By default it is set  to  hci0  but
       you can change it.

       A basic configuration looks like this:

          [transport-bluetooth]
          # Name of the interface (typically hciX)
          INTERFACE = hci0
          # Real hardware, no testing
          TESTMODE = 0 TESTING_IGNORE_KEYS = ACCEPT_FROM;

       In  order to use the Bluetooth transport plugin when the transport service is started, you
       must add the plugin name to the default transport service plugins list. For example:

          [transport] ...  PLUGINS = dns bluetooth ...

       If you want to use only the Bluetooth plugin set PLUGINS = bluetooth

       On Windows, you cannot specify which device to use. The only thing that you should  do  is
       to add bluetooth on the plugins list of the transport service.

   How can I test it?
       If  you  have  two  Bluetooth  devices on the same machine and you are using GNU/Linux you
       must:

       • create two different file configuration (one which will use the first  interface  (hci0)
         and  the  other  which will use the second interface (hci1)). Let’s name them peer1.conf
         and peer2.conf.

       • run gnunet-peerinfo -c peerX.conf -s in order to generate the peers private keys. The  X
         must be replace with 1 or 2.

       • run  gnunet-arm  -c  peerX.conf -s -i=transport in order to start the transport service.
         (Make sure that you have "bluetooth" on the transport  plugins  list  if  the  Bluetooth
         transport service doesn’t start.)

       • run  gnunet-peerinfo  -c  peer1.conf  -s to get the first peer’s ID. If you already know
         your peer ID (you saved it from the first command), this can be skipped.

       • run gnunet-transport -c peer2.conf -p=PEER1_ID -s to start sending data for benchmarking
         to the other peer.

       This  scenario will try to connect the second peer to the first one and then start sending
       data for benchmarking.

       If you have two different machines and your configuration files are good you can  use  the
       same scenario presented on the beginning of this section.

       Another  way to test the plugin functionality is to create your own application which will
       use the GNUnet framework with the Bluetooth transport service.

   The implementation of the Bluetooth transport plugin
       This page describes the implementation of the Bluetooth transport plugin.

       First I want to remind you that the Bluetooth transport plugin  uses  virtually  the  same
       code  as  the  WLAN  plugin and only the helper binary is different. Also the scope of the
       helper binary from the Bluetooth transport plugin is the same as the one used for the WLAN
       transport  plugin:  it  accesses  the  interface  and  then  it  forwards  traffic in both
       directions between the Bluetooth interface and stdin/stdout of the process involved.

       The Bluetooth plugin transport could be used both on GNU/Linux and Windows platforms.

       • Linux functionality

       • Pending Features

   Linux functionality
       In order to implement the plugin functionality on GNU/Linux I used the  BlueZ  stack.  For
       the  communication  with the other devices I used the RFCOMM protocol. Also I used the HCI
       protocol to gain some control over the device. The helper binary takes a  single  argument
       (the name of the Bluetooth interface) and is separated in two stages:

   Todo
       ‘THE INITIALIZATION’ should be in bigger letters or stand out, not starting a new section?

   THE INITIALIZATION
       • first,  it  checks  if  we  have  root  privileges  (Remember  that we need to have root
         privileges in order to be able to bring the interface up if it is down or to change  its
         state.).

       • second, it verifies if the interface with the given name exists.

         If the interface with that name exists and it is a Bluetooth interface:

       • it  creates  a  RFCOMM  socket which will be used for listening and call the open_device
         method

         On the open_device method:

         • creates a HCI socket used to send control events to the device

         • searches for the device ID using the interface name

         • saves the device MAC address

         • checks if the interface is down and tries to bring it UP

         • checks if the interface is in discoverable mode and tries to make it discoverable

         • closes the HCI socket and binds the RFCOMM one

         • switches the RFCOMM socket in listening mode

         • registers the SDP service (the service will be used by the other devices  to  get  the
           port on which this device is listening on)

       • drops the root privileges

         If the interface is not a Bluetooth interface the helper exits with a suitable error

   THE LOOP
       The  helper  binary  uses  a  list  where  it  saves  all  the connected neighbour devices
       (neighbours.devices) and two buffers (write_pout and write_std). The first  message  which
       is  send  is a control message with the device’s MAC address in order to announce the peer
       presence to the neighbours. Here are a short description of what happens in the main loop:

       • Every time when it receives something from the STDIN it processes the data and saves the
         message  in  the first buffer (write_pout). When it has something in the buffer, it gets
         the destination address from the buffer, searches the destination address  in  the  list
         (if  there  is  no connection with that device, it creates a new one and saves it to the
         list) and sends the message.

       • Every time when it receives something on the listening socket it accepts the  connection
         and saves the socket on a list with the reading sockets.

       • Every  time  when  it  receives  something  from a reading socket it parses the message,
         verifies the CRC and saves it in the write_std buffer in order to be sent later  to  the
         STDOUT.

       So  in  the  main loop we use the select function to wait until one of the file descriptor
       saved in one of the two file descriptors sets used is ready to use. The first  set  (rfds)
       represents  the  reading  set  and it could contain the list with the reading sockets, the
       STDIN file descriptor or the listening socket. The second set (wfds) is  the  writing  set
       and  it  could  contain the sending socket or the STDOUT file descriptor. After the select
       function returns, we check which file descriptor is  ready  to  use  and  we  do  what  is
       supposed  to  do on that kind of event. For example: if it is the listening socket then we
       accept a new connection and save the socket in the reading list; if it is the STDOUT  file
       descriptor, then we write to STDOUT the message from the write_std buffer.

       To  find out on which port a device is listening on we connect to the local SDP server and
       search the registered service for that device.

       You should be aware of the fact that if the device fails to connect to  another  one  when
       trying  to send a message it will attempt one more time.  If it fails again, then it skips
       the message. Also you  should  know  that  the  transport  Bluetooth  plugin  has  support
       forbroadcast messages.

   Details about the broadcast implementation
       First I want to point out that the broadcast functionality for the CONTROL messages is not
       implemented in a conventional way. Since the inquiry scan time is too big and it will take
       some  time  to  send  a  message  to  all the discoverable devices I decided to tackle the
       problem in a different way. Here is how I did it:

       • If it is the first time when I have to broadcast a message I make an  inquiry  scan  and
         save all the devices’ addresses to a vector.

       • After  the inquiry scan ends I take the first address from the list and I try to connect
         to it. If it fails, I try to connect to the next one. If it succeeds, I save the  socket
         to a list and send the message to the device.

       • When  I  have  to broadcast another message, first I search on the list for a new device
         which I’m not connected to. If there is no new device on the list I go to the  beginning
         of the list and send the message to the old devices. After 5 cycles I make a new inquiry
         scan to check out if there are new discoverable devices and save them to  the  list.  If
         there  are  no new discoverable devices I reset the cycling counter and go again through
         the old list and send messages to the devices saved in it.

       Therefore:

       • every time when I have a broadcast message I look up on the list for a  new  device  and
         send the message to it

       • if  I  reached the end of the list for 5 times and I’m connected to all the devices from
         the list I make a new inquiry scan. The number of the list’s  cycles  after  an  inquiry
         scan could be increased by redefining the MAX_LOOPS variable

       • when there are no new devices I send messages to the old ones.

       Doing so, the broadcast control messages will reach the devices but with delay.

       NOTICE:  When  I have to send a message to a certain device first I check on the broadcast
       list to see if we are connected to that device.  If not we try to connect  to  it  and  in
       case  of  success  we  save  the  address  and  the  socket on the list. If we are already
       connected to that device we simply use the socket.

   Pending features
       • Implement a testcase for the helper : The testcase consists of a program which  emulates
         the  plugin  and  uses the helper. It will simulate connections, disconnections and data
         transfers.

       If you have a new idea about a feature of the plugin or  suggestions  about  how  I  could
       improve the implementation you are welcome to comment or to contact me.

   WLAN plugin
       This  section  documents  how  the  wlan  transport  plugin  works.  Parts  which  are not
       implemented yet or could be better implemented are described at the end.

       [Transport2014]
            https://bib.gnunet.org/date.html#paper_5fshort2014

   TRANSPORT-NG  Next-generation transport management
       The current GNUnet TRANSPORT architecture is rooted in the  GNUnet  0.4  design  of  using
       plugins  for  the  actual transmission operations and the ATS subsystem to select a plugin
       and allocate bandwidth. The following key issues have been identified with this design:

       • Bugs in one plugin can affect the TRANSPORT service and other plugins. There is at least
         one  open bug that affects sockets, where the origin is difficult to pinpoint due to the
         large code base.

       • Relevant operating system default configurations often  impose  a  limit  of  1024  file
         descriptors  per  process.  Thus,  one  plugin  may  impact  other plugin’s connectivity
         choices.

       • Plugins are required to offer bi-directional connectivity. However, firewalls (incl. NAT
         boxes)  and  physical  environments  sometimes  only allow uni-directional connectivity,
         which then currently cannot be utilized at all.

       • Distance vector routing was implemented in 209 but shortly afterwards broken and due  to
         the  complexity  of implementing it as a plugin and dealing with the resource allocation
         consequences was never useful.

       • Most existing plugins  communicate  completely  using  cleartext,  exposing  metad  data
         (message size) and making it easy to fingerprint and possibly block GNUnet traffic.

       • Various NAT traversal methods are not supported.

       • The  service  logic  is cluttered with "manipulation" support code for TESTBED to enable
         faking network characteristics like lossy connections or firewewalls.

       • Bandwidth allocation is done in ATS, requiring the duplication of state and resulting in
         much  delayed  allocation decisions. As a result, often available bandwidth goes unused.
         Users are expected to manually configure bandwidth limits, instead  of  TRANSPORT  using
         congestion control to adapt automatically.

       • TRANSPORT is difficult to test and has bad test coverage.

       • HELLOs  include  an  absolute  expiration  time. Nodes with unsynchronized clocks cannot
         connect.

       • Displaying the contents of a HELLO requires the respective plugin as the plugin-specific
         data is encoded in binary. This also complicates logging.

   Design goals of TNG
       In order to address the above issues, we want to:

       • Move  plugins  into  separate processes which we shall call communicators. Communicators
         connect as clients to the transport service.

       • TRANSPORT should be able to utilize any number of communcators to the same peer  at  the
         same time.

       • TRANSPORT   should   be   responsible   for  fragmentation,  retransmission,  flow-  and
         congestion-control. Users should no longer have to configure bandwidth limits: TRANSPORT
         should detect what is available and use it.

       • Commnunicators  should  be allowed to be uni-directional and unreliable. TRANSPORT shall
         create bi-directional channels from this whenever possible.

       • DV should no longer be a plugin, but part of TRANSPORT.

       • TRANSPORT should provide communicators help communicating, for example in  the  case  of
         uni-directional  communicators or the need for out-of-band signalling for NAT traversal.
         We call this functionality backchannels.

       • Transport manipulation should be signalled to CORE on a per-message basis instead of  an
         approximate bandwidth.

       • CORE   should   signal  performance  requirements  (reliability,  latency,  etc.)  on  a
         per-message basis to TRANSPORT. If possible, TRANSPORT  should  consider  those  options
         when scheduling messages for transmission.

       • HELLOs should be in a humman-readable format with monotonic time expirations.

       The new architecture is planned as follows: [image]

       TRANSPORT’s main objective is to establish bi-directional virtual links using a variety of
       possibly uni-directional communicators. Links undergo the following steps:

       1. Communicator informs TRANSPORT A that a  queue  (direct  neighbour)  is  available,  or
          equivalently TRANSPORT A discovers a (DV) path to a target B.

       2. TRANSPORT  A  sends a challenge to the target peer, trying to confirm that the peer can
          receive. FIXME: This is not implemented properly for DV. Here we should really  take  a
          validated DVH and send a challenge exactly down that path!

       3. The  other  TRANSPORT,  TRANSPORT B, receives the challenge, and sends back a response,
          possibly using a dierent path. If TRANSPORT B does not yet have a virtual link to A, it
          must try to establish a virtual link.

       4. Upon  receiving  the  response,  TRANSPORT  A creates the virtual link. If the response
          included a challenge, TRANSPORT A must respond to this  challenge  as  well,  eectively
          re-creating the TCP 3-way handshake (just with longer challenge values).

   HELLO-NG
       HELLOs  change  in three ways. First of all, communicators encode the respective addresses
       in a human-readable URL-like string. This way, we do no longer require the communicator to
       print  the contents of a HELLO.  Second, HELLOs no longer contain an expiration time, only
       a creation time. The receiver must only compare the respective absolute values. So given a
       HELLO  from  the  same  sender  with a larger creation time, then the old one is no longer
       valid. This also obsoletes the need for the gnunet-hello binary to  set  HELLO  expiration
       times  to  never. Third, a peer no longer generates one big HELLO that always contains all
       of the addresses. Instead, each address is signed individually and shared  only  over  the
       address  scopes  where  it makes sense to share the address. In particular, care should be
       taken to not share MACs across the Internet and confine their use  to  the  LAN.  As  each
       address  is signed separately, having multiple addresses valid at the same time (given the
       new creation time expiration logic) requires that those addresses must  have  exactly  the
       same  creation  time.  Whenever  that  monotonic  time is increased, all addresses must be
       re-signed and re-distributed.

   Priorities and preferences
       In the new design, TRANSPORT adopts a feature (which was previously already  available  in
       CORE)  of  the  MQ  API  to  allow  applications to specify priorities and preferences per
       message (or rather, per MQ envelope). The (updated) MQ API allows applications to  specify
       one  of  four  priority  levels as well as desired preferences for transmission by setting
       options on an envelope. These preferences currently are:

       • GNUNET_MQ_PREF_UNRELIABLE: Disables TRANSPORT waiting for ACKS  on  unreliable  channels
         like  UDP.  Now  it  is  fire  and  forget.  These  messages then cannot be used for RTT
         estimates either.

       • GNUNET_MQ_PREF_LOW_LATENCY: Directs TRANSPORT to select the lowest-latency  transmission
         choices possible.

       • GNUNET_MQ_PREF_CORK_ALLOWED: Allows TRANSPORT to delay transmission to group the message
         with other messages into a larger batch to reduce the number of packets sent.

       • GNUNET_MQ_PREF_GOODPUT:  Directs  TRANSPORT  to  select  the  highest  goodput   channel
         available.

       • GNUNET_MQ_PREF_OUT_OF_ORDER:  Allows  TRANSPORT  to reorder the messages as it sees fit,
         otherwise TRANSPORT should attempt to preserve transmission order.

       Each MQ envelope is always able to store those options (and  the  priority),  and  in  the
       future  this  uniform  API  will  be  used  by  TRANSPORT,  CORE, CADET and possibly other
       subsystems that send messages (like LAKE). When CORE sets preferences and  priorities,  it
       is  supposed  to  respect  the  preferences and priorities it is given from higher layers.
       Similarly, CADET also simply passes on the preferences and priorities of the  layer  above
       CADET.  When  a layer combines multiple smaller messages into one larger transmission, the
       GNUNET_MQ_env_combine_options() should be used  to  calculate  options  for  the  combined
       message. We note that the exact semantics of the options may differ by layer. For example,
       CADET will always strictly implement reliable and in-order delivery of messages, while the
       same  options  are  only  advisory  for TRANSPORT and CORE: they should try (using ACKs on
       unreliable communicators, not changing the message order themselves), but if messages  are
       lost  anyway  (e.g.  because a TCP is dropped in the middle), or if messages are reordered
       (e.g. because they took different paths over the network and arrived in a different order)
       TRANSPORT and CORE do not have to correct this. Whether a preference is strict or loose is
       thus dened by the respective layer.

   Communicators
       The API for communicators is  defined  in  gnunet_transport_communication_service.h.  Each
       communicator  must  specify its (global) communication characteristics, which for now only
       say whether the communication is reliable (e.g.  TCP,  HTTPS)  or  unreliable  (e.g.  UDP,
       WLAN).  Each  communicator must specify a unique address prex, or NULL if the communicator
       cannot establish outgoing connections (for example because it is  only  acting  as  a  TCP
       server).  A  communicator  must  tell  TRANSPORT  which  addresses  it is reachable under.
       Addresses may be added or removed at any time. A  communicator  may  have  zero  addresses
       (transmission only). Addresses do not have to match the address prefix.

       TRANSPORT  may  ask  a  communicator to try to connect to another address.  TRANSPORT will
       only ask for connections where the address matches the communicator’s address prefix  that
       was  provided  when  the  connection was established. Communicators should then attempt to
       establish a connection. No response is provided  to  TRANSPORT  service  on  failure.  The
       TRANSPORT service has to ask the communicator explicitly to retry.

       If  a communicator succeeds in establishing an outgoing connection for transmission, or if
       a communicator receives an  incoming  bi-directional  connection,  the  communicator  must
       inform  the TRANSPORT service that a message queue (MQ) for transmission is now available.
       For that MQ, the communicator must provide the peer identity claimed by the other  end,  a
       human-readable  address  (for  debugging) and a maximum transfer unit (MTU). A MTU of zero
       means sending is not supported, SIZE_MAX should be  used  for  no  MTU.  The  communicator
       should  also  tell TRANSPORT what network type is used for the queue. The communicator may
       tell TRANSPORT anytime that the queue was deleted and is no longer available.

       The communicator  API  also  provides  for  flow  control.  First,  communicators  exhibit
       back-pressure  on  TRANSPORT:  the  number  of  messages  TRANSPORT may add to a queue for
       transmission will be limited. So by not draining the transmission queue, back-pressure  is
       provided  to TRANSPORT.  In the other direction, communicators may allow TRANSPORT to give
       back-pressure     towards     the     communicator     by     providing     a     non-NULL
       GNUNET_TRANSPORT_MessageCompletedCallback            argument            to            the
       GNUNET_TRANSPORT_communicator_receive function. In this case, TRANSPORT will  only  invoke
       this  function  once  it  has  processed  the  message  and  is  ready  to  receive  more.
       Communicators should then limit how much traffic they receive based on this  backpressure.
       Note       that       communicators      do      not      have      to      provide      a
       GNUNET_TRANSPORT_MessageCompletedCallback; for example, UDP cannot  support  back-pressure
       due  to  the  nature  of  the UDP protocol. In this case, TRANSPORT will implement its own
       TRANSPORT-to-TRANSPORT flow control to reduce the sender’s data rate to acceptable levels.

       TRANSPORT may notify a communicator about backchannel  messages  TRANSPORT  received  from
       other  peers  for  this communicator. Similarly, communicators can ask TRANSPORT to try to
       send a backchannel message to other communicators of other peers.  The  semantics  of  the
       backchannel  message  are  up  to  the  communicators  which  use them. TRANSPORT may fail
       transmitting backchannel messages, and TRANSPORT will not attempt to retransmit them.

   HOSTLIST  HELLO bootstrapping and gossip
       Peers in the GNUnet overlay network need address information so that they can connect with
       other  peers.  GNUnet  uses so called HELLO messages to store and exchange peer addresses.
       GNUnet provides several methods for peers to obtain this information:

       • out-of-band exchange of HELLO messages (manually, using for example gnunet-peerinfo)

       • HELLO messages shipped with GNUnet (automatic with distribution)

       • UDP neighbor discovery in LAN (IPv4 broadcast, IPv6 multicast)

       • topology gossiping (learning from other peers we already connected to), and

       • the HOSTLIST daemon  covered  in  this  section,  which  is  particularly  relevant  for
         bootstrapping new peers.

       New  peers  have  no existing connections (and thus cannot learn from gossip among peers),
       may not have other peers in their LAN and might be started with an outdated set  of  HELLO
       messages  from the distribution. In this case, getting new peers to connect to the network
       requires either manual effort or the use of a HOSTLIST to obtain HELLOs.

   HELLOs
       The basic information peers require to connect to other peers are contained in  so  called
       HELLO  messages  you  can  think  of  as a business card. Besides the identity of the peer
       (based on the cryptographic public key) a HELLO message may  contain  address  information
       that  specifies  ways to contact a peer. By obtaining HELLO messages, a peer can learn how
       to contact other peers.

   Overview for the HOSTLIST subsystem
       The HOSTLIST subsystem provides a way to distribute  and  obtain  contact  information  to
       connect  to  other  peers using a simple HTTP GET request.  Its implementation is split in
       three parts, the main file for the  daemon  itself  (gnunet-daemon-hostlist.c),  the  HTTP
       client used to download peer information (hostlist-client.c) and the server component used
       to provide this information to other peers (hostlist-server.c). The server is basically  a
       small  HTTP  web server (based on GNU libmicrohttpd) which provides a list of HELLOs known
       to the local peer for download. The client component is basically a HTTP client (based  on
       libcurl)  which can download hostlists from one or more websites. The hostlist format is a
       binary blob containing a sequence of  HELLO  messages.  Note  that  any  HTTP  server  can
       theoretically serve a hostlist, the built-in hostlist server makes it simply convenient to
       offer this service.

   Features
       The HOSTLIST daemon can:

       • provide HELLO messages with validated addresses obtained from PEERINFO to  download  for
         other peers

       • download  HELLO  messages  and  forward  these  message  to  the TRANSPORT subsystem for
         validation

       • advertises the URL of this peer’s hostlist address to other peers via gossip

       • automatically learn about hostlist servers from the gossip of other peers

   HOSTLIST - Limitations
       The HOSTLIST daemon does not:

       • verify the cryptographic information in the HELLO messages

       • verify the address information in the HELLO messages

   Interacting with the HOSTLIST daemon
       The HOSTLIST subsystem is currently implemented as a daemon, so there is no need  for  the
       user  to  interact  with  it  and  therefore  there  is no command line tool and no API to
       communicate with the daemon. In the future, we can envision changing this to  allow  users
       to manually trigger the download of a hostlist.

       Since  there  is  no  command  line  interface  to interact with HOSTLIST, the only way to
       interact with the hostlist is to use STATISTICS to obtain or modify information about  the
       status of HOSTLIST:

          $ gnunet-statistics -s hostlist

       In  particular, HOSTLIST includes a persistent value in statistics that specifies when the
       hostlist server might be queried next. As this value is  exponentially  increasing  during
       runtime,  developers  may want to reset or manually adjust it. Note that HOSTLIST (but not
       STATISTICS) needs to be shutdown if changes to this value are to have any  effect  on  the
       daemon (as HOSTLIST does not monitor STATISTICS for changes to the download frequency).

   Hostlist security address validation
       Since  information  obtained  from  other parties cannot be trusted without validation, we
       have to distinguish between validated and not validated addresses. Before  using  (and  so
       trusting)  information  from  other  parties,  this  information  has to be double-checked
       (validated).  Address validation is not done by HOSTLIST but by the TRANSPORT service.

       The HOSTLIST component is functionally located between  the  PEERINFO  and  the  TRANSPORT
       subsystem.  When acting as a server, the daemon obtains valid (validated) peer information
       (HELLO messages) from the PEERINFO service and provides it to other peers. When acting  as
       a  client,  it contacts the HOSTLIST servers specified in the configuration, downloads the
       (unvalidated) list of HELLO messages and  forwards  these  information  to  the  TRANSPORT
       server to validate the addresses.

   The HOSTLIST daemon
       The  hostlist daemon is the main component of the HOSTLIST subsystem. It is started by the
       ARM service and (if configured) starts the HOSTLIST client and server components.

       GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT If the daemon provides a hostlist itself it can
       advertise    it’s    own    hostlist   to   other   peers.   To   do   so   it   sends   a
       GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT message to other peers  when  they  connect  to
       this  peer  on  the  CORE  level.  This hostlist advertisement message contains the URL to
       access the HOSTLIST HTTP server of the sender. The daemon may also subscribe to this  type
       of  message  from  CORE  service,  and  then forward these kind of message to the HOSTLIST
       client. The client then  uses  all  available  URLs  to  download  peer  information  when
       necessary.

       When  starting,  the  HOSTLIST daemon first connects to the CORE subsystem and if hostlist
       learning is enabled, registers a CORE handler to receive this kind of  messages.  Next  it
       starts  (if  configured)  the  client  and  server. It passes pointers to CORE connect and
       disconnect and receive handlers where the client and server store their functions, so  the
       daemon can notify them about CORE events.

       To  clean up on shutdown, the daemon has a cleaning task, shutting down all subsystems and
       disconnecting from CORE.

   The HOSTLIST server
       The server provides a way for other peers to obtain HELLOs. Basically it is  a  small  web
       server  other  peers  can connect to and download a list of HELLOs using standard HTTP; it
       may also advertise the URL of the hostlist to other peers connecting on CORE level.

   The HTTP Server
       During startup, the server starts a web server listening on the port  specified  with  the
       HTTPPORT  value  (default 8080). In addition it connects to the PEERINFO service to obtain
       peer information. The HOSTLIST server uses the GNUNET_PEERINFO_iterate function to request
       HELLO  information  for all peers and adds their information to a new hostlist if they are
       suitable (expired addresses and HELLOs without addresses are both not  suitable)  and  the
       maximum  size  for  a  hostlist  is  not exceeded (MAX_BYTES_PER_HOSTLISTS = 500000). When
       PEERINFO finishes (with a last NULL callback), the server destroys the  previous  hostlist
       response  available  for  download  on  the  web  server  and replaces it with the updated
       hostlist. The hostlist format is basically a sequence of HELLO messages (as obtained  from
       PEERINFO)  without  any  special  tokenization.  Since  each HELLO message contains a size
       field, the response can easily be split into separate HELLO messages by the client.

       A HOSTLIST client connecting to the HOSTLIST server will receive the hostlist as  an  HTTP
       response  and  the  server will terminate the connection with the result code HTTP 200 OK.
       The connection will be closed immediately if no hostlist is available.

   Advertising the URL
       The server also advertises the URL to download the hostlist to  other  peers  if  hostlist
       advertisement  is enabled. When a new peer connects and has hostlist learning enabled, the
       server sends a GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT message to this peer  using  the
       CORE service.

       HOSTLIST client .. _The-HOSTLIST-client:

   The HOSTLIST client
       The  client  provides the functionality to download the list of HELLOs from a set of URLs.
       It performs a standard HTTP request to the URLs configured and learned from  advertisement
       messages  received  from  other  peers.  When  a  HELLO is downloaded, the HOSTLIST client
       forwards the HELLO to the TRANSPORT service for validation.

       The client supports two modes of operation:

       • download of HELLOs (bootstrapping)

       • learning of URLs

   Bootstrapping
       For bootstrapping, it schedules a task to download the hostlist  from  the  set  of  known
       URLs.  The  downloads  are  only performed if the number of current connections is smaller
       than a minimum number of connections (at the moment 4).  The  interval  between  downloads
       increases  exponentially;  however, the exponential growth is limited if it becomes longer
       than an hour. At that point, the frequency growth is capped at (#number of  connections  *
       1h).

       Once  the decision has been taken to download HELLOs, the daemon chooses a random URL from
       the list of known URLs. URLs can be configured in the configuration  or  be  learned  from
       advertisement  messages.  The  client uses a HTTP client library (libcurl) to initiate the
       download  using  the  libcurl  multi  interface.  Libcurl   passes   the   data   to   the
       callback_download function which stores the data in a buffer if space is available and the
       maximum size for a hostlist download is not exceeded (MAX_BYTES_PER_HOSTLISTS  =  500000).
       When  a  full  HELLO  was downloaded, the HOSTLIST client offers this HELLO message to the
       TRANSPORT service for validation. When the download is  finished  or  failed,  statistical
       information about the quality of this URL is updated.

   Learning
       The  client  also  manages  hostlist  advertisements from other peers. The HOSTLIST daemon
       forwards GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT  messages  to  the  client  subsystem,
       which  extracts  the  URL  from  the  message.  Next,  a test of the newly obtained URL is
       performed by triggering a download from the new URL. If the URL  works  correctly,  it  is
       added to the list of working URLs.

       The  size  of  the list of URLs is restricted, so if an additional server is added and the
       list is full, the URL with  the  worst  quality  ranking  (determined  through  successful
       downloads  and  number  of  HELLOs e.g.) is discarded. During shutdown the list of URLs is
       saved to a file for persistence and loaded on startup. URLs from  the  configuration  file
       are never discarded.

   Usage
       To  start  HOSTLIST  by default, it has to be added to the DEFAULTSERVICES section for the
       ARM services. This is done in the default configuration.

       For more information on how to configure  the  HOSTLIST  subsystem  see  the  installation
       handbook: Configuring  the  hostlist  to  bootstrap Configuring  your  peer  to  provide a
       hostlist

   PEERINFO  Persistent HELLO storage
       The PEERINFO subsystem is used to store verified (validated) information about known peers
       in  a  persistent way. It obtains these addresses for example from TRANSPORT service which
       is in charge of address validation.  Validation means that the information  in  the  HELLO
       message  are  checked  by  connecting  to  the  addresses  and  performing a cryptographic
       handshake to authenticate the peer instance stating to be reachable with these  addresses.
       Peerinfo  does  not validate the HELLO messages itself but only stores them and gives them
       to interested clients.

       As future work, we think about moving from storing just  HELLO  messages  to  providing  a
       generic  persistent  per-peer  information store. More and more subsystems tend to need to
       store per-peer information in persistent way. To not duplicate this functionality we  plan
       to provide a PEERSTORE service providing this functionality.

   PEERINFO - Features
       • Persistent storage

       • Client notification mechanism on update

       • Periodic clean up for expired information

       • Differentiation between public and friend-only HELLO

   PEERINFO - Limitations
       • Does not perform HELLO validation

   DeveloperPeer Information
       The  PEERINFO  subsystem  stores  these  information in the form of HELLO messages you can
       think of as business cards. These HELLO messages contain the public key of a peer and  the
       addresses a peer can be reached under. The addresses include an expiration date describing
       how long they are valid. This information is updated regularly by the TRANSPORT service by
       revalidating the address. If an address is expired and not renewed, it can be removed from
       the HELLO message.

       Some peer do not want to have their HELLO messages distributed to other peers,  especially
       when  GNUnet’s  friend-to-friend modus is enabled. To prevent this undesired distribution.
       PEERINFO distinguishes  between  public  and  friend-only  HELLO  messages.  Public  HELLO
       messages  can  be  freely distributed to other (possibly unknown) peers (for example using
       the hostlist, gossiping, broadcasting), whereas friend-only  HELLO  messages  may  not  be
       distributed to other peers. Friend-only HELLO messages have an additional flag friend_only
       set internally. For public HELLO message this flag is not set. PEERINFO  does  and  cannot
       not check if a client is allowed to obtain a specific HELLO type.

       The HELLO messages can be managed using the GNUnet HELLO library. Other GNUnet systems can
       obtain these information from PEERINFO and use it for  their  purposes.  Clients  are  for
       example  the  HOSTLIST  component  providing these information to other peers in form of a
       hostlist or the TRANSPORT subsystem using these information  to  maintain  connections  to
       other peers.

   Startup
       During  startup  the  PEERINFO services loads persistent HELLOs from disk.  First PEERINFO
       parses the directory configured in the HOSTS value of the PEERINFO  configuration  section
       to  store PEERINFO information. For all files found in this directory valid HELLO messages
       are extracted. In addition it loads HELLO messages shipped with the  GNUnet  distribution.
       These  HELLOs  are  used  to  simplify  network  bootstrapping  by  providing  valid  peer
       information with the distribution. The use of these HELLOs can be prevented by setting the
       USE_INCLUDED_HELLOS  in the PEERINFO configuration section to NO. Files containing invalid
       information are removed.

   Managing Information
       The PEERINFO services stores information about known PEERS and a single HELLO message  for
       every  peer.  A  peer does not need to have a HELLO if no information are available. HELLO
       information from different sources, for example a HELLO obtained from  a  remote  HOSTLIST
       and  a  second HELLO stored on disk, are combined and merged into one single HELLO message
       per peer which will  be  given  to  clients.  During  this  merge  process  the  HELLO  is
       immediately written to disk to ensure persistence.

       PEERINFO  in  addition  periodically  scans the directory where information are stored for
       empty HELLO messages with expired TRANSPORT addresses.  This periodic task scans all files
       in  the  directory  and recreates the HELLO messages it finds. Expired TRANSPORT addresses
       are removed from the HELLO and if the HELLO does not contain any valid  addresses,  it  is
       discarded and removed from the disk.

   Obtaining Information
       When  a  client  requests  information  from  PEERINFO, PEERINFO performs a lookup for the
       respective peer or all peers if desired and transmits this information to the client.  The
       client  can  specify if friend-only HELLOs have to be included or not and PEERINFO filters
       the respective HELLO messages before transmitting information.

       To notify clients about changes to PEERINFO information,  PEERINFO  maintains  a  list  of
       clients interested in this notifications. Such a notification occurs if a HELLO for a peer
       was updated (due to a merge for example) or a new peer was added.

   The PEERINFO Client-Service Protocol
       To connect and disconnect to and from the PEERINFO  Service  PEERINFO  utilizes  the  util
       client/server infrastructure, so no special messages types are used here.

       To  add  information  for  a  peer,  the plain HELLO message is transmitted to the service
       without any wrapping. All pieces of information  required  are  stored  within  the  HELLO
       message.  The  PEERINFO  service provides a message handler accepting and processing these
       HELLO messages.

       When obtaining PEERINFO information using the iterate functionality specific messages  are
       used.  To obtain information for all peers, a struct ListAllPeersMessage with message type
       GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL  and  a  flag  include_friend_only  to  indicate   if
       friend-only  HELLO  messages  should  be  included  are  transmitted. If information for a
       specific     peer     is     required     a      struct      ListAllPeersMessage      with
       GNUNET_MESSAGE_TYPE_PEERINFO_GET containing the peer identity is used.

       For both variants the PEERINFO service replies for each HELLO message it wants to transmit
       with a struct ListAllPeersMessage with type  GNUNET_MESSAGE_TYPE_PEERINFO_INFO  containing
       the   plain   HELLO.   The   final   message  is  struct  GNUNET_MessageHeader  with  type
       GNUNET_MESSAGE_TYPE_PEERINFO_INFO. If the client receives this  message,  it  can  proceed
       with the next request if any is pending.

   libgnunetpeerinfo
       The PEERINFO API consists mainly of three different functionalities:

       • maintaining a connection to the service

       • adding new information to the PEERINFO service

       • retrieving information from the PEERINFO service

   Connecting to the PEERINFO Service
       To  connect to the PEERINFO service the function GNUNET_PEERINFO_connect is used, taking a
       configuration handle as  an  argument,  and  to  disconnect  from  PEERINFO  the  function
       GNUNET_PEERINFO_disconnect,  taking the PEERINFO handle returned from the connect function
       has to be called.

   Adding Information to the PEERINFO Service
       GNUNET_PEERINFO_add_peer adds a new peer to the PEERINFO subsystem storage. This  function
       takes  the  PEERINFO  handle as an argument, the HELLO message to store and a continuation
       with a closure to be called with the result of the operation. The GNUNET_PEERINFO_add_peer
       returns  a  handle  to this operation allowing to cancel the operation with the respective
       cancel function GNUNET_PEERINFO_add_peer_cancel. To retrieve information from PEERINFO you
       can  iterate  over all information stored with PEERINFO or you can tell PEERINFO to notify
       if new peer information are available.

   Obtaining Information from the PEERINFO Service
       To iterate over information in PEERINFO you  use  GNUNET_PEERINFO_iterate.  This  function
       expects the PEERINFO handle, a flag if HELLO messages intended for friend only mode should
       be included, a timeout how long the operation should take and a callback with  a  callback
       closure  to  be  called  for the results. If you want to obtain information for a specific
       peer, you can specify the peer identity, if this identity is  NULL,  information  for  all
       peers  are  returned. The function returns a handle to allow to cancel the operation using
       GNUNET_PEERINFO_iterate_cancel.

       To get notified when peer information changes, you can  use  GNUNET_PEERINFO_notify.  This
       function expects a configuration handle and a flag if friend-only HELLO messages should be
       included. The PEERINFO service will  notify  you  about  every  change  and  the  callback
       function  will  be  called  to  notify you about changes. The function returns a handle to
       cancel notifications with GNUNET_PEERINFO_notify_cancel.

   PEERSTORE  Extensible local persistent data storage
       GNUnet’s  PEERSTORE  subsystem  offers  persistent  per-peer  storage  for  other   GNUnet
       subsystems.  GNUnet  subsystems  can  use  PEERSTORE  to  persistently  store and retrieve
       arbitrary data. 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.

   Functionality
       Subsystems can store any type of value under a (subsystem,  peerid,  key)  combination.  A
       "replace"  flag set during store operations forces the PEERSTORE to replace any old values
       stored  under  the  same  (subsystem,  peerid,  key)  combination  with  the  new   value.
       Additionally,  an  expiry  date  is  set  after  which the record is *possibly* deleted by
       PEERSTORE.

       Subsystems can iterate over all values stored under any of the  following  combination  of
       fields:

       • (subsystem)

       • (subsystem, peerid)

       • (subsystem, key)

       • (subsystem, peerid, key)

       Subsystems can also request to be notified about any new values stored under a (subsystem,
       peerid, key) combination by sending a "watch" request to PEERSTORE.

   Architecture
       PEERSTORE implements the following components:

       • PEERSTORE service: Handles store, iterate and watch operations.

       • PEERSTORE API: API to be used by other subsystems to communicate and issue  commands  to
         the PEERSTORE service.

       • PEERSTORE  plugins:  Handles  the  persistent  storage.  At the moment, only an "sqlite"
         plugin is implemented.

   libgnunetpeerstore
       libgnunetpeerstore is the library containing the PEERSTORE  API.   Subsystems  wishing  to
       communicate  with  the  PEERSTORE  service use this API to open a connection to PEERSTORE.
       This is done by calling GNUNET_PEERSTORE_connect which  returns  a  handle  to  the  newly
       created connection. This handle has to be used with any further calls to the API.

       To  store  a  new record, the function GNUNET_PEERSTORE_store is to be used which requires
       the record fields and a continuation function that will be called by  the  API  after  the
       STORE  request  is  sent  to  the  PEERSTORE  service.  Note that calling the continuation
       function does not mean that the record is successfully stored, only that the STORE request
       has been successfully sent to the PEERSTORE service.  GNUNET_PEERSTORE_store_cancel can be
       called to cancel the STORE request only before the continuation function has been called.

       To iterate over stored records, the  function  GNUNET_PEERSTORE_iterate  is  to  be  used.
       peerid  and key can be set to NULL. An iterator callback function will be called with each
       matching record found and a NULL record at the end  to  signal  the  end  of  result  set.
       GNUNET_PEERSTORE_iterate_cancel  can  be  used  to  cancel  the ITERATE request before the
       iterator callback is called with a NULL record.

       To be notified with new values stored under a (subsystem, peerid,  key)  combination,  the
       function  GNUNET_PEERSTORE_watch  is  to  be used. This will register the watcher with the
       PEERSTORE service, any new  records  matching  the  given  combination  will  trigger  the
       callback    function    passed    to    GNUNET_PEERSTORE_watch.   This   continues   until
       GNUNET_PEERSTORE_watch_cancel is called or the connection to the service is destroyed.

       After the connection is no longer needed, the function GNUNET_PEERSTORE_disconnect can  be
       called  to  disconnect  from  the PEERSTORE service. Any pending ITERATE or WATCH requests
       will be destroyed. If the sync_first flag is set to GNUNET_YES, the  API  will  delay  the
       disconnection  until  all  pending  STORE  requests  are  sent  to  the PEERSTORE service,
       otherwise, the pending STORE requests will be destroyed as well.

   CORE  GNUnet link layer
       The CORE subsystem in GNUnet is responsible for securing link-layer communications between
       nodes in the GNUnet overlay network. CORE builds on the TRANSPORT subsystem which provides
       for the actual, insecure, unreliable link-layer communication (for  example,  via  UDP  or
       WLAN), and then adds fundamental security to the connections:

       • confidentiality  with  so-called  perfect  forward secrecy; we use ECDHE (Elliptic-curve
         Diffie—Hellman) powered by Curve25519 (Curve25519) for the key  exchange  and  then  use
         symmetric encryption, encrypting with both AES-256 (AES-256) and Twofish (Twofish)

       • authentication  is  achieved  by  signing  the ephemeral keys using Ed25519 (Ed25519), a
         deterministic variant of ECDSA (ECDSA)

       • integrity protection (using SHA-512 (SHA-512) to do encrypt-then-MAC (encrypt-then-MAC))

       • Replay  (replay)  protection  (using  nonces,  timestamps,  challenge-response,  message
         counters and ephemeral keys)

       • liveness (keep-alive messages, timeout)

   Limitations
       CORE  does  not  perform routing; using CORE it is only possible to communicate with peers
       that happen to already be "directly" connected with each other. CORE also does not have an
       API  to allow applications to establish such "direct" connections — for this, applications
       can ask TRANSPORT, but TRANSPORT might not be able to establish a "direct" connection. The
       TOPOLOGY  subsystem  is  responsible for trying to keep a few "direct" connections open at
       all times.  Applications that need to talk  to  particular  peers  should  use  the  CADET
       subsystem, as it can establish arbitrary "indirect" connections.

       Because  CORE  does  not  perform routing, CORE must only be used directly by applications
       that either perform their own routing logic (such as anonymous file-sharing)  or  that  do
       not  require  routing,  for  example  because they are based on flooding the network. CORE
       communication is unreliable and  delivery  is  possibly  out-of-order.  Applications  that
       require  reliable  communication  should  use the CADET service. Each application can only
       queue one message per target peer with the CORE service at any time;  messages  cannot  be
       larger  than  approximately  63  kilobytes. If messages are small, CORE may group multiple
       messages (possibly from different applications) prior to encryption. If permitted  by  the
       application  (using  the cork option), CORE may delay transmissions to facilitate grouping
       of multiple small messages. If cork is not enabled, CORE will transmit the message as soon
       as  TRANSPORT  allows  it  (TRANSPORT is responsible for limiting bandwidth and congestion
       control). CORE does not allow flow control; applications are expected to process  messages
       at line-speed. If flow control is needed, applications should use the CADET service.

   When is a peer connected ?
       In  addition  to  the security features mentioned above, CORE also provides one additional
       key feature to applications using it, and that is a limited form of protocol-compatibility
       checking.   CORE   distinguishes   between   TRANSPORT-level   connections  (which  enable
       communication with other peers) and application-level connections. Applications using  the
       CORE  API  will  (typically)  learn about application-level connections from CORE, and not
       about TRANSPORT-level connections. When a typical application uses CORE, it will specify a
       set  of message types (from gnunet_protocols.h) that it understands. CORE will then notify
       the application  about  connections  it  has  with  other  peers  if  and  only  if  those
       applications  registered  an  intersecting  set  of message types with their CORE service.
       Thus, it is quite possible that CORE only exposes  a  subset  of  the  established  direct
       connections  to  a  particular application — and different applications running above CORE
       might see different sets of connections at the same time.

       A special case are applications that do not register a handler for any message type.  CORE
       assumes  that these applications merely want to monitor connections (or "all" messages via
       other callbacks) and will notify those applications about all connections. This  is  used,
       for  example, by the gnunet-core command-line tool to display the active connections. Note
       that it is also possible that the TRANSPORT service has more active connections  than  the
       CORE  service,  as  the  CORE  service first has to perform a key exchange with connecting
       peers  before  exchanging  information  about  supported  message  types   and   notifying
       applications about the new connection.

   libgnunetcore
       The  CORE  API  (defined  in gnunet_core_service.h) is the basic messaging API used by P2P
       applications built using GNUnet. It provides applications the ability to send and  receive
       encrypted messages to the peer’s "directly" connected neighbours.

       As  CORE connections are generally "direct" connections, applications must not assume that
       they can connect to arbitrary peers this way, as "direct" connections may  not  always  be
       possible.  Applications  using CORE are notified about which peers are connected. Creating
       new "direct" connections must be done using the TRANSPORT API.

       The CORE API provides unreliable, out-of-order delivery. While the implementation tries to
       ensure  timely, in-order delivery, both message losses and reordering are not detected and
       must be  tolerated  by  the  application.  Most  important,  the  core  will  NOT  perform
       retransmission if messages could not be delivered.

       Note  that  CORE  allows applications to queue one message per connected peer. The rate at
       which each connection operates  is  influenced  by  the  preferences  expressed  by  local
       application  as  well  as  restrictions  imposed by the other peer. Local applications can
       express their preferences for particular connections using the "performance"  API  of  the
       ATS service.

       Applications  that  require  more sophisticated transmission capabilities such as TCP-like
       behavior, or if you intend to send messages to arbitrary  remote  peers,  should  use  the
       CADET API.

       The   typical   use   of   the   CORE  API  is  to  connect  to  the  CORE  service  using
       GNUNET_CORE_connect, process events from the CORE service (such as peers connecting, peers
       disconnecting   and  incoming  messages)  and  send  messages  to  connected  peers  using
       GNUNET_CORE_notify_transmit_ready.    Note   that   applications   must   cancel   pending
       transmission  requests  if  they  receive  a  disconnect  event  for  a  peer  that  had a
       transmission pending; furthermore, queuing more than one transmission request per peer per
       application using the service is not permitted.

       The  CORE  API also allows applications to monitor all communications of the peer prior to
       encryption (for outgoing messages) or after decryption (for incoming messages).  This  can
       be  useful  for  debugging, diagnostics or to establish the presence of cover traffic (for
       anonymity). As monitoring applications are  often  not  interested  in  the  payload,  the
       monitoring  callbacks can be configured to only provide the message headers (including the
       message type and size) instead of copying the full data stream to the monitoring client.

       The init callback of the GNUNET_CORE_connect function is  called  with  the  hash  of  the
       public  key  of  the  peer.  This  public key is used to identify the peer globally in the
       GNUnet network. Applications are encouraged to check that the provided  hash  matches  the
       hash  that  they  are  using  (as  theoretically  the application may be using a different
       configuration file with a different private key, which would result in hard to find bugs).

       As with most service APIs, the CORE API isolates applications from  crashes  of  the  CORE
       service.  If  the CORE service crashes, the application will see disconnect events for all
       existing connections.  Once the connections are re-established, the applications  will  be
       receive matching connect events.

       core client-service protocol .. _The-CORE-Client_002dService-Protocol:

   The CORE Client-Service Protocol
       This  section  describes  the  protocol between an application using the CORE service (the
       client) and the CORE service process itself.

   Setup2
       When a client connects to the CORE service, it first sends a InitMessage  which  specifies
       options  for  the  connection  and a set of message type values which are supported by the
       application. The options bitmask specifies which  events  the  client  would  like  to  be
       notified about. The options include:

       GNUNET_CORE_OPTION_NOTHING
              No notifications

       GNUNET_CORE_OPTION_STATUS_CHANGE
              Peers connecting and disconnecting

       GNUNET_CORE_OPTION_FULL_INBOUND
              All inbound messages (after decryption) with full payload

       GNUNET_CORE_OPTION_HDR_INBOUND
              Just the MessageHeader of all inbound messages

       GNUNET_CORE_OPTION_FULL_OUTBOUND
              All outbound messages (prior to encryption) with full payload

       GNUNET_CORE_OPTION_HDR_OUTBOUND
              Just the MessageHeader of all outbound messages

       Typical applications will only monitor for connection status changes.

       The  CORE  service responds to the InitMessage with an InitReplyMessage which contains the
       peer’s identity. Afterwards, both CORE and the client can send messages.

   Notifications
       The CORE will  send  ConnectNotifyMessages  and  DisconnectNotifyMessages  whenever  peers
       connect  or  disconnect  from  the CORE (assuming their type maps overlap with the message
       types registered by the client). When the CORE receives a message that matches the set  of
       message types specified during the InitMessage (or if monitoring is enabled in for inbound
       messages in the options), it sends a NotifyTrafficMessage with the peer  identity  of  the
       sender   and   the   decrypted   payload.   The   same   message   format   (except   with
       GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND for the message type) is used to  notify  clients
       monitoring outbound messages; here, the peer identity given is that of the receiver.

   Sending
       When  a  client  wants  to  transmit  a  message, it first requests a transmission slot by
       sending a SendMessageRequest which specifies  the  priority,  deadline  and  size  of  the
       message.  Note  that  these  values  may  be  ignored  by CORE. When CORE is ready for the
       message, it answers with a SendMessageReady response. The client  can  then  transmit  the
       payload  with  a SendMessage message. Note that the actual message size in the SendMessage
       is allowed to be smaller than the size in the original request. A client may at  any  time
       send  a  fresh  SendMessageRequest, which then superceeds the previous SendMessageRequest,
       which is then no longer valid. The client  can  tell  which  SendMessageRequest  the  CORE
       service’s  SendMessageReady  message  is  for  as all of these messages contain a "unique"
       request ID (based on a counter incremented by the client for each request).

       CORE Peer-to-Peer Protocol .. _The-CORE-Peer_002dto_002dPeer-Protocol:

   The CORE Peer-to-Peer Protocol
       EphemeralKeyMessage creation .. _Creating-the-EphemeralKeyMessage:

   Creating the EphemeralKeyMessage
       When the CORE service starts, each peer creates a fresh ephemeral (ECC) public-private key
       pair  and  signs  the  corresponding  EphemeralKeyMessage with its long-term key (which we
       usually call the peer’s identity; the hash of the public long term key is what results  in
       a  struct  GNUNET_PeerIdentity  in  all GNUnet APIs. The ephemeral key is ONLY used for an
       ECDHE (Elliptic-curve Diffie—Hellman) exchange by the CORE service to establish  symmetric
       session   keys.   A  peer  will  use  the  same  EphemeralKeyMessage  for  all  peers  for
       REKEY_FREQUENCY, which is usually 12 hours. After  that  time,  it  will  create  a  fresh
       ephemeral  key  (forgetting  the old one) and broadcast the new EphemeralKeyMessage to all
       connected peers, resulting in fresh symmetric session keys. Note that peers  independently
       decide  on  when to discard ephemeral keys; it is not a protocol violation to discard keys
       more often. Ephemeral keys are also never stored to disk;  restarting  a  peer  will  thus
       always  create  a  fresh ephemeral key. The use of ephemeral keys is what provides forward
       secrecy.

       Just before transmission, the  EphemeralKeyMessage  is  patched  to  reflect  the  current
       sender_status,  which specifies the current state of the connection from the point of view
       of the sender. The possible values are:

       • KX_STATE_DOWN Initial value, never used on the network

       • KX_STATE_KEY_SENT We sent our ephemeral key, do not know the key of the other peer

       • KX_STATE_KEY_RECEIVED This peer has received a valid ephemeral key of  the  other  peer,
         but  we  are waiting for the other peer to confirm it’s authenticity (ability to decode)
         via challenge-response.

       • KX_STATE_UP The connection is fully up from  the  point  of  view  of  the  sender  (now
         performing keep-alive)

       • KX_STATE_REKEY_SENT The sender has initiated a rekeying operation; the other peer has so
         far failed to confirm a working connection using the new ephemeral key

   Establishing a connection
       Peers begin their interaction by sending a EphemeralKeyMessage to the other peer once  the
       TRANSPORT  service  notifies  the  CORE  service about the connection. A peer receiving an
       EphemeralKeyMessage with a status indicating that the sender does not have the  receiver’s
       ephemeral  key,  the receiver’s EphemeralKeyMessage is sent in response.  Additionally, if
       the receiver has not yet confirmed the authenticity  of  the  sender,  it  also  sends  an
       (encrypted)PingMessage  with  a  challenge  (and  the identity of the target) to the other
       peer. Peers receiving a PingMessage respond with an (encrypted) PongMessage which includes
       the  challenge.  Peers  receiving a PongMessage check the challenge, and if it matches set
       the connection to KX_STATE_UP.

   Encryption and Decryption
       All functions related to the key exchange and encryption/decryption  of  messages  can  be
       found  in  gnunet-service-core_kx.c (except for the cryptographic primitives, which are in
       util/crypto*.c). Given the key  material  from  ECDHE,  a  Key  derivation  function  (Key
       derivation  function)  is  used  to derive two pairs of encryption and decryption keys for
       AES-256 and TwoFish, as well as initialization vectors and authentication keys  (for  HMAC
       (HMAC)).  The  HMAC  is computed over the encrypted payload. Encrypted messages include an
       iv_seed and the HMAC in the header.

       Each encrypted message in the CORE service includes a sequence number and a  timestamp  in
       the encrypted payload. The CORE service remembers the largest observed sequence number and
       a bit-mask which represents which of the previous 32 sequence numbers were  already  used.
       Messages  with  sequence  numbers lower than the largest observed sequence number minus 32
       are discarded. Messages with a timestamp that is less than REKEY_TOLERANCE off (5 minutes)
       are  also  discarded.  This  of  course  means  that  system  clocks need to be reasonably
       synchronized for peers to be able to  communicate.  Additionally,  as  the  ephemeral  key
       changes  every  12  hours, a peer would not even be able to decrypt messages older than 12
       hours.

   Type maps
       Once an encrypted connection has been established, peers begin to exchange type maps. Type
       maps  are used to allow the CORE service to determine which (encrypted) connections should
       be shown to which applications. A type map is an array  of  65536  bits  representing  the
       different  types  of messages understood by applications using the CORE service. Each CORE
       service maintains this map, simply by setting the respective bit  for  each  message  type
       supported  by  any  of the applications using the CORE service. Note that bits for message
       types embedded in higher-level protocols (such as MESH) will not be included in these type
       maps.

       Typically,  the  type  map  of  a  peer will be sparse. Thus, the CORE service attempts to
       compress its type map using gzip-style  compression  ("deflate")  prior  to  transmission.
       However,  if  the  compression  fails  to compact the map, the map may also be transmitted
       without  compression   (resulting   in   GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP   or
       GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP  messages  respectively).   Upon receiving a type
       map, the respective CORE service notifies applications about the connection to  the  other
       peer  if  they  support  any message type indicated in the type map (or no message type at
       all). If the CORE service experience a connect or disconnect event from an application, it
       updates  its  type  map  (setting  or  unsetting  the  respective  bits)  and notifies its
       neighbours about the change. The CORE services of the neighbours  then  in  turn  generate
       connect  and  disconnect  events  for the peer that sent the type map for their respective
       applications. As CORE messages may be lost, the CORE service confirms receiving a type map
       by  sending back a GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP. If such a confirmation (with
       the correct hash of the type map) is not received, the sender will retransmit the type map
       (with exponential back-off).

   NSE  Network size estimation
       NSE  stands  for  Network Size Estimation. The NSE subsystem provides other subsystems and
       users with a rough estimate of the number of peers currently participating in  the  GNUnet
       overlay.  The  computed  value  is not a precise number as producing a precise number in a
       decentralized, efficient and secure way is impossible. While NSE’s estimate is  inherently
       imprecise, NSE also gives the expected range. For a peer that has been running in a stable
       network for a while, the real network size will typically (99.7% of the time)  be  in  the
       range  of [2/3 estimate, 3/2 estimate]. We will now give an overview of the algorithm used
       to calculate the estimate; all of the details can be found in this technical report.

   Todo
       link to the report.

   Motivation
       Some subsystems, like DHT, need to know the size of the GNUnet network  to  optimize  some
       parameters  of  their own protocol. The decentralized nature of GNUnet makes efficient and
       securely counting the exact  number  of  peers  infeasible.  Although  there  are  several
       decentralized algorithms to count the number of peers in a system, so far there is none to
       do so securely. Other protocols may allow any  malicious  peer  to  manipulate  the  final
       result  or  to  take  advantage  of  the system to perform Denial of Service (DoS) attacks
       against the network. GNUnet’s NSE protocol avoids these drawbacks.

       NSE security .. _Security:

   Security
       The NSE subsystem is designed to be resilient against these attacks.  It  uses  proofs  of
       work  to  prevent  one peer from impersonating a large number of participants, which would
       otherwise allow an adversary to artificially inflate  the  estimate.  The  DoS  protection
       comes   from  the  time-based  nature  of  the  protocol:  the  estimates  are  calculated
       periodically and out-of-time traffic is either ignored or stored for later  retransmission
       by benign peers. In particular, peers cannot trigger global network communication at will.

   Principle
       The algorithm calculates the estimate by finding the globally closest peer ID to a random,
       time-based value.

       The idea is that the closer the ID is to the random value, the more "densely  packed"  the
       ID space is, and therefore, more peers are in the network.

   Example
       Suppose  all  peers have IDs between 0 and 100 (our ID space), and the random value is 42.
       If the closest peer has the ID 70 we can imagine that the average "distance" between peers
       is  around  30  and  therefore  the are around 3 peers in the whole ID space. On the other
       hand, if the closest peer has the ID 44, we can imagine that the space  is  rather  packed
       with peers, maybe as much as 50 of them. Naturally, we could have been rather unlucky, and
       there is only one peer and happens to have the  ID  44.  Thus,  the  current  estimate  is
       calculated as the average over multiple rounds, and not just a single sample.

   Algorithm
       Given  that  example,  one  can  imagine  that  the job of the subsystem is to efficiently
       communicate the ID of the closest peer to the target value to all  the  other  peers,  who
       will calculate the estimate from it.

   Target value
       The  target  value  itself  is  generated  by hashing the current time, rounded down to an
       agreed value. If the rounding amount is 1h (default) and the time is 12:34:56, the time to
       hash  would  be  12:00:00.  The  process is repeated each rounding amount (in this example
       would be every hour). Every repetition is called a round.

   Timing
       The NSE subsystem has some timing control to avoid everybody broadcasting its  ID  all  at
       one.  Once each peer has the target random value, it compares its own ID to the target and
       calculates the hypothetical size of the network if that peer were to be the closest.  Then
       it  compares  the  hypothetical  size with the estimate from the previous rounds. For each
       value there is an associated point in the period, let’s call it "broadcast time".  If  its
       own  hypothetical  estimate  is  the  same as the previous global estimate, its "broadcast
       time" will be in the middle of the round. If its bigger it will  be  earlier  and  if  its
       smaller  (the  most  likely case) it will be later. This ensures that the peers closest to
       the target value start broadcasting their ID the first.

   Controlled Flooding
       When a peer receives a value, first it verifies that it is closer than the  closest  value
       it  had  so  far,  otherwise it answers the incoming message with a message containing the
       better value. Then it checks a proof of  work  that  must  be  included  in  the  incoming
       message,  to  ensure  that  the other peer’s ID is not made up (otherwise a malicious peer
       could claim to have an ID of exactly the target value every  round).  Once  validated,  it
       compares  the  broadcast  time of the received value with the current time and if it’s not
       too early, sends the received value to its neighbors. Otherwise it stores the value  until
       the correct broadcast time comes. This prevents unnecessary traffic of sub-optimal values,
       since a better value can come before  the  broadcast  time,  rendering  the  previous  one
       obsolete  and  saving  the  traffic  that  would  have  been  used  to broadcast it to the
       neighbors.

   Calculating the estimate
       Once the closest ID has been spread across the network each peer gets the  exact  distance
       between  this  ID  and  the  target  value of the round and calculates the estimate with a
       mathematical formula described in the tech report. The estimate generated with this method
       for  a  single round is not very precise. Remember the case of the example, where the only
       peer is the ID 44 and we happen to generate the target value 42,  thinking  there  are  50
       peers  in  the  network.  Therefore, the NSE subsystem remembers the last 64 estimates and
       calculates an average over them,  giving  a  result  of  which  usually  has  one  bit  of
       uncertainty  (the real size could be half of the estimate or twice as much). Note that the
       actual network size is calculated in powers of two of the  raw  input,  thus  one  bit  of
       uncertainty means a factor of two in the size estimate.

   libgnunetnse
       The   NSE  subsystem  has  the  simplest  API  of  all  services,  with  only  two  calls:
       GNUNET_NSE_connect and GNUNET_NSE_disconnect.

       The connect call gets a callback function as a parameter and this function is called  each
       time  the  network  agrees  on  an  estimate.  This  usually  is once per round, with some
       exceptions: if the closest peer has a late local clock and starts spreading its  ID  after
       everyone  else  agreed  on  a value, the callback might be activated twice in a round, the
       second value being always bigger than the first. The default round time is set to 1 hour.

       The disconnect call disconnects from the NSE subsystem  and  the  callback  is  no  longer
       called with new estimates.

   Results
       The  callback  provides  two values: the average and the standard deviation of the last 64
       rounds. The values provided by the callback function are logarithmic, this means that  the
       real  estimate  numbers  can  be obtained by calculating 2 to the power of the given value
       (2average). From a statistics point of view this means that:

       • 68% of the time the real size is included in the interval [(2average-stddev), 2]

       • 95% of the  time  the  real  size  is  included  in  the  interval  [(2average-2*stddev,
         2^average+2*stddev]

       • 99.7%  of  the  time  the  real  size  is  included in the interval [(2average-3*stddev,
         2average+3*stddev]

       The expected standard variation for 64 rounds in a network of stable size is 0.2. Thus, we
       can say that normally:

       • 68% of the time the real size is in the range [-13%, +15%]

       • 95% of the time the real size is in the range [-24%, +32%]

       • 99.7% of the time the real size is in the range [-34%, +52%]

       As  said  in  the introduction, we can be quite sure that usually the real size is between
       one third and three times the estimate. This can of course vary with  network  conditions.
       Thus,  applications  may  want to also consider the provided standard deviation value, not
       only the average (in particular, if the standard variation is very high, the average maybe
       meaningless: the network size is changing rapidly).

   Examples
       Let’s close with a couple examples.

       Average: 10, std dev: 1 Here the estimate would be
              2^10  =  1024 peers. (The range in which we can be 95% sure is: [2^8, 2^12] = [256,
              4096]. We can be very (>99.7%) sure that the network is not  a  hundred  peers  and
              absolutely sure that it is not a million peers, but somewhere around a thousand.)

       Average 22, std dev: 0.2 Here the estimate would be
              2^22  =  4  Million  peers.  (The  range in which we can be 99.7% sure is: [2^21.4,
              2^22.6] = [2.8M, 6.3M]. We can be  sure  that  the  network  size  is  around  four
              million, with absolutely way of it being 1 million.)

       To  put  this  in  perspective,  if  someone  remembers  the LHC Higgs boson results, were
       announced with "5 sigma" and "6 sigma" certainties. In this case a 5 sigma  minimum  would
       be 2 million and a 6 sigma minimum, 1.8 million.

   The NSE Client-Service Protocol
       As  with  the  API,  the  client-service  protocol  is  very  simple, only has 2 different
       messages, defined in src/nse/nse.h:

       • GNUNET_MESSAGE_TYPE_NSE_START This message has no parameters and is sent from the client
         to the service upon connection.

       • GNUNET_MESSAGE_TYPE_NSE_ESTIMATE This message is sent from the service to the client for
         every new estimate and upon connection.  Contains a  timestamp  for  the  estimate,  the
         average and the standard deviation for the respective round.

       When  the  GNUNET_NSE_disconnect  API call is executed, the client simply disconnects from
       the service, with no message involved.

       NSE Peer-to-Peer Protocol .. _The-NSE-Peer_002dto_002dPeer-Protocol:

   The NSE Peer-to-Peer Protocol
       GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD The NSE subsystem  only  has  one  message  in  the  P2P
       protocol, the GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD message.

       This  message  key contents are the timestamp to identify the round (differences in system
       clocks may cause some peers to send messages way  too  early  or  way  too  late,  so  the
       timestamp  allows other peers to identify such messages easily), the proof of work used to
       make it difficult to mount a Sybil attack, and the public key, which is used to verify the
       signature on the message.

       Every  peer  stores  a message for the previous, current and next round.  The messages for
       the previous and current round are given to peers that connect to us. The message for  the
       next round is simply stored until our system clock advances to the next round. The message
       for the current round is what we are flooding the network with right now. At the beginning
       of each round the peer does the following:

       • calculates its own distance to the target value

       • creates,  signs  and  stores  the  message for the current round (unless it has a better
         message in the "next round" slot which came early in the previous round)

       • calculates, based on the stored round message (own or received) when to  start  flooding
         it to its neighbors

       Upon  receiving  a  message  the  peer checks the validity of the message (round, proof of
       work, signature). The next action depends on the contents of the incoming message:

       • if the message is worse than the current stored message,  the  peer  sends  the  current
         message back immediately, to stop the other peer from spreading suboptimal results

       • if  the  message  is  better  than  the  current stored message, the peer stores the new
         message and calculates the new target time  to  start  spreading  it  to  its  neighbors
         (excluding the one the message came from)

       • if  the  message  is for the previous round, it is compared to the message stored in the
         "previous round slot", which may then be updated

       • if the message is for the next round, it is compared to the message stored in the  "next
         round slot", which again may then be updated

       Finally,  when  it comes to send the stored message for the current round to the neighbors
       there is a random delay added for each neighbor, to  avoid  traffic  spikes  and  minimize
       cross-messages.

   DHT  Distributed Hash Table
       GNUnet  includes  a generic distributed hash table that can be used by developers building
       P2P applications in the framework. This section  documents  high-level  features  and  how
       developers  are  expected  to  use the DHT. We have a research paper detailing how the DHT
       works. Also, Nate’s thesis includes a detailed description and  performance  analysis  (in
       chapter 6). [R5N2011]

   Todo
       Confirm: Are “Nate’s thesis” and the “research paper” separate entities?

       Key features of GNUnet’s DHT include:

       • stores key-value pairs with values up to (approximately) 63k in size

       • works  with  many underlay network topologies (small-world, random graph), underlay does
         not need to be a full mesh / clique

       • support for extended queries (more  than  just  a  simple  ‘key’),  filtering  duplicate
         replies  within  the  network  (bloomfilter) and content validation (for details, please
         read the subsection on the block library)

       • can (optionally) return paths taken by the PUT and GET operations to the application

       • provides content replication to handle churn

       GNUnet’s DHT is randomized and unreliable.  Unreliable  means  that  there  is  no  strict
       guarantee that a value stored in the DHT is always found — values are only found with high
       probability. While this is somewhat true in all P2P  DHTs,  GNUnet  developers  should  be
       particularly  wary  of  this  fact (this will help you write secure, fault-tolerant code).
       Thus, when writing  any  application  using  the  DHT,  you  should  always  consider  the
       possibility  that  a value stored in the DHT by you or some other peer might simply not be
       returned, or returned with a significant delay. Your application logic must be written  to
       tolerate  this  (naturally,  some loss of performance or quality of service is expected in
       this case).

   Block library and plugins
   What is a Block?
       Blocks are small (< 63k) pieces of data  stored  under  a  key  (struct  GNUNET_HashCode).
       Blocks  have  a  type  (enum GNUNET_BlockType) which defines their data format. Blocks are
       used in GNUnet as units of static data exchanged between  peers  and  stored  (or  cached)
       locally.  Uses  of  blocks include file-sharing (the files are broken up into blocks), the
       VPN (DNS information is stored in blocks) and the DHT (all  information  in  the  DHT  and
       meta-information  for  the maintenance of the DHT are both stored using blocks). The block
       subsystem provides a few common functions that must be available for any type of block.

       libgnunetblock API .. _The-API-of-libgnunetblock:

   The API of libgnunetblock
       The block library requires for each (family of) block type(s) a block plugin (implementing
       gnunet_block_plugin.h)  that  provides  basic  functions  that  are needed by the DHT (and
       possibly other subsystems)  to  manage  the  block.  These  block  plugins  are  typically
       implemented  within  their  respective  subsystems. The main block library is then used to
       locate, load and query the appropriate  block  plugin.  Which  plugin  is  appropriate  is
       determined  by the block type (which is just a 32-bit integer). Block plugins contain code
       that specifies which block types are supported by a given plugin. The block library  loads
       all  block  plugins  that  are  installed  at  the local peer and forwards the application
       request to the respective plugin.

       The central functions of the block APIs (plugin and main library) are to allow the mapping
       of  blocks  to their respective key (if possible) and the ability to check that a block is
       well-formed and matches a given request (again, if possible). This way, GNUnet  can  avoid
       storing  invalid  blocks,  storing  blocks  under  the  wrong key and forwarding blocks in
       response to a query that they do not answer.

       One key function of block plugins is that it allows GNUnet  to  detect  duplicate  replies
       (via  the  Bloom  filter). All plugins MUST support detecting duplicate replies (by adding
       the current response to the Bloom filter and rejecting it if it is encountered again).  If
       a plugin fails to do this, responses may loop in the network.

   Queries
       The query format for any block in GNUnet consists of four main components. First, the type
       of the desired block must be specified.  Second, the query must contain a hash  code.  The
       hash  code is used for lookups in hash tables and databases and must not be unique for the
       block (however, if possible a unique hash should  be  used  as  this  would  be  best  for
       performance).  Third,  an optional Bloom filter can be specified to exclude known results;
       replies  that  hash  to  the  bits  set  in  the  Bloom  filter  are  considered  invalid.
       False-positives  can  be eliminated by sending the same query again with a different Bloom
       filter mutator value, which parametrizes the hash function  that  is  used.   Finally,  an
       optional  application-specific  "eXtended  query"  (xquery)  can  be  specified to further
       constrain the results. It is entirely up to the type-specific plugin to determine  whether
       or  not  a  given block matches a query (type, hash, Bloom filter, and xquery). Naturally,
       not all xquery’s are valid and some types of blocks may not support Bloom filters  either,
       so the plugin also needs to check if the query is valid in the first place.

       Depending  on  the results from the plugin, the DHT will then discard the (invalid) query,
       forward the query, discard the (invalid) reply, cache the (valid)  reply,  and/or  forward
       the (valid and non-duplicate) reply.

   Sample Code
       The source code in plugin_block_test.c is a good starting point for new block plugins — it
       does the minimal work by implementing a plugin that performs no  validation  at  all.  The
       respective Makefile.am shows how to build and install a block plugin.

   Conclusion2
       In  conclusion,  GNUnet  subsystems that want to use the DHT need to define a block format
       and write a plugin to match queries and replies. For testing,  the  GNUNET_BLOCK_TYPE_TEST
       block type can be used; it accepts any query as valid and any reply as matching any query.
       This type is also used for the DHT command line tools. However, it should NOT be used  for
       normal  applications  due  to  the lack of error checking that results from this primitive
       implementation.

       libgnunetdht libgnunetdht ———————————————-

       The DHT API itself is pretty simple and offers the usual GET and PUT functions  that  work
       as  expected. The specified block type refers to the block library which allows the DHT to
       run application-specific logic for data stored in the network.

   GET
       When using GET, the main consideration for  developers  (other  than  the  block  library)
       should  be  that  after  issuing a GET, the DHT will continuously cause (small amounts of)
       network traffic until the operation is explicitly canceled. So GET does  not  simply  send
       out a single network request once; instead, the DHT will continue to search for data. This
       is needed to achieve good success rates and also handles the case where the respective PUT
       operation  happens  after  the  GET operation was started. Developers should not cancel an
       existing GET operation and then explicitly re-start it to trigger a new round  of  network
       requests;  this is simply inefficient, especially as the internal automated version can be
       more efficient, for example by filtering results in the network  that  have  already  been
       returned.

       If  an  application that performs a GET request has a set of replies that it already knows
       and would like to filter, it can call GNUNET_DHT_get_filter_known_results with an array of
       hashes  over the respective blocks to tell the DHT that these results are not desired (any
       more). This way, the DHT will filter the respective blocks using the block library in  the
       network, which may result in a significant reduction in bandwidth consumption.

   PUT
   Todo
       inconsistent use of “must” above it’s written “MUST”

       In contrast to GET operations, developers must manually re-run PUT operations periodically
       (if they intend the content to continue to  be  available).  Content  stored  in  the  DHT
       expires  or  might  be  lost  due  to  churn. Furthermore, GNUnet’s DHT typically requires
       multiple rounds of PUT operations before a key-value pair is consistently available to all
       peers (the DHT randomizes paths and thus storage locations, and only after multiple rounds
       of PUTs there will be a sufficient number of replicas in  large  DHTs).  An  explicit  PUT
       operation  using  the  DHT API will only cause network traffic once, so in order to ensure
       basic availability and resistance to churn (and adversaries), PUTs must be repeated. While
       the exact frequency depends on the application, a rule of thumb is that there should be at
       least a dozen PUT operations within the content lifetime. Content  in  the  DHT  typically
       expires after one day, so DHT PUT operations should be repeated at least every 1-2 hours.

   MONITOR
       The  DHT  API also allows applications to monitor messages crossing the local DHT service.
       The types of messages used by the  DHT  are  GET,  PUT  and  RESULT  messages.  Using  the
       monitoring  API,  applications  can  choose  to  monitor these requests, possibly limiting
       themselves to requests for a particular block type.

       The monitoring API is not only useful for diagnostics, it can  also  be  used  to  trigger
       application  operations  based on PUT operations. For example, an application may use PUTs
       to distribute work requests to other peers. The workers would then monitor for  PUTs  that
       give  them work, instead of looking for work using GET operations. This can be beneficial,
       especially if the workers have no good way to guess the keys under  which  work  would  be
       stored.  Naturally, additional protocols might be needed to ensure that the desired number
       of workers will process the distributed workload.

   DHT Routing Options
       There are two important options for GET and PUT requests:

       GNUNET_DHT_RO_DEMULITPLEX_EVERYWHERE This option means that all
              peers should process the request, even if their peer ID is not closest to the  key.
              For  a  PUT  request, this means that all peers that a request traverses may make a
              copy of the data. Similarly for a GET request, all peers  will  check  their  local
              database  for a result.  Setting this option can thus significantly improve caching
              and reduce bandwidth consumption — at the expense of a larger DHT database.  If  in
              doubt, we recommend that this option should be used.

       GNUNET_DHT_RO_RECORD_ROUTE This option instructs the DHT to record
              the  path  that  a  GET or a PUT request is taking through the overlay network. The
              resulting paths are then returned to the application with  the  respective  result.
              This  allows  the receiver of a result to construct a path to the originator of the
              data, which might then be used for routing. Naturally, setting this option requires
              additional  bandwidth  and  disk space, so applications should only set this if the
              paths are needed by the application logic.

       GNUNET_DHT_RO_FIND_PEER This option is an internal option used by
              the DHT’s peer discovery mechanism and should not be used by applications.

       GNUNET_DHT_RO_BART This option is currently not implemented. It may
              in the future offer performance improvements for clique topologies.

   The DHT Client-Service Protocol
   PUTting data into the DHT
       To store (PUT) data into the DHT, the client sends a struct GNUNET_DHT_ClientPutMessage to
       the  service.  This  message  specifies  the  block  type,  routing  options,  the desired
       replication level, the expiration time,  key,  value  and  a  64-bit  unique  ID  for  the
       operation. The service responds with a struct GNUNET_DHT_ClientPutConfirmationMessage with
       the same 64-bit unique ID. Note that the service sends the confirmation as soon as it  has
       locally processed the PUT request. The PUT may still be propagating through the network at
       this time.

       In the future, we may want to change this to provide (limited) feedback to the client, for
       example  if we detect that the PUT operation had no effect because the same key-value pair
       was already stored in the DHT.  However, changing this would also require additional state
       and messages in the P2P interaction.

   GETting data from the DHT
       To retrieve (GET) data from the DHT, the client sends a struct GNUNET_DHT_ClientGetMessage
       to  the  service.  The  message  specifies  routing  options,  a  replication  level  (for
       replicating  the  GET,  not  the content), the desired block type, the key, the (optional)
       extended query and unique 64-bit request ID.

       Additionally,     the     client     may     send      any      number      of      struct
       GNUNET_DHT_ClientGetResultSeenMessages to notify the service about results that the client
       is already aware of. These messages consist of the  key,  the  unique  64-bit  ID  of  the
       request,  and an arbitrary number of hash codes over the blocks that the client is already
       aware of. As messages are restricted to 64k, a client that already knows more than about a
       thousand  blocks  may need to send several of these messages. Naturally, the client should
       transmit these messages as quickly as possible after the original GET  request  such  that
       the DHT can filter those results in the network early on. Naturally, as these messages are
       sent after the original request, it is conceivable that the DHT service may return  blocks
       that match those already known to the client anyway.

       In response to a GET request, the service will send struct GNUNET_DHT_ClientResultMessages
       to the client. These messages contain the block type, expiration, key, unique  ID  of  the
       request and of course the value (a block). Depending on the options set for the respective
       operations, the replies may also contain the path the GET and/or the PUT took through  the
       network.

       A  client  can  stop  receiving  replies  either  by  disconnecting or by sending a struct
       GNUNET_DHT_ClientGetStopMessage which must contain the key and the 64-bit unique ID of the
       original  request. Using an explicit "stop" message is more common as this allows a client
       to run many concurrent GET operations over the same connection with the DHT service —  and
       to stop them individually.

   Monitoring the DHT
       To  begin monitoring, the client sends a struct GNUNET_DHT_MonitorStartStop message to the
       DHT service. In this message, flags can be set to enable (or disable) monitoring  of  GET,
       PUT and RESULT messages that pass through a peer. The message can also restrict monitoring
       to a particular block type or a particular  key.  Once  monitoring  is  enabled,  the  DHT
       service    will    notify   the   client   about   any   matching   event   using   struct
       GNUNET_DHT_MonitorGetMessages for GET events, struct GNUNET_DHT_MonitorPutMessage for  PUT
       events  and  struct  GNUNET_DHT_MonitorGetRespMessage  for RESULTs. Each of these messages
       contains all of the information about the event.

   The DHT Peer-to-Peer Protocol
   Routing GETs or PUTs
       When routing GETs or PUTs, the DHT service selects a suitable  subset  of  neighbours  for
       forwarding.  The  exact  number  of  neighbours can be zero or more and depends on the hop
       counter of the query (initially zero) in  relation  to  the  (log  of)  the  network  size
       estimate,  the desired replication level and the peer’s connectivity. Depending on the hop
       counter and our network size estimate, the selection of the peers maybe randomized  or  by
       proximity  to  the  key.  Furthermore,  requests include a set of peers that a request has
       already traversed; those peers are also excluded from the selection.

   PUTting data into the DHT
       To  PUT  data  into  the  DHT,  the  service  sends  a  struct  PeerPutMessage   of   type
       GNUNET_MESSAGE_TYPE_DHT_P2P_PUT  to  the  respective  neighbour.  In addition to the usual
       information about the content (type, routing options, desired replication  level  for  the
       content,  expiration  time, key and value), the message contains a fixed-size Bloom filter
       with information about which peers (may) have already seen this request. This Bloom filter
       is  used  to ensure that DHT messages never loop back to a peer that has already processed
       the request. Additionally, the message includes the current hop counter and, depending  on
       the  routing  options, the message may include the full path that the message has taken so
       far.  The Bloom filter should already contain the identity of the previous  hop;  however,
       the  path  should  not  include  the  identity of the previous hop and the receiver should
       append the identity of the sender to the path, not its  own  identity  (this  is  done  to
       reduce bandwidth).

   GETting data from the DHT
       A    peer   can   search   the   DHT   by   sending   struct   PeerGetMessages   of   type
       GNUNET_MESSAGE_TYPE_DHT_P2P_GET to other peers. In addition to the usual information about
       the request (type, routing options, desired replication level for the request, the key and
       the extended query), a GET request also contains a hop counter, a Bloom  filter  over  the
       peers  that  have  processed  the request already and depending on the routing options the
       full path traversed by the GET. Finally, a GET request  includes  a  variable-size  second
       Bloom  filter  and  a  so-called  Bloom filter mutator value which together indicate which
       replies the sender has already seen. During the lookup, each block that matches they block
       type,  key  and  extended  query  is  additionally  subjected to a test against this Bloom
       filter. The block plugin is expected to take the hash of the block and combine it with the
       mutator  value  and  check if the result is not yet in the Bloom filter. The originator of
       the query will from time to time modify the mutator to (eventually) allow  false-positives
       filtered by the Bloom filter to be returned.

       Peers  that  receive a GET request perform a local lookup (depending on their proximity to
       the key and the query options) and forward the request to other peers. They then  remember
       the  request  (including  the  Bloom  filter for blocking duplicate results) and when they
       obtain  a  matching,  non-filtered   response   a   struct   PeerResultMessage   of   type
       GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT is forwarded to the previous hop.  Whenever a result is
       forwarded, the block plugin is used to update the Bloom filter accordingly, to ensure that
       the  same  result  is  never  forwarded  more  than  once.  The DHT service may also cache
       forwarded  results  locally  if  the  "CACHE_RESULTS"  option  is  set  to  "YES"  in  the
       configuration.

       [R5N2011]
            https://bib.gnunet.org/date.html#R5N

   REGEX  Service discovery using regular expressions
       Using  the  REGEX  subsystem, you can discover peers that offer a particular service using
       regular  expressions.  The  peers  that  offer  a  service  specify  it  using  a  regular
       expressions.  Peers  that  want  to  patronize  a service search using a string. The REGEX
       subsystem will then use the DHT to return a set of matching offerers to the patrons.

       For the technical details, we have Max’s defense talk and Max’s Master’s thesis.

       NOTE:
          An additional publication is under preparation and available to team members (in Git).

   Todo
       Missing links to Max’s talk and Master’s thesis

   How to run the regex profiler
       The gnunet-regex-profiler can be used to profile the usage of mesh/regex for a  given  set
       of regular expressions and strings. Mesh/regex allows you to announce your peer ID under a
       certain regex and search for peers  matching  a  particular  regex  using  a  string.  See
       szengel2012ms for a full introduction.

       First  of  all,  the  regex  profiler  uses  GNUnet testbed, thus all the implications for
       testbed also apply to the regex profiler (for example you need password-less ssh login  to
       the machines listed in your hosts file).

       Configuration

       Moreover,  an  appropriate  configuration  file  is needed. In the following paragraph the
       important details are highlighted.

       Announcing  of  the  regular  expressions  is  done  by  the  gnunet-daemon-regexprofiler,
       therefore  you have to make sure it is started, by adding it to the START_ON_DEMAND set of
       ARM:

          [regexprofiler]
          START_ON_DEMAND = YES

       Furthermore you have to specify the location of the binary:

          [regexprofiler]
          # Location of the gnunet-daemon-regexprofiler binary.
          BINARY = /home/szengel/gnunet/src/mesh/.libs/gnunet-daemon-regexprofiler
          # Regex prefix that will be applied to all regular expressions and
          # search string.
          REGEX_PREFIX = "GNVPN-0001-PAD"

       When running the profiler with a large scale deployment, you probably want to  reduce  the
       workload of each peer. Use the following options to do this.

          [dht]
          # Force network size estimation
          FORCE_NSE = 1

          [dhtcache]
          DATABASE = heap
          # Disable RC-file for Bloom filter? (for benchmarking with limited IO
          # availability)
          DISABLE_BF_RC = YES
          # Disable Bloom filter entirely
          DISABLE_BF = YES

          [nse]
          # Minimize proof-of-work CPU consumption by NSE
          WORKBITS = 1

       Options

       To  finally  run  the profiler some options and the input data need to be specified on the
       command line.

          gnunet-regex-profiler -c config-file -d log-file -n num-links \
          -p path-compression-length -s search-delay -t matching-timeout \
          -a num-search-strings hosts-file policy-dir search-strings-file

       Where...

       • ... config-file means the configuration file created earlier.

       • ... log-file is the file where to write statistics output.

       • ... num-links indicates the number of random links between started peers.

       • ... path-compression-length is the maximum path compression length in the DFA.

       • ... search-delay time to wait between peers  finished  linking  and  starting  to  match
         strings.

       • ... matching-timeout timeout after which to cancel the searching.

       • ... num-search-strings number of strings in the search-strings-file.

       • ...  the  hosts-file should contain a list of hosts for the testbed, one per line in the
         following format:

         • user@host_ip:port

       • ... the policy-dir is a folder containing text files  containing  one  or  more  regular
         expressions.  A peer is started for each file in that folder and the regular expressions
         in the corresponding file are announced by this peer.

       • ... the search-strings-file is a text file containing search strings, one in each line.

       You can create regular expressions and search strings for every AS in the  Internet  using
       the  attached scripts. You need one of the CAIDA routeviews prefix2as data files for this.
       Run

          create_regex.py <filename> <output path>

       to create the regular expressions and

          create_strings.py <input path> <outfile>

       to create a search strings file from the previously created regular expressions.

   CADET  Confidential Ad-hoc Decentralized End-to-end Transport
       The CADET subsystem in GNUnet is responsible for secure end-to-end communications  between
       nodes  in  the  GNUnet overlay network. CADET builds on the CORE subsystem, which provides
       for the link-layer communication, by adding routing, forwarding, and  additional  security
       to  the  connections.  CADET  offers  the  same  cryptographic services as CORE, but on an
       end-to-end level. This is done so peers retransmitting traffic on behalf  of  other  peers
       cannot access the payload data.

       • CADET  provides  confidentiality  with  so-called  perfect forward secrecy; we use ECDHE
         powered by Curve25519 for the key exchange and then use symmetric encryption, encrypting
         with both AES-256 and Twofish

       • authentication  is achieved by signing the ephemeral keys using Ed25519, a deterministic
         variant of ECDSA

       • integrity protection (using SHA-512 to do encrypt-then-MAC, although only 256  bits  are
         sent to reduce overhead)

       • replay  protection  (using  nonces, timestamps, challenge-response, message counters and
         ephemeral keys)

       • liveness (keep-alive messages, timeout)

       Additional to the CORE-like security benefits, CADET offers other properties that make  it
       a more universal service than CORE.

       • CADET  can establish channels to arbitrary peers in GNUnet. If a peer is not immediately
         reachable, CADET will find a path through the network and ask other peers to  retransmit
         the traffic on its behalf.

       • CADET  offers  (optional)  reliability  mechanisms.  In  a  reliable  channel traffic is
         guaranteed to arrive complete, unchanged and in-order.

       • CADET takes care of flow and congestion control mechanisms, not allowing the  sender  to
         send more traffic than the receiver or the network are able to process.

   libgnunetcadet
       The  CADET  API  (defined  in  gnunet_cadet_service.h)  is  the  messaging API used by P2P
       applications built using GNUnet. It provides applications the ability to send and  receive
       encrypted  messages  to  any peer participating in GNUnet. The API is heavily based on the
       CORE API.

       CADET delivers messages to other peers in "channels". A channel is a permanent  connection
       defined  by  a  destination  peer  (identified  by  its  public  key)  and  a port number.
       Internally, CADET tunnels all channels towards a destination peer using  one  session  key
       and relays the data on multiple "connections", independent from the channels.

       Each  channel  has  optional  parameters,  the  most important being the reliability flag.
       Should a message get lost on TRANSPORT/CORE  level,  if  a  channel  is  created  with  as
       reliable,  CADET  will  retransmit  the  lost  message  and  deliver  it  in  order to the
       destination application.

       GNUNET_CADET_connect

       To communicate with other peers using CADET, it is  necessary  to  first  connect  to  the
       service  using  GNUNET_CADET_connect.  This  function  takes several parameters in form of
       callbacks, to allow the client to react to  various  events,  like  incoming  channels  or
       channels that terminate, as well as specify a list of ports the client wishes to listen to
       (at the moment it is not possible to start listening on further ports once connected,  but
       nothing  prevents  a  client to connect several times to CADET, even do one connection per
       listening port). The function returns a handle which  has  to  be  used  for  any  further
       interaction with the service.

       GNUNET_CADET_channel_create

       To  connect  to  a  remote  peer,  a  client  has  to call the GNUNET_CADET_channel_create
       function. The most important parameters given are the remote peer’s  identity  (it  public
       key)  and  a  port,  which  specifies  which application on the remote peer to connect to,
       similar to TCP/UDP ports. CADET will  then  find  the  peer  in  the  GNUnet  network  and
       establish  the  proper  low-level connections and do the necessary key exchanges to assure
       and    authenticated,    secure     and     verified     communication.     Similar     to
       GNUNET_CADET_connect,GNUNET_CADET_create_channel  returns  a  handle  to interact with the
       created channel.

       GNUNET_CADET_notify_transmit_ready

       For  every   message   the   client   wants   to   send   to   the   remote   application,
       GNUNET_CADET_notify_transmit_ready  must  be  called,  indicating the channel on which the
       message should be sent and the size of the message (but not  the  message  itself!).  Once
       CADET  is  ready  to  send  the  message, the provided callback will fire, and the message
       contents are provided to this callback.

       Please note the CADET does not provide an explicit  notification  of  when  a  channel  is
       connected.  In  loosely connected networks, like big wireless mesh networks, this can take
       several seconds, even minutes in the worst case. To be alerted when a channel is online, a
       client      can      call     GNUNET_CADET_notify_transmit_ready     immediately     after
       GNUNET_CADET_create_channel. When the callback is activated, it means that the channel  is
       online. The callback can give 0 bytes to CADET if no message is to be sent, this is OK.

       GNUNET_CADET_notify_transmit_cancel

       If  a  transmission was requested but before the callback fires it is no longer needed, it
       can be canceled with  GNUNET_CADET_notify_transmit_ready_cancel,  which  uses  the  handle
       given back by GNUNET_CADET_notify_transmit_ready. As in the case of CORE, only one message
       can be requested at a time: a  client  must  not  call  GNUNET_CADET_notify_transmit_ready
       again until the callback is called or the request is canceled.

       GNUNET_CADET_channel_destroy

       When  a channel is no longer needed, a client can call GNUNET_CADET_channel_destroy to get
       rid of it. Note that CADET will try to transmit all pending traffic before  notifying  the
       remote  peer  of the destruction of the channel, including retransmitting lost messages if
       the channel was reliable.

       Incoming channels, channels being closed by the remote peer, and traffic on  any  incoming
       or outgoing channels are given to the client when CADET executes the callbacks given to it
       at the time of GNUNET_CADET_connect.

       GNUNET_CADET_disconnect

       Finally,  when  an  application  no  longer  wants  to   use   CADET,   it   should   call
       GNUNET_CADET_disconnect,  but  first all channels and pending transmissions must be closed
       (otherwise CADET will complain).

   RPS  Random peer sampling
       In literature, Random Peer Sampling (RPS) refers to the problem of  reliably  [1]  drawing
       random samples from an unstructured p2p network.

       Doing  so  in  a  reliable  manner  is not only hard because of inherent problems but also
       because of possible malicious peers that could try to bias the selection.

       It is useful for all kind of gossip protocols that require the selection of  random  peers
       in  the  whole network like gathering statistics, spreading and aggregating information in
       the network, load balancing and overlay topology management.

       The approach chosen in the RPS service implementation in GNUnet follows the Brahms design.

       The current state is "work in progress". There are a lot of things that need to  be  done,
       primarily finishing the experimental evaluation and a re-design of the API.

       The  abstract  idea is to subscribe to connect to/start the RPS service and request random
       peers that will be returned when they represent a random selection from the whole  network
       with high probability.

       An  additional  feature  to the original Brahms-design is the selection of sub-groups: The
       GNUnet implementation of RPS enables clients to ask for random peers from a group that  is
       defined  by a common shared secret.  (The secret could of course also be public, depending
       on the use-case.)

       Another addition to the original  protocol  was  made:  The  sampler  mechanism  that  was
       introduced  in  Brahms  was  slightly  adapted  and  used to actually sample the peers and
       returned to the client. This  is  necessary  as  the  original  design  only  keeps  peers
       connected  to random other peers in the network. In order to return random peers to client
       requests independently random, they cannot be drawn from the connected peers. The  adapted
       sampler makes sure that each request for random peers is independent from the others.

   Brahms
       The  high-level  concept  of  Brahms  is two-fold: Combining push-pull gossip with locally
       fixing a  assumed  bias  using  cryptographic  min-wise  permutations.  The  central  data
       structure  is  the view - a peer’s current local sample. This view is used to select peers
       to push to and pull from. This simple mechanism can be  biased  easily.  For  this  reason
       Brahms ‘fixes’ the bias by using the so-called sampler. A data structure that takes a list
       of elements as input and outputs a random one of them independently of  the  frequency  in
       the  input set. Both an element that was put into the sampler a single time and an element
       that was put into it a million times have the same probability of being the  output.  This
       is  achieved  with exploiting min-wise independent permutations. In the RPS service we use
       HMACs: On the initialisation of a sampler element, a key is  chosen  at  random.  On  each
       input the HMAC with the random key is computed. The sampler element keeps the element with
       the minimal HMAC.

       In order to fix the bias in the view, a fraction of the elements in the view  are  sampled
       through the sampler from the random stream of peer IDs.

       According  to  the  theoretical  analysis  of  Bortnikov  et al. this suffices to keep the
       network connected and having random peers in the view.

       [1]  "Reliable" in this context means having no bias, neither spatial, nor  temporal,  nor
            through malicious activity.

   Peer-to-Peer Set Operations
       Many applications

   SET  Peer to peer set operations (Deprecated)
       NOTE:
          The  SET  subsystem  is  in  process of being replaced by the SETU and SETI subsystems,
          which provide basically the same functionality, just using  two  different  subsystems.
          SETI and SETU should be used for new code.

       The SET service implements efficient set operations between two peers over a CADET tunnel.
       Currently, set union and set intersection are the only supported operations. Elements of a
       set consist of an element type and arbitrary binary data. The size of an element’s data is
       limited to around 62 KB.

   Local Sets
       Sets created by a local client can be modified and reused for multiple operations. As each
       set  operation  requires  potentially  expensive special auxiliary data to be computed for
       each element of a set, a set can only participate in one type  of  set  operation  (either
       union  or  intersection).   The  type  of  a set is determined upon its creation. If a the
       elements of a set are needed for an operation of  a  different  type,  all  of  the  set’s
       element must be copied to a new set of appropriate type.

   Set Modifications
       Even  when  set  operations  are  active,  one  can add to and remove elements from a set.
       However, these changes will only be visible to operations that have been created after the
       changes  have  taken  place.  That is, every set operation only sees a snapshot of the set
       from the time the operation was started. This mechanism is not implemented by copying  the
       whole set, but by attaching generation information to each element and operation.

   Set Operations
       Set operations can be started in two ways: Either by accepting an operation request from a
       remote peer, or by requesting a set operation from  a  remote  peer.  Set  operations  are
       uniquely identified by the involved peers, an application id and the operation type.

       The client is notified of incoming set operations by set listeners. A set listener listens
       for incoming operations of a specific operation type and application id. Once notified  of
       an  incoming set request, the client can accept the set request (providing a local set for
       the operation) or reject it.

   Result Elements
       The SET service has three result modes that determine how an  operation’s  result  set  is
       delivered to the client:

       • Full  Result  Set.  All elements of set resulting from the set operation are returned to
         the client.

       • Added Elements. Only elements that result from the operation and are not already in  the
         local  peer’s  set  are  returned. Note that for some operations (like set intersection)
         this result mode will never return any elements. This can be useful if only  the  remove
         peer is actually interested in the result of the set operation.

       • Removed  Elements. Only elements that are in the local peer’s initial set but not in the
         operation’s result set are returned. Note that for some operations (like set union) this
         result  mode  will never return any elements. This can be useful if only the remove peer
         is actually interested in the result of the set operation.

   libgnunetset
   Sets
       New sets are created with GNUNET_SET_create. Both the local peer’s configuration (as  each
       set  has  its  own  client  connection)  and the operation type must be specified. The set
       exists until either the client calls GNUNET_SET_destroy or the client’s connection to  the
       service  is  disrupted.  In the latter case, the client is notified by the return value of
       functions dealing with sets. This return value must always be checked.

       Elements are added and removed with GNUNET_SET_add_element and GNUNET_SET_remove_element.

   Listeners
       Listeners are created with GNUNET_SET_listen. Each time time a remote peer suggests a  set
       operation  with  an  application id and operation type matching a listener, the listener’s
       callback is invoked.  The client then must synchronously call either GNUNET_SET_accept  or
       GNUNET_SET_reject.  Note  that  the  operation  will not be started until the client calls
       GNUNET_SET_commit (see Section "Supplying a Set").

   Operations
       Operations to be initiated by the local peer are  created  with  GNUNET_SET_prepare.  Note
       that  the  operation  will  not  be  started until the client calls GNUNET_SET_commit (see
       Section "Supplying a Set").

   Supplying a Set
       To create symmetry between the two  ways  of  starting  a  set  operation  (accepting  and
       initiating it), the operation handles returned by GNUNET_SET_accept and GNUNET_SET_prepare
       do not yet have a set to operate on, thus they can not do any work yet.

       The client must call  GNUNET_SET_commit  to  specify  a  set  to  use  for  an  operation.
       GNUNET_SET_commit may only be called once per set operation.

   The Result Callback
       Clients  must  specify both a result mode and a result callback with GNUNET_SET_accept and
       GNUNET_SET_prepare. The result callback with a status indicating either  that  an  element
       was  received,  or  the  operation failed or succeeded. The interpretation of the received
       element depends on the result mode. The callback needs to know which  result  mode  it  is
       used in, as the arguments do not indicate if an element is part of the full result set, or
       if it is in the difference between the original set and the final set.

   The SET Client-Service Protocol
   Creating Sets
       For each set of a client, there exists a  client  connection  to  the  service.  Sets  are
       created  by  sending  the  GNUNET_SERVICE_SET_CREATE message over a new client connection.
       Multiple operations for one set are  multiplexed  over  one  client  connection,  using  a
       request id supplied by the client.

   Listeners
       Each   listener   also   requires   a   separate   client   connection.   By  sending  the
       GNUNET_SERVICE_SET_LISTEN message, the client notifies the service of the  application  id
       and  operation  type  it is interested in. A client rejects an incoming request by sending
       GNUNET_SERVICE_SET_REJECT on the listener’s client connection. In contrast, when accepting
       an incoming request, a GNUNET_SERVICE_SET_ACCEPT message must be sent over the set that is
       supplied for the set operation.

   Initiating Operations
       Operations with remote  peers  are  initiated  by  sending  a  GNUNET_SERVICE_SET_EVALUATE
       message  to the service. The client connection that this message is sent by determines the
       set to use.

   Modifying Sets
       Sets are modified with the GNUNET_SERVICE_SET_ADD and GNUNET_SERVICE_SET_REMOVE messages.

   Results and Operation Status
       The service notifies the client of result elements and success/failure of a set  operation
       with the GNUNET_SERVICE_SET_RESULT message.

   Iterating Sets
       All  elements  of  a  set can be requested by sending GNUNET_SERVICE_SET_ITER_REQUEST. The
       server  responds  with  GNUNET_SERVICE_SET_ITER_ELEMENT  and  eventually  terminates   the
       iteration  with GNUNET_SERVICE_SET_ITER_DONE. After each received element, the client must
       send GNUNET_SERVICE_SET_ITER_ACK. Note that only one set iteration may be active for a set
       at any given time.

   The SET Intersection Peer-to-Peer Protocol
       The    intersection    protocol    operates    over    CADET    and    starts    with    a
       GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST  being  sent  by  the  peer  initiating  the
       operation  to  the peer listening for inbound requests. It includes the number of elements
       of the initiating peer, which is used to decide which side will send a Bloom filter first.

       The listening peer checks if the operation type and application identifier are  acceptable
       for  its  current  state.  If not, it responds with a GNUNET_MESSAGE_TYPE_SET_RESULT and a
       status of GNUNET_SET_STATUS_FAILURE (and terminates the CADET channel).

       If   the   application   accepts   the   request,    the    listener    sends    back    a
       GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO  if  it has more elements in the set
       than the client. Otherwise, it immediately starts with the Bloom filter exchange.  If  the
       initiator  receives  a  GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO response, it
       beings the Bloom filter exchange, unless the set size is indicated to be  zero,  in  which
       case the intersection is considered finished after just the initial handshake.

   The Bloom filter exchange
       In this phase, each peer transmits a Bloom filter over the remaining keys of the local set
       to the  other  peer  using  a  GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF  message.  This
       message  additionally includes the number of elements left in the sender’s set, as well as
       the XOR over all of the keys in that set.

       The number of bits ‘k’ set per element in the Bloom filter  is  calculated  based  on  the
       relative  size  of  the  two sets. Furthermore, the size of the Bloom filter is calculated
       based on ‘k’ and the number of elements in the set to maximize the amount of data filtered
       per  byte  transmitted  on  the  wire  (while  avoiding  an  excessively  high  number  of
       iterations).

       The receiver of the message removes all elements from its local set that do not  pass  the
       Bloom  filter test. It then checks if the set size of the sender and the XOR over the keys
       match   what   is   left   of   its   own    set.    If    they    do,    it    sends    a
       GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_DONE  back to indicate that the latest set is the
       final result. Otherwise, the receiver starts another Bloom filter  exchange,  except  this
       time as the sender.

   Salt
       Bloomfilter  operations  are  probabilistic:  With  some non-zero probability the test may
       incorrectly say an element is in the set, even though it is not.

       To mitigate this problem, the intersection  protocol  iterates  exchanging  Bloom  filters
       using  a  different random 32-bit salt in each iteration (the salt is also included in the
       message). With different salts, set operations may fail for  different  elements.  Merging
       the results from the executions, the probability of failure drops to zero.

       The  iterations terminate once both peers have established that they have sets of the same
       size, and where the XOR over all keys computes the same 512-bit value (leaving  a  failure
       probability of 2-511).

   The SET Union Peer-to-Peer Protocol
       The  SET  union protocol is based on Eppstein’s efficient set reconciliation without prior
       context. You should read this paper first if you want to understand the protocol.

   Todo
       Link to Eppstein’s paper!

       The    union    protocol     operates     over     CADET     and     starts     with     a
       GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST  being  sent  by  the  peer  initiating  the
       operation to the peer listening for inbound requests. It includes the number  of  elements
       of the initiating peer, which is currently not used.

       The  listening peer checks if the operation type and application identifier are acceptable
       for its current state. If not, it responds with  a  GNUNET_MESSAGE_TYPE_SET_RESULT  and  a
       status of GNUNET_SET_STATUS_FAILURE (and terminates the CADET channel).

       If  the  application accepts the request, it sends back a strata estimator using a message
       of type GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE. The initiator evaluates the strata estimator
       and    initiates    the    exchange    of    invertible    Bloom    filters,   sending   a
       GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.

       During the IBF exchange, if the receiver cannot invert  the  Bloom  filter  or  detects  a
       cycle,  it sends a larger IBF in response (up to a defined maximum limit; if that limit is
       reached, the operation fails). Elements decoded while processing the IBF  are  transmitted
       to  the other peer using GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, or requested from the other
       peer using GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS messages, depending  on  the  sign
       observed     during     decoding     of     the     IBF.     Peers     respond     to    a
       GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS message with  the  respective  element  in  a
       GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS  message. If the IBF fully decodes, the peer responds
       with    a    GNUNET_MESSAGE_TYPE_SET_UNION_P2P_DONE    message    instead    of    another
       GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF.

       All  Bloom  filter  operations use a salt to mingle keys before hashing them into buckets,
       such that future iterations have a fresh chance  of  succeeding  if  they  failed  due  to
       collisions before.

   SETI  Peer to peer set intersections
       The  SETI  service  implements  efficient  set intersection between two peers over a CADET
       tunnel. Elements of a set consist of an element type and arbitrary binary data.  The  size
       of an element’s data is limited to around 62 KB.

   Intersection Sets
       Sets  created by a local client can be modified (by adding additional elements) and reused
       for multiple operations. If elements are to be removed, a fresh set must be created by the
       client.

   Set Intersection Modifications
       Even  when  set  operations  are  active,  one  can add elements to a set.  However, these
       changes will only be visible to operations that have been created after the  changes  have
       taken  place.  That  is, every set operation only sees a snapshot of the set from the time
       the operation was started.  This mechanism is not implemented by copying  the  whole  set,
       but by attaching generation information to each element and operation.

   Set Intersection Operations
       Set operations can be started in two ways: Either by accepting an operation request from a
       remote peer, or by requesting a set operation from  a  remote  peer.  Set  operations  are
       uniquely identified by the involved peers, an application id and the operation type.

       The client is notified of incoming set operations by set listeners. A set listener listens
       for incoming operations of a specific operation type and application id. Once notified  of
       an  incoming set request, the client can accept the set request (providing a local set for
       the operation) or reject it.

   Intersection Result Elements
       The SET service has two result modes that determine  how  an  operation’s  result  set  is
       delivered to the client:

       • Return  intersection.  All  elements  of  set  resulting  from  the set intersection are
         returned to the client.

       • Removed Elements. Only elements that are in the local peer’s initial set but not in  the
         intersection are returned.

   libgnunetseti
   Intersection Set API
       New sets are created with GNUNET_SETI_create. Only the local peer’s configuration (as each
       set has its own client connection) must be provided.  The  set  exists  until  either  the
       client calls GNUNET_SET_destroy or the client’s connection to the service is disrupted. In
       the latter case, the client is notified by the return  value  of  functions  dealing  with
       sets. This return value must always be checked.

       Elements are added with GNUNET_SET_add_element.

   Intersection Listeners
       Listeners  are created with GNUNET_SET_listen. Each time time a remote peer suggests a set
       operation with an application id and operation type matching a  listener,  the  listener’s
       callback  is invoked.  The client then must synchronously call either GNUNET_SET_accept or
       GNUNET_SET_reject. Note that the operation will not be  started  until  the  client  calls
       GNUNET_SET_commit (see Section "Supplying a Set").

   Intersection Operations
       Operations  to  be  initiated  by the local peer are created with GNUNET_SET_prepare. Note
       that the operation will not be started  until  the  client  calls  GNUNET_SET_commit  (see
       Section "Supplying a Set").

   Supplying a Set for Intersection
       To  create  symmetry  between  the  two  ways  of  starting a set operation (accepting and
       initiating it), the operation handles returned by GNUNET_SET_accept and GNUNET_SET_prepare
       do not yet have a set to operate on, thus they can not do any work yet.

       The  client  must  call  GNUNET_SET_commit  to  specify  a  set  to  use for an operation.
       GNUNET_SET_commit may only be called once per set operation.

   The Intersection Result Callback
       Clients must specify both a result mode and a result callback with  GNUNET_SET_accept  and
       GNUNET_SET_prepare.  The  result  callback with a status indicating either that an element
       was received, or the operation failed or succeeded. The  interpretation  of  the  received
       element  depends  on  the  result mode. The callback needs to know which result mode it is
       used in, as the arguments do not indicate if an element is part of the full result set, or
       if it is in the difference between the original set and the final set.

   The SETI Client-Service Protocol
   Creating Intersection Sets
       For  each  set  of  a  client,  there  exists a client connection to the service. Sets are
       created by sending the GNUNET_SERVICE_SETI_CREATE message over a  new  client  connection.
       Multiple  operations  for  one  set  are  multiplexed  over one client connection, using a
       request id supplied by the client.

   Listeners for Intersection
       Each  listener  also   requires   a   separate   client   connection.   By   sending   the
       GNUNET_SERVICE_SETI_LISTEN  message, the client notifies the service of the application id
       and operation type it is interested in. A client rejects an incoming  request  by  sending
       GNUNET_SERVICE_SETI_REJECT   on  the  listener’s  client  connection.  In  contrast,  when
       accepting an incoming request, a GNUNET_SERVICE_SETI_ACCEPT  message  must  be  sent  over
       the set that is supplied for the set operation.

   Initiating Intersection Operations
       Operations  with  remote  peers  are  initiated  by sending a GNUNET_SERVICE_SETI_EVALUATE
       message to the service. The client connection that this message is sent by determines  the
       set to use.

   Modifying Intersection Sets
       Sets are modified with the GNUNET_SERVICE_SETI_ADD message.

   Intersection Results and Operation Status
       The  service notifies the client of result elements and success/failure of a set operation
       with the GNUNET_SERVICE_SETI_RESULT message.

   The SETI Intersection Peer-to-Peer Protocol
       The    intersection    protocol    operates    over    CADET    and    starts    with    a
       GNUNET_MESSAGE_TYPE_SETI_P2P_OPERATION_REQUEST  being  sent  by  the  peer  initiating the
       operation to the peer listening for inbound requests. It includes the number  of  elements
       of the initiating peer, which is used to decide which side will send a Bloom filter first.

       The  listening peer checks if the operation type and application identifier are acceptable
       for its current state. If not, it responds with a  GNUNET_MESSAGE_TYPE_SETI_RESULT  and  a
       status of GNUNET_SETI_STATUS_FAILURE (and terminates the CADET channel).

       If    the    application    accepts    the    request,   the   listener   sends   back   a
       GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO if it has more elements  in  the  set  than  the
       client.  Otherwise, it immediately starts with the Bloom filter exchange. If the initiator
       receives a GNUNET_MESSAGE_TYPE_SETI_P2P_ELEMENT_INFO response, it beings the Bloom  filter
       exchange,  unless  the set size is indicated to be zero, in which case the intersection is
       considered finished after just the initial handshake.

   The Bloom filter exchange in SETI
       In this phase, each peer transmits a Bloom filter over the remaining keys of the local set
       to   the   other  peer  using  a  GNUNET_MESSAGE_TYPE_SETI_P2P_BF  message.  This  message
       additionally includes the number of elements left in the sender’s set, as well as the  XOR
       over all of the keys in that set.

       The  number  of  bits  ‘k’  set per element in the Bloom filter is calculated based on the
       relative size of the two sets. Furthermore, the size of the  Bloom  filter  is  calculated
       based on ‘k’ and the number of elements in the set to maximize the amount of data filtered
       per  byte  transmitted  on  the  wire  (while  avoiding  an  excessively  high  number  of
       iterations).

       The  receiver  of the message removes all elements from its local set that do not pass the
       Bloom filter test. It then checks if the set size of the sender and the XOR over the  keys
       match    what    is    left    of    its    own    set.   If   they   do,   it   sends   a
       GNUNET_MESSAGE_TYPE_SETI_P2P_DONE back to indicate  that  the  latest  set  is  the  final
       result.  Otherwise, the receiver starts another Bloom filter exchange, except this time as
       the sender.

   Intersection Salt
       Bloom filter operations are probabilistic: With some non-zero  probability  the  test  may
       incorrectly say an element is in the set, even though it is not.

       To  mitigate  this  problem,  the  intersection protocol iterates exchanging Bloom filters
       using a different random 32-bit salt in each iteration (the salt is also included  in  the
       message).  With  different  salts, set operations may fail for different elements. Merging
       the results from the executions, the probability of failure drops to zero.

       The iterations terminate once both peers have established that they have sets of the  same
       size,  and  where the XOR over all keys computes the same 512-bit value (leaving a failure
       probability of 2-511).

   SETU  Peer to peer set unions
       The SETU service implements efficient set union operations between two peers over a  CADET
       tunnel.  Elements  of a set consist of an element type and arbitrary binary data. The size
       of an element’s data is limited to around 62 KB.

   Union Sets
       Sets created by a local client can be modified (by adding additional elements) and  reused
       for multiple operations. If elements are to be removed, a fresh set must be created by the
       client.

   Set Union Modifications
       Even when set operations are active, one can  add  elements  to  a  set.   However,  these
       changes  will  only be visible to operations that have been created after the changes have
       taken place. That is, every set operation only sees a snapshot of the set  from  the  time
       the  operation  was  started.  This mechanism is not implemented by copying the whole set,
       but by attaching generation information to each element and operation.

   Set Union Operations
       Set operations can be started in two ways: Either by accepting an operation request from a
       remote  peer,  or  by  requesting  a  set operation from a remote peer. Set operations are
       uniquely identified by the involved peers, an application id and the operation type.

       The client is notified of incoming set operations by set listeners. A set listener listens
       for  incoming operations of a specific operation type and application id. Once notified of
       an incoming set request, the client can accept the set request (providing a local set  for
       the operation) or reject it.

   Union Result Elements
       The  SET  service  has  three result modes that determine how an operation’s result set is
       delivered to the client:

       • Locally added Elements. Elements that are in the union but  not  already  in  the  local
         peer’s set are returned.

       • Remote  added  Elements.  Additionally, notify the client if the remote peer lacked some
         elements and thus also return to the local client those elements that we are sending  to
         the  remote peer to be added to its union. Obtaining these elements requires setting the
         GNUNET_SETU_OPTION_SYMMETRIC option.

   libgnunetsetu
   Union Set API
       New sets are created with GNUNET_SETU_create. Only the local peer’s configuration (as each
       set  has  its  own  client  connection)  must be provided. The set exists until either the
       client calls GNUNET_SETU_destroy or the client’s connection to the service  is  disrupted.
       In  the  latter case, the client is notified by the return value of functions dealing with
       sets. This return value must always be checked.

       Elements are added with GNUNET_SETU_add_element.

   Union Listeners
       Listeners are created with GNUNET_SETU_listen. Each time time a remote peer suggests a set
       operation  with  an  application id and operation type matching a listener, the listener’s
       callback is invoked.  The client then must synchronously call either GNUNET_SETU_accept or
       GNUNET_SETU_reject.  Note  that  the  operation will not be started until the client calls
       GNUNET_SETU_commit (see Section "Supplying a Set").

   Union Operations
       Operations to be initiated by the local peer are created  with  GNUNET_SETU_prepare.  Note
       that  the  operation  will  not  be started until the client calls GNUNET_SETU_commit (see
       Section "Supplying a Set").

   Supplying a Set for Union
       To create symmetry between the two  ways  of  starting  a  set  operation  (accepting  and
       initiating    it),    the   operation   handles   returned   by   GNUNET_SETU_accept   and
       GNUNET_SETU_prepare do not yet have a set to operate on, thus they can  not  do  any  work
       yet.

       The  client  must  call  GNUNET_SETU_commit  to  specify  a  set  to use for an operation.
       GNUNET_SETU_commit may only be called once per set operation.

   The Union Result Callback
       Clients must specify both a result mode and a result callback with GNUNET_SETU_accept  and
       GNUNET_SETU_prepare.  The  result callback with a status indicating either that an element
       was received, transmitted to the other peer (if this information was requested), or if the
       operation failed or ultimately succeeded.

   The SETU Client-Service Protocol
   Creating Union Sets
       For  each  set  of  a  client,  there  exists a client connection to the service. Sets are
       created by sending the GNUNET_SERVICE_SETU_CREATE message over a  new  client  connection.
       Multiple  operations  for  one  set  are  multiplexed  over one client connection, using a
       request id supplied by the client.

   Listeners for Union
       Each  listener  also   requires   a   separate   client   connection.   By   sending   the
       GNUNET_SERVICE_SETU_LISTEN  message, the client notifies the service of the application id
       and operation type it is interested in. A client rejects an incoming  request  by  sending
       GNUNET_SERVICE_SETU_REJECT   on  the  listener’s  client  connection.  In  contrast,  when
       accepting an incoming request, a GNUNET_SERVICE_SETU_ACCEPT  message  must  be  sent  over
       the set that is supplied for the set operation.

   Initiating Union Operations
       Operations  with  remote  peers  are  initiated  by sending a GNUNET_SERVICE_SETU_EVALUATE
       message to the service. The client connection that this message is sent by determines  the
       set to use.

   Modifying Union Sets
       Sets are modified with the GNUNET_SERVICE_SETU_ADD message.

   Union Results and Operation Status
       The  service notifies the client of result elements and success/failure of a set operation
       with the GNUNET_SERVICE_SETU_RESULT message.

   The SETU Union Peer-to-Peer Protocol
       The SET union protocol is based on Eppstein’s efficient set reconciliation  without  prior
       context. You should read this paper first if you want to understand the protocol.

   Todo
       Link to Eppstein’s paper!

       The     union     protocol     operates     over     CADET     and     starts    with    a
       GNUNET_MESSAGE_TYPE_SETU_P2P_OPERATION_REQUEST being  sent  by  the  peer  initiating  the
       operation  to  the peer listening for inbound requests. It includes the number of elements
       of the initiating peer, which is currently not used.

       The listening peer checks if the operation type and application identifier are  acceptable
       for  its  current  state. If not, it responds with a GNUNET_MESSAGE_TYPE_SETU_RESULT and a
       status of GNUNET_SETU_STATUS_FAILURE (and terminates the CADET channel).

       If the application accepts the request, it sends back a strata estimator using  a  message
       of  type GNUNET_MESSAGE_TYPE_SETU_P2P_SE. The initiator evaluates the strata estimator and
       initiates    the    exchange    of     invertible     Bloom     filters,     sending     a
       GNUNET_MESSAGE_TYPE_SETU_P2P_IBF.

       During  the  IBF  exchange,  if  the  receiver cannot invert the Bloom filter or detects a
       cycle, it sends a larger IBF in response (up to a defined maximum limit; if that limit  is
       reached,  the  operation fails). Elements decoded while processing the IBF are transmitted
       to the other peer using GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS, or requested from the other
       peer  using  GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS messages, depending on the sign
       observed    during     decoding     of     the     IBF.     Peers     respond     to     a
       GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENT_REQUESTS  message  with  the  respective element in a
       GNUNET_MESSAGE_TYPE_SETU_P2P_ELEMENTS  message.   If  the  IBF  fully  decodes,  the  peer
       responds   with   a   GNUNET_MESSAGE_TYPE_SETU_P2P_DONE   message   instead   of   another
       GNUNET_MESSAGE_TYPE_SETU_P2P_IBF.

       All Bloom filter operations use a salt to mingle keys before hashing  them  into  buckets,
       such  that  future  iterations  have  a  fresh  chance of succeeding if they failed due to
       collisions before.

   VPN and VPN Support
   GNS and GNS Support
       The GNU Name System is a secure and censorship-resistant alternative to  the  Domain  Name
       System (DNS) in common use for resolving domain names.

   GNS  the GNU Name System
       The  GNU  Name  System  (GNS)  is  a decentralized database that enables users to securely
       resolve names to values. Names can be used to identify other users (for example, in social
       networking),  or  network services (for example, VPN services running at a peer in GNUnet,
       or purely IP-based services on the Internet). Users interact  with  GNS  by  typing  in  a
       hostname  that ends in a top-level domain that is configured in the “GNS” section, matches
       an identity of the user or ends in a Base32-encoded public key.

       Videos giving an overview of most of the GNS and the motivations behind  it  is  available
       here  and  here.  The  remainder of this chapter targets developers that are familiar with
       high level concepts of GNS as presented in these talks.

   Todo
       Link to videos and GNS talks?

       GNS-aware applications should use the GNS resolver to obtain the respective  records  that
       are  stored under that name in GNS. Each record consists of a type, value, expiration time
       and flags.

       The type specifies the format of the value. Types below 65536  correspond  to  DNS  record
       types,  larger  values are used for GNS-specific records.  Applications can define new GNS
       record types by reserving a number and  implementing  a  plugin  (which  mostly  needs  to
       convert  the  binary value representation to a human-readable text format and vice-versa).
       The expiration time specifies how long the record is to be valid. The GNS API ensures that
       applications  are  only  given  non-expired values. The flags are typically irrelevant for
       applications, as GNS uses them internally to control visibility and validity of records.

       Records are stored along with a signature. The signature is generated  using  the  private
       key of the authoritative zone. This allows any GNS resolver to verify the correctness of a
       name-value mapping.

       Internally, GNS uses the NAMECACHE to cache information obtained  from  other  users,  the
       NAMESTORE  to  store information specific to the local users, and the DHT to exchange data
       between users. A plugin API is used to enable applications to define new GNS record types.

   libgnunetgns
       The GNS API itself is extremely simple. Clients first connect to  the  GNS  service  using
       GNUNET_GNS_connect.  They  can  then  perform  lookups  using  GNUNET_GNS_lookup or cancel
       pending lookups using GNUNET_GNS_lookup_cancel. Once finished,  clients  disconnect  using
       GNUNET_GNS_disconnect.

   Looking up records
       GNUNET_GNS_lookup takes a number of arguments:

       handle This is simply the GNS connection handle from
              GNUNET_GNS_connect.

       name The client needs to specify the name to
              be resolved. This can be any valid DNS or GNS hostname.

       zone The client
              needs to specify the public key of the GNS zone against which the resolution should
              be done. Note that a key must be provided, the  client  should  look  up  plausible
              values using its configuration, the identity service and by attempting to interpret
              the TLD as a base32-encoded public key.

       type This is the desired GNS or DNS record type
              to look for. While all records for the given name will be  returned,  this  can  be
              important  if  the  client  wants  to resolve record types that themselves delegate
              resolution, such as CNAME, PKEY or GNS2DNS.  Resolving a record  of  any  of  these
              types  will only work if the respective record type is specified in the request, as
              the GNS resolver will otherwise follow the delegation and return the  records  from
              the respective destination, instead of the delegating record.

       only_cached This argument should typically be set to
              GNUNET_NO. Setting it to GNUNET_YES disables resolution via the overlay network.

       shorten_zone_key If GNS encounters new names during resolution,
              their  respective  zones  can  automatically  be  learned and added to the "shorten
              zone". If this is desired, clients must pass the private key of the  shorten  zone.
              If NULL is passed, shortening is disabled.

       proc This argument identifies
              the  function  to call with the result. It is given proc_cls, the number of records
              found (possibly zero) and the array of the records as arguments. proc will only  be
              called once. After proc,> has been called, the lookup must no longer be canceled.

       proc_cls The closure for proc.

   Accessing the records
       The  libgnunetgnsrecord library provides an API to manipulate the GNS record array that is
       given to proc. In particular, it offers functions such  as  converting  record  values  to
       human-readable  strings  (and  back).   However, most libgnunetgnsrecord functions are not
       interesting to GNS client applications.

       For DNS records, the  libgnunetdnsparser  library  provides  functions  for  parsing  (and
       serializing) common types of DNS records.

   Creating records
       Creating  GNS  records  is  typically  done  by building the respective record information
       (possibly with the help of libgnunetgnsrecord and libgnunetdnsparser) and then  using  the
       libgnunetnamestore  to  publish  the  information.  The  GNS  API  is not involved in this
       operation.

   Future work
       In the future, we want to expand libgnunetgns to allow applications to observe  shortening
       operations  performed  during GNS resolution, for example so that users can receive visual
       feedback when this happens.

   libgnunetgnsrecord
       The libgnunetgnsrecord library is used to manipulate GNS records (in plaintext or in their
       encrypted  format).  Applications  mostly  interact  with  libgnunetgnsrecord by using the
       functions to convert GNS record values to strings or vice-versa, or to lookup a GNS record
       type  number  by  name  (or vice-versa). The library also provides various other functions
       that are mostly used internally within GNS, such as converting keys to names, checking for
       expiration,  encrypting  GNS  records  to  GNS  blocks, verifying GNS block signatures and
       decrypting GNS records from GNS blocks.

       We will now discuss the four commonly used functions of the  API. libgnunetgnsrecord  does
       not  perform  these  operations itself, but instead uses plugins to perform the operation.
       GNUnet includes plugins to support common DNS record types as well as standard GNS  record
       types.

   Value handling
       GNUNET_GNSRECORD_value_to_string  can  be used to convert the (binary) representation of a
       GNS record value to a human readable, 0-terminated UTF-8 string. NULL is returned  if  the
       specified record type is not supported by any available plugin.

       GNUNET_GNSRECORD_string_to_value  can be used to try to convert a human readable string to
       the respective (binary) representation of a GNS record value.

   Type handling
       GNUNET_GNSRECORD_typename_to_number can be used to obtain  the  numeric  value  associated
       with  a  given  typename.  For  example,  given  the typename "A" (for DNS A reocrds), the
       function will return the number 1. A list of common DNS record types is  here.  Note  that
       not all DNS record types are supported by GNUnet GNSRECORD plugins at this time.

       GNUNET_GNSRECORD_number_to_typename  can  be used to obtain the typename associated with a
       given numeric value. For example, given the type number 1, the function  will  return  the
       typename "A".

   GNS plugins
       Adding a new GNS record type typically involves writing (or extending) a GNSRECORD plugin.
       The plugin needs to implement  the  gnunet_gnsrecord_plugin.h  API  which  provides  basic
       functions  that  are needed by GNSRECORD to convert typenames and values of the respective
       record type to strings (and back).  These  gnsrecord  plugins  are  typically  implemented
       within  their  respective  subsystems.  Examples  for  such  plugins  can  be found in the
       GNSRECORD, GNS and CONVERSATION subsystems.

       The libgnunetgnsrecord library is then used to locate,  load  and  query  the  appropriate
       gnsrecord  plugin.  Which plugin is appropriate is determined by the record type (which is
       just a 32-bit integer). The libgnunetgnsrecord library loads all block  plugins  that  are
       installed  at  the  local peer and forwards the application request to the plugins. If the
       record type is not supported by the plugin, it should simply return an error code.

       The central functions of the block APIs (plugin  and  main  library)  are  the  same  four
       functions  for converting between values and strings, and typenames and numbers documented
       in the previous subsection.

   The GNS Client-Service Protocol
       The GNS client-service protocol consists of two simple messages, the  LOOKUP  message  and
       the  LOOKUP_RESULT. Each LOOKUP message contains a unique 32-bit identifier, which will be
       included in the corresponding response. Thus, clients can send  many  lookup  requests  in
       parallel and receive responses out-of-order. A LOOKUP request also includes the public key
       of the GNS zone, the desired record type  and  fields  specifying  whether  shortening  is
       enabled  or  networking  is  disabled. Finally, the LOOKUP message includes the name to be
       resolved.

       The response includes the number of records and  the  records  themselves  in  the  format
       created  by  GNUNET_GNSRECORD_records_serialize.  They  can  thus  be  deserialized  using
       GNUNET_GNSRECORD_records_deserialize.

   Hijacking the DNS-Traffic using gnunet-service-dns
       This section documents how the gnunet-service-dns (and the  gnunet-helper-dns)  intercepts
       DNS  queries  from  the  local system. This is merely one method for how we can obtain GNS
       queries. It is also  possible  to  change  resolv.conf  to  point  to  a  machine  running
       gnunet-dns2gns or to modify libc’s name system switch (NSS) configuration to include a GNS
       resolution plugin. The method described in this chapter is more of a last-ditch  catch-all
       approach.

       gnunet-service-dns  enables  intercepting  DNS traffic using policy based routing. We MARK
       every outgoing DNS-packet if it was not sent by our application. Using  a  second  routing
       table in the Linux kernel these marked packets are then routed through our virtual network
       interface and can thus be captured unchanged.

       Our application then reads the query and decides how to handle it. If  the  query  can  be
       addressed  via  GNS, it is passed to gnunet-service-gns and resolved internally using GNS.
       In the future, a reverse query for an address of the configured virtual network  could  be
       answered  with  records kept about previous forward queries. Queries that are not hijacked
       by some application using the DNS service will be sent  to  the  original  recipient.  The
       answer  to  the  query  will  always  be  sent back through the virtual interface with the
       original nameserver as source address.

   Network Setup Details
       The DNS interceptor adds the following rules to the Linux kernel:

          iptables -t mangle -I OUTPUT 1 -p udp --sport $LOCALPORT --dport 53 \
          -j ACCEPT iptables -t mangle -I OUTPUT 2 -p udp --dport 53 -j MARK \
          --set-mark 3 ip rule add fwmark 3 table2 ip route add default via \
          $VIRTUALDNS table2

   Todo
       FIXME: Rewrite to reflect display which is no longer content by  line  due  to  the  <  74
       characters limit.

       Line  1  makes  sure that all packets coming from a port our application opened beforehand
       ($LOCALPORT) will be routed normally. Line 2 marks every other packet to a DNS-Server with
       mark 3 (chosen arbitrarily). The third line adds a routing policy based on this mark 3 via
       the routing table.

   Importing DNS Zones into GNS
       This section discusses the challenges and problems faced when writing the Ascension  tool.
       It also takes a look at possible improvements in the future.

       Consider the following diagram that shows the workflow of Ascension:

       [image: ascension] [image]

       Further the interaction between components of GNUnet are shown in the diagram below:

       DNS Conversion .. _Conversions-between-DNS-and-GNS:

   Conversions between DNS and GNS
       The  differences  between  the  two  name  systems  lies  in the details and is not always
       transparent. For instance an SRV record is converted to a BOX record which  is  unique  to
       GNS.

       This is done by converting to a BOX record from an existing SRV record:

          # SRV
          # _service._proto.name. TTL class SRV priority weight port target
          _sip._tcp.example.com. 14000 IN SRV     0 0 5060 www.example.com.
          # BOX
          # TTL BOX flags port protocol recordtype priority weight port target
          14000 BOX n 5060 6 33 0 0 5060 www.example.com

       Other  records  that need to undergo such transformation is the MX record type, as well as
       the SOA record type.

       Transformation of a SOA record into GNS works as described in the following example.  Very
       important to note are the rname and mname keys.

          # BIND syntax for a clean SOA record
             IN SOA master.example.com. hostmaster.example.com. (
              2017030300 ; serial
              3600       ; refresh
              1800       ; retry
              604800     ; expire
              600 )      ; ttl
          # Recordline for adding the record
          $ gnunet-namestore -z example.com -a -n  -t SOA -V \
              rname=master.example.com mname=hostmaster.example.com  \
              2017030300,3600,1800,604800,600 -e 7200s

       The transformation of MX records is done in a simple way.

          # mail.example.com. 3600 IN MX 10 mail.example.com.
          $ gnunet-namestore -z example.com -n mail -R 3600 MX n 10,mail

       Finally,  one  of  the biggest struggling points were the NS records that are found in top
       level domain zones. The intended behaviour for those is to add GNS2DNS records  for  those
       so  that  gnunet-gns  can  resolve records for those domains on its own. Those require the
       values from DNS GLUE records, provided they are within the same zone.

       The following two examples show one record with a GLUE record and the other one  does  not
       have a GLUE record. This takes place in the ‘com’ TLD.

          # ns1.example.com 86400 IN A 127.0.0.1
          # example.com 86400 IN NS ns1.example.com.
          $ gnunet-namestore -z com -n example -R 86400 GNS2DNS n \
              example.com@127.0.0.1

          # example.com 86400 IN NS ns1.example.org.
          $ gnunet-namestore -z com -n example -R 86400 GNS2DNS n \
              example.com@ns1.example.org

       As  you  can  see, one of the GNS2DNS records has an IP address listed and the other one a
       DNS name. For the first one there is a GLUE record to do the translation directly and  the
       second one will issue another DNS query to figure out the IP of ns1.example.org.

       A  solution  was  found  by  creating a hierarchical zone structure in GNS and linking the
       zones using PKEY records to one another. This allows the resolution of the name servers to
       work within GNS while not taking control over unwanted zones.

       Currently the following record types are supported:

       • A

       • AAAA

       • CNAME

       • MX

       • NS

       • SRV

       • TXT

       This  is not due to technical limitations but rather a practical ones.  The problem occurs
       with DNSSEC enabled DNS zones. As records within those zones are signed periodically,  and
       every  new  signature  is  an  update to the zone, there are many revisions of zones. This
       results in a problem with bigger zones as there are lots of records that have been  signed
       again  but  no  major  changes. Also trying to add records that are unknown that require a
       different format take time as they cause a CLI call of the namestore. Furthermore  certain
       record  types  need  transformation  into  a GNS compatible format which, depending on the
       record type, takes more time.

       Further a blacklist was added to drop for instance  DNSSEC  related  records.  Also  if  a
       record  type  is neither in the white list nor the blacklist it is considered as a loss of
       data and a message is shown to the user.  This  helps  with  transparency  and  also  with
       contributing, as the not supported record types can then be added accordingly.

   DNS Zone Size
       Another  very  big  problem  exists with very large zones. When migrating a small zone the
       delay between adding of records and their expiry is negligible. However when working  with
       big zones that easily have more than a few million records this delay becomes a problem.

       Records  will start to expire well before the zone has finished migrating. This is usually
       not a problem but can cause a high CPU load when a peer is restarted and the records  have
       expired.

       A  good  solution has not been found yet. One of the idea that floated around was that the
       records should be added with the s (shadow) flag to keep the records  resolvable  even  if
       they  expired.  However  this would introduce the problem of how to detect if a record has
       been removed from the zone and would require deletion of said record(s).

       Another problem that still persists is how to refresh records. Expired records  are  still
       displayed  when  calling  gnunet-namestore  but do not resolve with gnunet-gns. Zonemaster
       will sign the expired records again and make sure that the records are still valid. With a
       recent change this was fixed as gnunet-gns to improve the suffix lookup which allows for a
       fast lookup even with thousands of local egos.

       Currently the pace of adding records in general is around 10 records per second. Crypto is
       the  upper limit for adding of records. The performance of your machine can be tested with
       the perf_crypto_* tools. There is still a big discrepancy between the  pace  of  Ascension
       and the theoretical limit.

       A performance metric for measuring improvements has not yet been implemented in Ascension.

   Performance
       The  performance when migrating a zone using the Ascension tool is limited by a handful of
       factors. First of all ascension is written in Python3 and calls the CLI tools  of  GNUnet.
       This  is  comparable to a fork and exec call which costs a few CPU cycles. Furthermore all
       the records that are added to the same label are signed using the zones private key.  This
       signing  operation  is  very resource heavy and was optimized during development by adding
       the ‘-R’ (Recordline) option to gnunet-namestore which allows to specify multiple  records
       using the CLI tool. Assuming that in a TLD zone every domain has at least two name servers
       this halves the amount of signatures needed.

       Another improvement that could be made is with the addition of multiple threads  or  using
       asynchronous  subprocesses when opening the GNUnet CLI tools. This could be implemented by
       simply creating more workers in the program but performance improvements were not tested.

       Ascension  was  tested  using  different  hardware  and  database  backends.   Performance
       differences  between  SQLite and postgresql are marginal and almost non existent. What did
       make a huge impact on record adding performance was the storage medium. On  a  traditional
       mechanical hard drive adding of records were slow compared to a solid state disk.

       In  conclusion  there  are many bottlenecks still around in the program, namely the single
       threaded implementation and inefficient, sequential  calls  of  gnunet-namestore.  In  the
       future a solution that uses the C API would be cleaner and better.

   Registering names using the FCFS daemon
       This section describes FCFSD, a daemon used to associate names with PKEY records following
       a “First Come, First Served” policy. This policy means that a  certain  name  can  not  be
       registered again if someone registered it already.

       The  daemon can be started by using gnunet-namestore-fcfsd, which will start a simple HTTP
       server on localhost, using a port specified by the HTTPORT value in its configuration.

       Communication  is  performed  by  sending  GET  or  POST  requests   to   specific   paths
       (“endpoints”), as described in the following sections.

       The  daemon  will always respond with data structured using the JSON format. The fields to
       be expected will be listed for each endpoint.

       The only exceptions are for the  “root”  endpoint  (i.e.  /)  which  will  return  a  HTML
       document,  and  two  other  HTML  documents  which  will be served when certain errors are
       encountered, like when requesting an unknown endpoint.

       FCFSD GET requests .. _Obtaining-information-from-the-daemon:

   Obtaining information from the daemon
       To query the daemon, a GET request must be sent to these endpoints, placing parameters  in
       the address as per the HTTP specification, like so:

          GET /endpoint?param1=value&param2=value

       Each  endpoint will be described using its name (/endpoint in the example above), followed
       by the name of each parameter (like param1 and param2.)

       Endpoint: /search name
              This endpoint is used to query about the state of <name>, that is,  whether  it  is
              available for registration or not.

              The response JSON will contain two fields:

              • error

              • free

              error  can be either the string "true" or the string "false": when "true", it means
              there was an error within the daemon and the name could not be searched at all.

              free can be either the string "true"  or  the  string  "false":  when  "true",  the
              requested name can be registered.

       FCFSD POST requests .. _Submitting-data-to-the-daemon:

   Submitting data to the daemon
       To  send  data  to the daemon, a POST request must be sent to these endpoints, placing the
       data to submit in the body of the request, structured using the JSON format, like so:

          POST /endpoint
          Content-Type: application/json
          ...

          {"param1": value1, "param2": value2, ...}

       Each endpoint will be described using its name (/endpoint in the example above),  followed
       by the name of each JSON field (like param1 and param2.)

       Endpoint: /register name key
              This endpoint is used to register a new association between <name> and <key>.

              For  this  operation  to  succeed,  both  <NAME>  and  <KEY> must not be registered
              already.

              The response JSON will contain two fields:

              • error

              • message

              error can be either the string "true" or the string "false": when "true", it  means
              the  name  could  not be registered. Clients can get the reason of the failure from
              the HTTP response code or from the message field.

              message is a string which can be used by clients to let users know  the  result  of
              the operation. It might be localized to the daemon operator’s locale.

   Customizing the HTML output
       In  some  situations,  the  daemon will serve HTML documents instead of JSON values. It is
       possible to configure the daemon to serve custom documents instead of  the  ones  provided
       with GNUnet, by setting the HTMLDIR value in its configuration to a directory path.

       Within the provided path, the daemon will search for these three files:

       • fcfsd-index.html

       • fcfsd-notfound.html

       • fcfsd-forbidden.html

       The  fcfsd-index.html  file  is  the  daemon’s “homepage”: operators might want to provide
       information about the service here, or provide  a  form  with  which  it  is  possible  to
       register a name.

       The  fcfsd-notfound.html  file is used primarily to let users know they tried to access an
       unknown endpoint.

       The fcfsd-forbidden.html file is served to users when they try to access an endpoint  they
       should not access. For example, sending an invalid request might result in this page being
       served.

   NAMECACHE  DHT caching of GNS results
       The NAMECACHE subsystem is responsible for caching (encrypted) resolution results  of  the
       GNU  Name  System  (GNS). GNS makes zone information available to other users via the DHT.
       However, as accessing the DHT for every lookup is expensive (and as the DHT’s local  cache
       is lost whenever the peer is restarted), GNS uses the NAMECACHE as a more persistent cache
       for DHT lookups. Thus, instead of always looking up every  name  in  the  DHT,  GNS  first
       checks  if  the  result is already available locally in the NAMECACHE. Only if there is no
       result in the NAMECACHE, GNS queries the DHT.  The  NAMECACHE  stores  data  in  the  same
       (encrypted)  format  as  the  DHT. It thus makes no sense to iterate over all items in the
       NAMECACHE – the NAMECACHE does not have a way to provide the keys required to decrypt  the
       entries.

       Blocks  in  the  NAMECACHE  share the same expiration mechanism as blocks in the DHT – the
       block expires wheneever  any  of  the  records  in  the  (encrypted)  block  expires.  The
       expiration  time  of  the block is the only information stored in plaintext. The NAMECACHE
       service internally performs all of the required work to expire blocks, clients do not have
       to  worry  about  this. Also, given that NAMECACHE stores only GNS blocks that local users
       requested, there is no configuration option to limit the size  of  the  NAMECACHE.  It  is
       assumed to be always small enough (a few MB) to fit on the drive.

       The NAMECACHE supports the use of different database backends via a plugin API.

   libgnunetnamecache
       The    NAMECACHE    API   consists   of   five   simple   functions.   First,   there   is
       GNUNET_NAMECACHE_connect to connect to the NAMECACHE  service.  This  returns  the  handle
       required  for  all  other operations on the NAMECACHE.  Using GNUNET_NAMECACHE_block_cache
       clients can insert a block into the cache. GNUNET_NAMECACHE_lookup_block can  be  used  to
       lookup  blocks  that  were  stored in the NAMECACHE. Both operations can be canceled using
       GNUNET_NAMECACHE_cancel. Note that canceling a GNUNET_NAMECACHE_block_cache operation  can
       result in the block being stored in the NAMECACHE — or not. Cancellation primarily ensures
       that the continuation function with the result of the operation will no longer be invoked.
       Finally, GNUNET_NAMECACHE_disconnect closes the connection to the NAMECACHE.

       The   maximum   size   of   a   block   that   can   be   stored   in   the  NAMECACHE  is
       GNUNET_NAMECACHE_MAX_VALUE_SIZE, which is defined to be 63 kB.

   The NAMECACHE Client-Service Protocol
       All messages in the NAMECACHE IPC protocol start with the  struct  GNUNET_NAMECACHE_Header
       which adds a request ID (32-bit integer) to the standard message header. The request ID is
       used to match requests with the respective responses  from  the  NAMECACHE,  as  they  are
       allowed to happen out-of-order.

   Lookup
       The  struct  LookupBlockMessage is used to lookup a block stored in the cache. It contains
       the query hash. The NAMECACHE always responds with a struct LookupBlockResponseMessage. If
       the  NAMECACHE  has  no  response,  it  sets  the expiration time in the response to zero.
       Otherwise, the response is expected to contain the expiration time, the  ECDSA  signature,
       the derived key and the (variable-size) encrypted data of the block.

   Store
       The  struct  BlockCacheMessage  is used to cache a block in the NAMECACHE. It has the same
       structure as the struct LookupBlockResponseMessage. The service  responds  with  a  struct
       BlockCacheResponseMessage which contains the result of the operation (success or failure).
       In the future, we might want to make it possible to provide an error message as well.

   The NAMECACHE Plugin API
       The NAMECACHE plugin API consists of two functions, cache_block to store a  block  in  the
       database, and lookup_block to lookup a block in the database.

   Lookup2
       The  lookup_block  function  is  expected to return at most one block to the iterator, and
       return GNUNET_NO if there were no non-expired results. If there are  multiple  non-expired
       results  in  the  cache,  the  lookup  is  supposed  to return the result with the largest
       expiration time.

   Store2
       The cache_block function is expected to try to store the block in the database, and return
       GNUNET_SYSERR  if  this  was  not  possible  for  any  reason. Furthermore, cache_block is
       expected to implicitly perform cache maintenance and purge blocks from the cache that have
       expired.  Note  that  cache_block  might encounter the case where the database already has
       another block stored under the same key. In this case, the plugin  must  ensure  that  the
       block  with  the  larger  expiration time is preserved. Obviously, this can done either by
       simply adding new blocks and selecting for the most recent expiration time during  lookup,
       or by checking which block is more recent during the store operation.

   NAMESTORE  Storage of local GNS zones
       The  NAMESTORE  subsystem  provides persistent storage for local GNS zone information. All
       local GNS zone information are managed by NAMESTORE. It provides both the functionality to
       administer  local GNS information (e.g. delete and add records) as well as to retrieve GNS
       information (e.g to list name information in a client). NAMESTORE  does  only  manage  the
       persistent  storage  of  zone  information  belonging to the user running the service: GNS
       information from other users obtained from the DHT are stored by the NAMECACHE subsystem.

       NAMESTORE uses a  plugin-based  database  backend  to  store  GNS  information  with  good
       performance.  Here sqlite, MySQL and PostgreSQL are supported database backends. NAMESTORE
       clients interact with the IDENTITY subsystem to  obtain  cryptographic  information  about
       zones  based  on  egos  as described with the IDENTITY subsystem, but internally NAMESTORE
       refers to zones using the ECDSA  private  key.  In  addition,  it  collaborates  with  the
       NAMECACHE subsystem and stores zone information when local information are modified in the
       GNS cache to increase look-up performance for local information.

       NAMESTORE provides functionality to look-up and store records, to iterate over a  specific
       or  all  zones  and to monitor zones for changes.  NAMESTORE functionality can be accessed
       using the NAMESTORE api or the NAMESTORE command line tool.

   libgnunetnamestore
       To interact with NAMESTORE clients first  connect  to  the  NAMESTORE  service  using  the
       GNUNET_NAMESTORE_connect  passing  a  configuration  handle.  As  a  result  they obtain a
       NAMESTORE handle, they can use for operations, or  NULL  is  returned  if  the  connection
       failed.

       To  disconnect  from  NAMESTORE,  clients  use GNUNET_NAMESTORE_disconnect and specify the
       handle to disconnect.

       NAMESTORE internally uses the ECDSA private key to refer to zones. These private keys  can
       be  obtained  from  the IDENTITY subsystem. Here egos can be used to refer to zones or the
       default ego assigned to the GNS subsystem can  be  used  to  obtained  the  master  zone’s
       private key.

   Editing Zone Information
       NAMESTORE provides functions to lookup records stored under a label in a zone and to store
       records under a label in a zone.

       To store (and delete) records, the client uses the GNUNET_NAMESTORE_records_store function
       and  has  to  provide  namestore  handle to use, the private key of the zone, the label to
       store the records under, the records and number of  records  plus  an  callback  function.
       After  the  operation is performed NAMESTORE will call the provided callback function with
       the result GNUNET_SYSERR on failure (including timeout/queue  drop/failure  to  validate),
       GNUNET_NO  if  content was already there or not found GNUNET_YES (or other positive value)
       on success plus an additional error message.

       Records are deleted by using the store command with 0 records to store.  It  is  important
       to  note,  that  records are not merged when records exist with the label. So a client has
       first to retrieve records, merge with existing records and then store the result.

       To  perform  a  lookup  operation,  the  client  uses  the  GNUNET_NAMESTORE_records_store
       function.  Here  it  has to pass the namestore handle, the private key of the zone and the
       label. It also has to provide a callback function which will be called with the result  of
       the  lookup  operation: the zone for the records, the label, and the records including the
       number of records included.

       A special operation is used to set the preferred nickname for a zone.   This  nickname  is
       stored  with  the zone and is automatically merged with all labels and records stored in a
       zone. Here the client uses the GNUNET_NAMESTORE_set_nick function and passes  the  private
       key  of  the  zone,  the  nickname  as  string  plus a the callback with the result of the
       operation.

   Iterating Zone Information
       A client can iterate over all information in a zone or all  zones  managed  by  NAMESTORE.
       Here  a  client  uses  the  GNUNET_NAMESTORE_zone_iteration_start  function and passes the
       namestore handle, the zone to iterate over and  a  callback  function  to  call  with  the
       result.  To  iterate  over  all  the  zones,  it  is possible to pass NULL for the zone. A
       GNUNET_NAMESTORE_ZoneIterator handle is returned to be used to continue iteration.

       NAMESTORE  calls  the  callback  for  every  result  and  expects  the  client   to   call
       GNUNET_NAMESTORE_zone_iterator_next       to       continue       to       iterate      or
       GNUNET_NAMESTORE_zone_iterator_stop to interrupt the iteration. When NAMESTORE reached the
       last item it will call the callback with a NULL value to indicate.

   Monitoring Zone Information
       Clients  can  also  monitor  zones to be notified about changes. Here the clients uses the
       GNUNET_NAMESTORE_zone_monitor_start function and passes the private key of  the  zone  and
       and  a callback function to call with updates for a zone. The client can specify to obtain
       zone information first by iterating over the zone and specify a  synchronization  callback
       to be called when the client and the namestore are synced.

       On an update, NAMESTORE will call the callback with the private key of the zone, the label
       and the records and their number.

       To stop monitoring, the client calls  GNUNET_NAMESTORE_zone_monitor_stop  and  passes  the
       handle obtained from the function to start the monitoring.

   Applications
   FS  File sharing over GNUnet
       This  chapter  describes  the  details  of how the file-sharing service works. As with all
       services, it is split into an API (libgnunetfs), the service  process  (gnunet-service-fs)
       and user interface(s). The file-sharing service uses the datastore service to store blocks
       and the DHT  (and  indirectly  datacache)  for  lookups  for  non-anonymous  file-sharing.
       Furthermore, the file-sharing service uses the block library (and the block fs plugin) for
       validation of DHT operations.

       In contrast to many other services, libgnunetfs is rather complex since the client library
       includes a large number of high-level abstractions; this is necessary since the FS service
       itself largely only operates on the  block  level.  The  FS  library  is  responsible  for
       providing  a  file-based  abstraction  to  applications, including directories, meta data,
       keyword search, verification, and so on.

       The method used by GNUnet to break large files into blocks and to use  keyword  search  is
       called the "Encoding for Censorship Resistant Sharing" (ECRS). ECRS is largely implemented
       in the fs library; block validation is also reflected in the block FS plugin  and  the  FS
       service.  ECRS on-demand encoding is implemented in the FS service.

       NOTE:
          The documentation in this chapter is quite incomplete.

   ECRS  Encoding for Censorship-Resistant Sharing
       When GNUnet shares files, it uses a content encoding that is called ECRS, the Encoding for
       Censorship-Resistant Sharing. Most of ECRS  is  described  in  the  (so  far  unpublished)
       research  paper  attached  to  this  page.  ECRS  obsoletes  the previous ESED and ESED II
       encodings which were used in GNUnet before version 0.7.0. The rest of  this  page  assumes
       that the reader is familiar with the attached paper. What follows is a description of some
       minor extensions that GNUnet makes over what is described in the  paper.  The  reason  why
       these  extensions  are  not in the paper is that we felt that they were obvious or trivial
       extensions to the original scheme and thus did not warrant space in the research report.

   Todo
       Find missing link to file system paper.

   Namespace Advertisements
   Todo
       FIXME: all zeroses -> ?

       An SBlock with identifier all zeros is  a  signed  advertisement  for  a  namespace.  This
       special  SBlock  contains metadata describing the content of the namespace. Instead of the
       name of the identifier for a potential update, it contains the identifier for the root  of
       the  namespace.  The  URI  should  always  be empty. The SBlock is signed with the content
       provider’s RSA private key (just like any other SBlock).  Peers can search for SBlocks  in
       order to find out more about a namespace.

   KSBlocks
       GNUnet  implements  KSBlocks  which  are  KBlocks  that,  instead  of encrypting a CHK and
       metadata, encrypt an SBlock instead. In  other  words,  KSBlocks  enable  GNUnet  to  find
       SBlocks  using  the  global  keyword  search.  Usually the encrypted SBlock is a namespace
       advertisement. The rationale behind KSBlocks and SBlocks is to enable  peers  to  discover
       namespaces  via  keyword  searches,  and, to associate useful information with namespaces.
       When GNUnet finds KSBlocks during a normal keyword search, it adds the information  to  an
       internal  list of discovered namespaces. Users looking for interesting namespaces can then
       inspect this list, reducing the need for out-of-band discovery of  namespaces.  Naturally,
       namespaces  (or  more  specifically, namespace advertisements) can also be referenced from
       directories, but KSBlocks should make it easier to advertise namespaces for the  owner  of
       the pseudonym since they eliminate the need to first create a directory.

       Collections are also advertised using KSBlocks.

   File-sharing persistence directory structure
       This section documents how the file-sharing library implements persistence of file-sharing
       operations and specifically the resulting directory structure. This code is only active if
       the  GNUNET_FS_FLAGS_PERSISTENCE  flag was set when calling GNUNET_FS_start. In this case,
       the file-sharing library will try hard to ensure that  all  major  operations  (searching,
       downloading,  publishing,  unindexing)  are  persistent, that is, can live longer than the
       process itself. More specifically, an operation is supposed to live until it is explicitly
       stopped.

       If  GNUNET_FS_stop  is  called  before  an  operation has been stopped, a SUSPEND event is
       generated and then when the process calls GNUNET_FS_start next time,  a  RESUME  event  is
       generated.  Additionally, even if an application crashes (segfault, SIGKILL, system crash)
       and hence GNUNET_FS_stop is never called and no SUSPEND events are  generated,  operations
       are  still  resumed  (with  RESUME  events). This is implemented by constantly writing the
       current state of the file-sharing operations to disk. Specifically, the current  state  is
       always written to disk whenever anything significant changes (the exception are block-wise
       progress in publishing and  unindexing,  since  those  operations  would  be  slowed  down
       significantly  and  can be resumed cheaply even without detailed accounting). Note that if
       the process crashes (or is killed) during a serialization operation, FS does not guarantee
       that  this specific operation is recoverable (no strict transactional semantics, again for
       performance reasons). However, all other unrelated operations should resume nicely.

       Since we need to serialize the state continuously and want to recover as much as  possible
       even  after  crashing  during  a serialization operation, we do not use one large file for
       serialization. Instead, several directories are used  for  the  various  operations.  When
       GNUNET_FS_start  executes,  the  master  directories  are  scanned  for  files  describing
       operations to resume. Sometimes, these operations can refer to related operations in child
       directories which may also be resumed at this point. Note that corrupted files are cleaned
       up automatically. However, dangling  files  in  child  directories  (those  that  are  not
       referenced by files from the master directories) are not automatically removed.

       Persistence  data  is kept in a directory that begins with the "STATE_DIR" prefix from the
       configuration file (by default, "$SERVICEHOME/persistence/") followed by the name  of  the
       client as given to GNUNET_FS_start (for example, "gnunet-gtk") followed by the actual name
       of the master or child directory.

       The names for the master directories follow the names of the operations:

       • "search"

       • "download"

       • "publish"

       • "unindex"

       Each of the master directories contains names (chosen at random) for each active top-level
       (master)  operation. Note that a download that is associated with a search result is not a
       top-level operation.

       In contrast to the master directories, the  child  directories  are  only  consulted  when
       another  operation refers to them. For each search, a subdirectory (named after the master
       search synchronization file) contains the search  results.  Search  results  can  have  an
       associated  download,  which  is  then  stored  in the general "download-child" directory.
       Downloads can be recursive, in which case children are stored in subdirectories  mirroring
       the  structure  of  the  recursive  download  (either  starting  in  the master "download"
       directory or  in  the  "download-child"  directory  depending  on  how  the  download  was
       initiated).  For  publishing operations, the "publish-file" directory contains information
       about the individual files and directories that are part of the publication. However, this
       directory structure is flat and does not mirror the structure of the publishing operation.
       Note that unindex operations cannot have associated child operations.

   IDENTITY  Ego management
       Identities of "users" in GNUnet are called egos. Egos can be  used  as  pseudonyms  ("fake
       names")  or be tied to an organization (for example, "GNU") or even the actual identity of
       a human. GNUnet users are expected to have many egos. They might have one  tied  to  their
       real  identity,  some  for organizations they manage, and more for different domains where
       they want to operate under a pseudonym.

       The IDENTITY service allows users to manage their egos. The identity service  manages  the
       private  keys egos of the local user; it does not manage identities of other users (public
       keys). Public keys for other users need names to become manageable. GNUnet  uses  the  GNU
       Name System (GNS) to give names to other users and manage their public keys securely. This
       chapter is about the IDENTITY service, which is about the management of private keys.

       On the network, an ego corresponds to an ECDSA key (over Curve25519, using  RFC  6979,  as
       required by GNS). Thus, users can perform actions under a particular ego by using (signing
       with) a particular private key.  Other users can then confirm that the action  was  really
       performed by that ego by checking the signature against the respective public key.

       The  IDENTITY  service allows users to associate a human-readable name with each ego. This
       way, users can use names that will remind them of the purpose of  a  particular  ego.  The
       IDENTITY  service will store the respective private keys and allows applications to access
       key information by name. Users can change the name that is locally (!)  associated with an
       ego.  Egos  can  also  be deleted, which means that the private key will be removed and it
       thus will not be possible to perform actions with that ego in the future.

       Additionally, the IDENTITY subsystem  can  associate  service  functions  with  egos.  For
       example,  GNS  requires  the  ego  that  should be used for the shorten zone. GNS will ask
       IDENTITY for an ego for the "gns-short" service. The IDENTITY service  has  a  mapping  of
       such  service  strings to the name of the ego that the user wants to use for this service,
       for example "my-short-zone-ego".

       Finally, the IDENTITY API provides access  to  a  special  ego,  the  anonymous  ego.  The
       anonymous  ego  is  special  in  that its private key is not really private, but fixed and
       known to everyone. Thus, anyone can perform actions as anonymous. This can  be  useful  as
       with  this  trick,  code  does  not  have to contain a special case to distinguish between
       anonymous and pseudonymous egos.

   libgnunetidentity
   Connecting to the service
       First, typical clients connect to the identity service using GNUNET_IDENTITY_connect. This
       function  takes a callback as a parameter. If the given callback parameter is non-null, it
       will be invoked to notify the application about the current state of the identities in the
       system.

       • First, it will be invoked on all known egos at the time of the connection. For each ego,
         a handle to the ego and the user’s name for the ego will  be  passed  to  the  callback.
         Furthermore,  a  void  **  context  argument will be provided which gives the client the
         opportunity to associate some state with the ego.

       • Second, the callback will be invoked with NULL for the ego, the name  and  the  context.
         This signals that the (initial) iteration over all egos has completed.

       • Then, the callback will be invoked whenever something changes about an ego. If an ego is
         renamed, the callback is invoked with the ego handle of the ego that  was  renamed,  and
         the  new  name.  If an ego is deleted, the callback is invoked with the ego handle and a
         name of NULL. In the deletion case, the application should also release resources stored
         in the context.

       • When   the   application   destroys   the  connection  to  the  identity  service  using
         GNUNET_IDENTITY_disconnect, the callback is again invoked with the ego  and  a  name  of
         NULL  (equivalent  to  deletion of the egos).  This should again be used to clean up the
         per-ego context.

       The ego handle passed to the callback remains valid until the callback is invoked  with  a
       name of NULL, so it is safe to store a reference to the ego’s handle.

   Operations on Egos
       Given  an  ego  handle,  the  main  operations are to get its associated private key using
       GNUNET_IDENTITY_ego_get_private_key    or    its    associated    public     key     using
       GNUNET_IDENTITY_ego_get_public_key.

       The  other operations on egos are pretty straightforward. Using GNUNET_IDENTITY_create, an
       application can request the creation of  an  ego  by  specifying  the  desired  name.  The
       operation  will fail if that name is already in use. Using GNUNET_IDENTITY_rename the name
       of  an  existing  ego   can   be   changed.   Finally,   egos   can   be   deleted   using
       GNUNET_IDENTITY_delete. All of these operations will trigger updates to the callback given
       to the GNUNET_IDENTITY_connect function of all applications that are  connected  with  the
       identity service at the time.  GNUNET_IDENTITY_cancel can be used to cancel the operations
       before the respective continuations would  be  called.  It  is  not  guaranteed  that  the
       operation will not be completed anyway, only the continuation will no longer be called.

   The anonymous Ego
       A  special way to obtain an ego handle is to call GNUNET_IDENTITY_ego_get_anonymous, which
       returns an ego for the "anonymous" user — anyone knows and can get  the  private  key  for
       this  user, so it is suitable for operations that are supposed to be anonymous but require
       signatures (for example, to avoid a special path in the code). The anonymous ego is always
       valid and accessing it does not require a connection to the identity service.

   Convenience API to lookup a single ego
       As applications commonly simply have to lookup a single ego, there is a convenience API to
       do just that. Use GNUNET_IDENTITY_ego_lookup to lookup a single ego  by  name.  Note  that
       this  is  the user’s name for the ego, not the service function. The resulting ego will be
       returned via a callback and will only be valid during that callback. The operation can  be
       canceled  via  GNUNET_IDENTITY_ego_lookup_cancel  (cancellation  is  only legal before the
       callback is invoked).

   Associating egos with service functions
       The GNUNET_IDENTITY_set function is used to associate a  particular  ego  with  a  service
       function. The name used by the service and the ego are given as arguments. Afterwards, the
       service can use its name to lookup the associated ego using GNUNET_IDENTITY_get.

   The IDENTITY Client-Service Protocol
       A  client  connecting  to  the  identity  service  first  sends  a   message   with   type
       GNUNET_MESSAGE_TYPE_IDENTITY_START  to  the  service.  After that, the client will receive
       information   about   changes   to   the   egos   by   receiving    messages    of    type
       GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE.   Those  messages  contain the private key of the ego
       and the user’s name of the ego (or zero bytes for the name to indicate that  the  ego  was
       deleted).  A  special bit end_of_list is used to indicate the end of the initial iteration
       over the identity service’s egos.

       The client can trigger changes to the egos by sending CREATE, RENAME or  DELETE  messages.
       The  CREATE  message  contains  the  private  key and the desired name. The RENAME message
       contains the old name and the new name. The DELETE message only needs to include the  name
       of  the  ego  to delete. The service responds to each of these messages with a RESULT_CODE
       message which indicates success or error of the operation, and possibly  a  human-readable
       error message.

       Finally,  the  client  can  bind  the  name  of  a service function to an ego by sending a
       SET_DEFAULT message with the name of the service function and the private key of the  ego.
       Such bindings can then be resolved using a GET_DEFAULT message, which includes the name of
       the service function. The identity service will respond to a GET_DEFAULT  request  with  a
       SET_DEFAULT  message  containing  the  respective  information,  or  with a RESULT_CODE to
       indicate an error.

   REVOCATION  Ego key revocation
       The REVOCATION subsystem is responsible for key revocation of Egos. If a user learns  that
       their  private key has been compromised or has lost it, they can use the REVOCATION system
       to inform all of the other users that their private key is no longer valid. The  subsystem
       thus includes ways to query for the validity of keys and to propagate revocation messages.

   Dissemination
       When  a  revocation  is performed, the revocation is first of all disseminated by flooding
       the overlay network. The goal is to reach every peer, so that when a peer needs  to  check
       if  a  key has been revoked, this will be purely a local operation where the peer looks at
       its local revocation list. Flooding the network is  also  the  most  robust  form  of  key
       revocation  —  an  adversary  would  have  to  control a separator of the overlay graph to
       restrict the propagation of the  revocation  message.   Flooding  is  also  very  easy  to
       implement  —  peers  that receive a revocation message for a key that they have never seen
       before simply pass the message to all of their neighbours.

       Flooding can only distribute the revocation message to peers that are online. In order  to
       notify  peers  that  join the network later, the revocation service performs efficient set
       reconciliation over the sets of known revocation messages whenever two  peers  (that  both
       support  REVOCATION  dissemination)  connect.  The  SET  service  is  used to perform this
       operation efficiently.

   Revocation Message Design Requirements
       However, flooding is also quite costly, creating O(|E|) messages on  a  network  with  |E|
       edges. Thus, revocation messages are required to contain a proof-of-work, the result of an
       expensive computation (which, however, is cheap to verify). Only peers that have  expended
       the  CPU  time  necessary to provide this proof will be able to flood the network with the
       revocation message. This ensures that an attacker cannot simply  flood  the  network  with
       millions  of revocation messages. The proof-of-work required by GNUnet is set to take days
       on a typical PC to compute; if the ability to quickly revoke a key is needed,  users  have
       the  option  to  pre-compute revocation messages to store off-line and use instantly after
       their key has expired.

       Revocation messages must also be signed by the private key that is  being  revoked.  Thus,
       they  can  only  be  created  while the private key is in the possession of the respective
       user. This is another reason to create a revocation message ahead of time and store it  in
       a secure location.

   libgnunetrevocation
       The REVOCATION API consists of two parts, to query and to issue revocations.

   Querying for revoked keys
       GNUNET_REVOCATION_query is used to check if a given ECDSA public key has been revoked. The
       given callback will be invoked with the result of the check. The  query  can  be  canceled
       using GNUNET_REVOCATION_query_cancel on the return value.

   Preparing revocations
       It  is  often  desirable  to  create  a revocation record ahead-of-time and store it in an
       off-line location to be used later in an emergency. This is particularly true  for  GNUnet
       revocations, where performing the revocation operation itself is computationally expensive
       and thus is likely to take  some  time.  Thus,  if  users  want  the  ability  to  perform
       revocations  quickly  in  an  emergency, they must pre-compute the revocation message. The
       revocation API enables this with two functions that are used  to  compute  the  revocation
       message, but not trigger the actual revocation operation.

       GNUNET_REVOCATION_check_pow  should be used to calculate the proof-of-work required in the
       revocation message. This function takes the public key, the required number  of  bits  for
       the proof of work (which in GNUnet is a network-wide constant) and finally a proof-of-work
       number as arguments. The function then checks if the given proof-of-work number is a valid
       proof  of  work  for  the given public key. Clients preparing a revocation are expected to
       call this function repeatedly (typically  with  a  monotonically  increasing  sequence  of
       numbers of the proof-of-work number) until a given number satisfies the check. That number
       should then be saved for later use in the revocation operation.

       GNUNET_REVOCATION_sign_revocation is used to generate the signature that is required in  a
       revocation  message.  It  takes  the  private  key  that (possibly in the future) is to be
       revoked and returns the signature. The signature can again be saved to disk for later use,
       which will then allow performing a revocation even without access to the private key.

   Issuing revocations
       Given a ECDSA public key, the signature from GNUNET_REVOCATION_sign and the proof-of-work,
       GNUNET_REVOCATION_revoke can be used to perform the actual revocation. The given  callback
       is called upon completion of the operation. GNUNET_REVOCATION_revoke_cancel can be used to
       stop the library from calling the continuation; however, in  that  case  it  is  undefined
       whether or not the revocation operation will be executed.

   The REVOCATION Client-Service Protocol
       The REVOCATION protocol consists of four simple messages.

       A QueryMessage containing a public ECDSA key is used to check if a particular key has been
       revoked. The service responds with a QueryResponseMessage which simply contains a bit that
       says if the given public key is still valid, or if it has been revoked.

       The second possible interaction is for a client to revoke a key by passing a RevokeMessage
       to the service. The RevokeMessage contains the ECDSA public key to be revoked, a signature
       by  the  corresponding  private  key  and  the  proof-of-work. The service responds with a
       RevocationResponseMessage which can be used to indicate that the RevokeMessage was invalid
       (e.g.  the  proof  of work is incorrect), or otherwise to indicate that the revocation has
       been processed successfully.

   The REVOCATION Peer-to-Peer Protocol
       Revocation uses two disjoint ways to spread revocation information among peers.  First  of
       all,  P2P gossip exchanged via CORE-level neighbours is used to quickly spread revocations
       to all connected peers.  Second,  whenever  two  peers  (that  both  support  revocations)
       connect, the SET service is used to compute the union of the respective revocation sets.

       In both cases, the exchanged messages are RevokeMessages which contain the public key that
       is being revoked, a matching ECDSA signature, and a proof-of-work. Whenever a peer  learns
       about  a  new revocation this way, it first validates the signature and the proof-of-work,
       then stores it to disk (typically to a file $GNUNET_DATA_HOME/revocation.dat) and  finally
       spreads the information to all directly connected neighbours.

       For  computing  the  union  using  the  SET service, the peer with the smaller hashed peer
       identity will connect (as a "client" in the two-party set  protocol)  to  the  other  peer
       after one second (to reduce traffic spikes on connect) and initiate the computation of the
       set union. All revocation services use a common hash to identify the  SET  operation  over
       revocation sets.

       The  current  implementation accepts revocation set union operations from all peers at any
       time;  however,  well-behaved  peers  should  only  initiate  this  operation  once  after
       establishing a connection to a peer with a larger hashed peer identity.

   MESSENGER  Room-based end-to-end messaging
       The  MESSENGER  subsystem  is responsible for secure end-to-end communication in groups of
       nodes in the GNUnet overlay network.   MESSENGER  builds  on  the  CADET  subsystem  which
       provides  a reliable and secure end-to-end communication between the nodes inside of these
       groups.

       Additionally to the CADET  security  benefits,  MESSENGER  provides  following  properties
       designed for application level usage:

       • MESSENGER provides integrity by signing the messages with the users provided ego

       • MESSENGER  adds (optional) forward secrecy by replacing the key pair of the used ego and
         signing the propagation of the new one with old one (chaining egos)

       • MESSENGER provides verification of a original sender by checking against all  used  egos
         from  a  member  which are currently in active use (active use depends on the state of a
         member session)

       • MESSENGER offsers (optional) decentralized message forwarding between  all  nodes  in  a
         group to improve availability and prevent MITM-attacks

       • MESSENGER  handles  new  connections  and  disconnections  from  nodes  in  the group by
         reconnecting them preserving an efficient structure for message  distribution  (ensuring
         availability and accountablity)

       • MESSENGER  provides  replay protection (messages can be uniquely identified via SHA-512,
         include a timestamp and the hash of the last message)

       • MESSENGER allows detection for dropped messages by chaining them (messages refer to  the
         last message by their hash) improving accountability

       • MESSENGER allows requesting messages from other peers explicitly to ensure availability

       • MESSENGER  provides  confidentiality  by  padding  messages  to few different sizes (512
         bytes, 4096 bytes, 32768 bytes and maximal message size from CADET)

       • MESSENGER adds (optional) confidentiality with  ECDHE  to  exchange  and  use  symmetric
         encryption,  encrypting with both AES-256 and Twofish but allowing only selected members
         to decrypt (using the receivers ego for ECDHE)

       Also MESSENGER provides multiple features with privacy in mind:

       • MESSENGER allows deleting messages from all peers in the group by  the  original  sender
         (uses the MESSENGER provided verification)

       • MESSENGER  allows  using  the  publicly  known  anonymous  ego  instead  of  any  unique
         identifying ego

       • MESSENGER allows your node to decide between acting as host of the used  messaging  room
         (sharing  your  peer’s identity with all nodes in the group) or acting as guest (sharing
         your peer’s identity only with the nodes you explicitly open a connection to)

       • MESSENGER handles members independently of the peer’s identity making forwarded messages
         indistinguishable  from  directly  received ones ( complicating the tracking of messages
         and identifying its origin)

       • MESSENGER allows names of members being not unique (also names are optional)

       • MESSENGER does not include information about the  selected  receiver  of  an  explicitly
         encrypted  message  in its header, complicating it for other members to draw conclusions
         from communication partners

   libgnunetmessenger
       The MESSENGER API (defined in gnunet_messenger_service.h) allows  P2P  applications  built
       using  GNUnet  to  communicate  with  specified  kinds of messages in a group. It provides
       applications the ability to send and receive encrypted messages  to  any  group  of  peers
       participating  in  GNUnet  in  a  decentralized  way  (  without  even knowing all peers’s
       identities).

       MESSENGER delivers messages to other peers in "rooms". A room uses a  variable  amount  of
       CADET  "channels"  which  will  all  be  used  for  message distribution. Each channel can
       represent    an    outgoing    connection    opened    by    entering    a    room    with
       GNUNET_MESSENGER_enter_room  or  an  incoming connection if the room was opened before via
       GNUNET_MESSENGER_open_room.

       [image: messenger_room] [image]

       To enter a room you have to specify the "door" (peer’s identity of a peer which has opened
       the  room)  and the key of the room (which is identical to a CADET "port"). To open a room
       you have to specify only the key to use. When opening a room you automatically  distribute
       a PEER-message sharing your peer’s identity in the room.

       Entering  or  opening  a  room  can  also  be  combined in any order. In any case you will
       automatically get a unique member ID and send a JOIN-message notifying others  about  your
       entry and your public key from your selected ego.

       The  ego can be selected by name with the initial GNUNET_MESSENGER_connect besides setting
       a  (identity-)callback  for   each   change/confirmation   of   the   used   ego   and   a
       (message-)callback  which  gets  called  every time a message gets sent or received in the
       room.  Once  the  identity-callback  got  called  you  can  check  your  used   ego   with
       GNUNET_MESSENGER_get_key  providing  only its public key. The function returns NULL if the
       anonymous ego is used. If the ego should be replaced with a newly generated one,  you  can
       use GNUNET_MESSENGER_update to ensure proper chaining of used egos.

       Also   once   the  identity-callback  got  called  you  can  check  your  used  name  with
       GNUNET_MESSENGER_get_name    and    potentially    change    or    set    a    name    via
       GNUNET_MESSENGER_set_name.  A  name  is  for  example  required  to  create a new ego with
       GNUNET_MESSENGER_update. Also any change in ego or name will automatically be  distributed
       in the room with a NAME- or KEY-message respectively.

       To send a message a message inside of a room you can use GNUNET_MESSENGER_send_message. If
       you specify a selected contact as receiver, the message gets encrypted  automatically  and
       will be sent as PRIVATE- message instead.

       To  request  a  potentially missed message or to get a specific message after its original
       call of the message-callback, you can use GNUNET_MESSENGER_get_message. Additionally  once
       a  message  was  distributed to application level and the message-callback got called, you
       can   get   the   contact   respresenting   a   message’s   sender    respectively    with
       GNUNET_MESSENGER_get_sender.  This  allows  getting  name and the public key of any sender
       currently       in       use       with       GNUNET_MESSENGER_contact_get_name        and
       GNUNET_MESSENGER_contact_get_key.  It  is  also  possible  to  iterate through all current
       members of a room with GNUNET_MESSENGER_iterate_members using a callback.

       To leave a room you can use GNUNET_MESSENGER_close_room which will also  close  the  rooms
       connections once all applications on the same peer have left the room. Leaving a room will
       also send a LEAVE-message closing a member session  on  all  connected  peers  before  any
       connection  will  be closed. Leaving a room is however not required for any application to
       keep your member session open between multiple sessions of the actual application.

       Finally,  when  an  application  no  longer  wants  to   use   CADET,   it   should   call
       GNUNET_MESSENGER_disconnect.  You  don’t  have to explicitly close the used rooms or leave
       them.

       Here is a little summary to the kinds of messages you can send manually:

   MERGE-message
       MERGE-messages will generally be sent automatically  to  reduce  the  amount  of  parallel
       chained  messages.  This  is necessary to close a member session for example. You can also
       send MERGE-messages manually if required to merge two chains of messages.

   INVITE-message
       INVITE-messages can be used to invite other members in a room to a different room, sharing
       one  potential  door  and  the  required  key  to  enter the room. This kind of message is
       typically sent as encrypted PRIVATE-message to selected members because  it  doesn’t  make
       much  sense to invite all members from one room to another considering a rooms key doesn’t
       specify its usage.

   TEXT-message
       TEXT-messages can be used to send simple text-based messages and should be  considered  as
       being   in   readable  form  without  complex  decoding.  The  text  has  to  end  with  a
       NULL-terminator character and should be in UTF-8 encoding for most compatibility.

   FILE-message
       FILE-messages can be used to share files inside of a room. They do not contain the  actual
       file  being  shared  but  its  original  hash,  filename,  URI  to download the file and a
       symmetric key to decrypt the downloaded file.

       It is recommended to use the FS subsystem and the FILE-messages in combination.

   DELETE-message
       DELETE-messages can be used to delete messages selected  with  its  hash.   You  can  also
       select  any custom delay relative to the time of sending the DELETE-message. Deletion will
       only be processed on each peer in a room if the sender is authorized.

       The only information of a deleted message which being kept  will  be  the  chained  hashes
       connecting  the  message  graph  for  potential  traversion.   For  example  the check for
       completion of a member session requires this information.

   Member sessions
       A member session is a triple of the room key, the member ID and  the  public  key  of  the
       member’s ego. Member sessions allow that a member can change their ID or their ego once at
       a time without losing the ability to delete  old  messages  or  identifying  the  original
       sender  of a message.  On every change of ID or EGO a session will be marked as closed. So
       every session chain will only contain one open session with the current ID and public key.

       If a session is marked as closed the MESSENGER service will check from the  first  message
       opening a session to its last one closing the session for completion. If a the service can
       confirm that there is no message still missing which  was  sent  from  the  closed  member
       session, it will be marked as completed.

       A  completed  member  session is not able to verify any incoming message to ensure forward
       secrecy preventing others from using old stolen egos.

   REST  RESTful GNUnet Web APIs
   Todo
       Define REST

       Using the REST subsystem, you can expose REST-based APIs or services.  The REST service is
       designed  as a pluggable architecture. To create a new REST endpoint, simply add a library
       in the form “plugin_rest_*”. The REST service will automatically load all REST plugins  on
       startup.

       Configuration

       The REST service can be configured in various ways. The reference config file can be found
       in src/rest/rest.conf:

          [rest]
          REST_PORT=7776
          REST_ALLOW_HEADERS=Authorization,Accept,Content-Type
          REST_ALLOW_ORIGIN=*
          REST_ALLOW_CREDENTIALS=true

       The port as well as CORS (cross-origin resource sharing) headers that are supposed  to  be
       advertised by the rest service are configurable.

   Namespace considerations
       The  gnunet-rest-service will load all plugins that are installed. As such it is important
       that the endpoint namespaces do not clash.

       For example, plugin X might expose the endpoint “/xxx” while  plugin  Y  exposes  endpoint
       “/xxx/yyy”. This is a problem if plugin X is also supposed to handle a call to “/xxx/yyy”.
       Currently the REST service will not complain or warn about such clashes,  so  please  make
       sure that endpoints are unambiguous.

   Endpoint documentation
       This is WIP. Endpoints should be documented appropriately. Preferably using annotations.

   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
       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
   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
       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
       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
       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).

   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
       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
       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
       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
   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
       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
       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-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
       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
       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
       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
       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
       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
       Before you can test the client you’ve written so far, you’ll need to  also  implement  the
       corresponding service.

   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
       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
       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
       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
       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
       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
       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-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
       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
       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
       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
       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
       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
       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
       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
       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
       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
       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
       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
       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
       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
       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-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
       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.

   Doxygen
       The code documentation will soon be ported here.  Until then you can find it  in  the  old
       place: https://docs.gnunet.org/doxygen/

LIVING STANDARDS

       On this page you can find links to our RFC-style technical protocol specifications:

       • LSD0000: Reserved

       • LSD0001: The GNU Name SystemLSD0002: re:claimIDLSD0003: Byzantine Fault Tolerant Set Reconciliation (work-in-progress)LSD0004: The R5N Distributed Hash Table (work-in-progress)

GANA

       The  GNUnet Assigned Numbers Authority (GANA) contains various registries we maintain, for
       GNUnet other projects that need names and numbers for use in  network  protocols.  If  you
       need to open a new registry, please feel free to contact us at gana@gnunet.org.

       The registries can be found here: https://git.gnunet.org/gana.git

   History
       Barry  Leiba  wrote on April 4th 2020 that “Neither IANA nor participants in the IETF will
       have any necessary expertise to evaluate registration requests in  the  sort  of  registry
       described,  and  no one will be well served by the creation of such a registry at IANA. It
       would be far better to have a registration process be described in this document involving
       experts from the industry as reviewers and maintenance of the registrations by an industry
       organization, rather than by IANA.”

       So here we are. As IETF/IANA “lack the necessary expertise  to  operate  a  registry”  for
       names and numbers used in network protocols, the GNUnet project is happy to step up.

   License
       The GANA database is licensed under the GPL. See COPYING in the Git repository.

   Design
       Each  registry must have a unique name and all associated information lives in a directory
       under that unique name in the Git repository.

       Each registry must include at least the following files:

       • README[.*]: document describing the purpose of the registry in English

       • POLICY[.*]: registration policy,  explaining  required  fields  and  the  procedure  for
         adding, updating and deleting entries

       • registry.rec: GNU recutils data file with all of the current entries in the registry

       • Makefile:  GNU  make  makefile  with  a  make  check target to run the validation logic.
         Ideally, the registry.rec should be  written  such  that  the  check  target  is  simply
         invoking  recfix --check registry.rec. Additional targets to convert data.rec to various
         formats may be defined. In particular, see format.sh in the root directory  of  the  Git
         repository (try --help).

GUIS

   The graphical configuration interface
       If  you  also  would  like  to  use  gnunet-gtk  and  gnunet-setup (highly recommended for
       beginners), do:

   Configuring your peer
       This chapter will describe the various configuration options in GNUnet.

       The easiest way to configure your peer is to use the gnunet-setup  tool.  gnunet-setup  is
       part of the gnunet-gtk package. You might have to install it separately.

       Many  of  the  specific  sections  from  this  chapter  actually  are  linked  from within
       gnunet-setup to help you while using the setup tool.

       While you can also configure your peer by editing the configuration file by hand, this  is
       not  recommended  for  anyone  except  for  developers  as  it  requires  a  more in-depth
       understanding of the configuration files and internal dependencies of GNUnet.

   Configuration of the HOSTLIST proxy settings
       The hostlist client can be configured to use a proxy to connect to  the  hostlist  server.
       This  functionality  can  be  configured  in  the configuration file directly or using the
       gnunet-setup tool.

       The hostlist client supports the following proxy types at the moment:

       • HTTP and HTTP 1.0 only proxy

       • SOCKS 4/4a/5/5 with hostname

       In addition authentication at the proxy with username and password can be configured.

       To configure proxy support for the hostlist client in the gnunet-setup  tool,  select  the
       "hostlist"  tab  and  select  the  appropriate  proxy  type.  The  hostname  or IP address
       (including port if required) has to  be  entered  in  the  "Proxy  hostname"  textbox.  If
       required,  enter username and password in the "Proxy username" and "Proxy password" boxes.
       Be aware that this information will be stored in the configuration in  plain  text  (TODO:
       Add explanation and generalize the part in Chapter 3.6 about the encrypted home).

   Configuration of the HTTP and HTTPS transport plugins
       The  client parts of the http and https transport plugins can be configured to use a proxy
       to  connect  to  the  hostlist  server.  This  functionality  can  be  configured  in  the
       configuration file directly or using the gnunet-setup tool.

       Both the HTTP and HTTPS clients support the following proxy types at the moment:

       • HTTP 1.1 proxy

       • SOCKS 4/4a/5/5 with hostname

       In addition authentication at the proxy with username and password can be configured.

       To  configure  proxy  support  for  the  clients  in  the  gnunet-setup  tool,  select the
       "transport" tab and activate the respective plugin. Now you  can  select  the  appropriate
       proxy  type.  The hostname or IP address (including port if required) has to be entered in
       the "Proxy hostname" textbox. If required, enter  username  and  password  in  the  "Proxy
       username"  and  "Proxy  password" boxes. Be aware that these information will be stored in
       the configuration in plain text.

   GTK File-sharing User Interface
       This chapter describes first steps for file-sharing with  GNUnet.  To  start,  you  should
       launch gnunet-fs-gtk.

       As  we  want  to  be  sure  that the network contains the data that we are looking for for
       testing, we need to begin by publishing a file.

   Publishing
       To publish a file, select "File Sharing" in the menu bar just below the "Statistics" icon,
       and then select "Publish" from the menu.

       Afterwards, the following publishing dialog will appear:

       |image3|

       In this dialog, select the "Add File" button. This will open a file selection dialog:

       |image4|

       Now, you should select a file from your computer to be published on GNUnet. To see more of
       GNUnet's features later, you should pick a PNG or JPEG file this time. You can  leave  all
       of  the other options in the dialog unchanged. Confirm your selection by pressing the "OK"
       button in the bottom right corner. Now, you will briefly see a "Messages..."   dialog  pop
       up,  but  most likely it will be too short for you to really read anything. That dialog is
       showing you progress information as GNUnet takes a first look at the selected file(s). For
       a  normal image, this is virtually instant, but if you later import a larger directory you
       might be interested in the progress dialog and potential errors that might be  encountered
       during  processing.  After  the progress dialog automatically disappears, your file should
       now appear in the publishing dialog:

       |image5|

       Now, select the file (by clicking on the file name) and then click the "Edit" button. This
       will open the editing dialog:

       |image6|

       In  this  dialog,  you can see many details about your file. In the top left area, you can
       see meta data extracted about the file, such as the original filename,  the  mimetype  and
       the  size  of  the image. In the top right, you should see a preview for the image (if GNU
       libextractor was installed correctly with the respective plugins). Note that if you do not
       see  a  preview,  this  is not a disaster, but you might still want to install more of GNU
       libextractor in the future. In the bottom left, the dialog contains a  list  of  keywords.
       These  are the keywords under which the file will be made available. The initial list will
       be based on the extracted meta data. Additional publishing options are in the right bottom
       corner.  We  will  now  add an additional keyword to the list of keywords. This is done by
       entering the keyword above the keyword list between  the  label  "Keyword"  and  the  "Add
       keyword"  button. Enter "test" and select "Add keyword". Note that the keyword will appear
       at the bottom of the existing keyword list, so you might have to scroll down  to  see  it.
       Afterwards, push the "OK" button at the bottom right of the dialog.

       You should now be back at the "Publish content on GNUnet" dialog.  Select "Execute" in the
       bottom right to close the dialog and publish your file on GNUnet! Afterwards,  you  should
       see  the  main  dialog  with  a  new  area showing the list of published files (or ongoing
       publishing operations with progress indicators).

   Searching
       Below the  menu  bar,  there  are  four  entry  widges  labeled  "Namespace",  "Keywords",
       "Anonymity"  and  "Mime-type"  (from  left  to  right).  These widgets are used to control
       searching for files in GNUnet. Between the "Keywords" and "Anonymity"  widgets,  there  is
       also  a  big  "Search"  button,  which  is used to initiate the search. We will ignore the
       "Namespace", "Anonymity" and "Mime-type" options  in  this  tutorial,  please  leave  them
       empty.  Instead,  simply enter "test" under "Keywords" and press "Search". Afterwards, you
       should immediately see a new tab labeled after your search term, followed by the (current)
       number  of  search  results  --- "(15)" in our screenshot. Note that your results may vary
       depending on what other users may have shared and how your peer is connected.

       You can now select one of the search results. Once you  do  this,  additional  information
       about  the  result  should be displayed on the right. If available, a preview image should
       appear on the top right.  Meta data describing the file  will  be  listed  at  the  bottom
       right.

       Once  a  file  is  selected,  at  the  bottom  of the search result list a little area for
       downloading appears.

   Downloading
       In the downloading area, you can select the target directory (default is "Downloads")  and
       specify  the  desired filename (by default the filename it taken from the meta data of the
       published file). Additionally, you can specify if the download  should  be  anonymous  and
       (for directories) if the download should be recursive. In most cases, you can simply start
       the download with the "Download!" button.

       Once you selected download, the progress of the download will be displayed with the search
       result. You may need to resize the result list or scroll to the right. The "Status" column
       shows the current status of the download, and "Progress" how much has been completed. When
       you close the search tab (by clicking on the "X" button next to the "test" label), ongoing
       and completed downloads are not aborted but moved to a special "*" tab.

       You can remove completed downloads from the "*" tab by clicking the cleanup button next to
       the  "*".  You  can  also abort downloads by right clicking on the respective download and
       selecting "Abort download" from the menu.

       That's it, you now know the basics for file-sharing with GNUnet!

FREQUENTLY ASKED QUESTIONS

       This    will    be    available     here     soon.      Until     then,     look     here:
       https://www.gnunet.org/en/faq.html

AUTHOR

       GNUnet Project

COPYRIGHT

       2022, GNUnet Project

                                           Aug 15, 2022                                 GNUNET(1)