
.. index::
   double: subsystem; PEERINFO

.. _PEERINFO-Subsystem:

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-_002d-Features:

PEERINFO - Features
-------------------

-  Persistent storage

-  Client notification mechanism on update

-  Periodic clean up for expired information

-  Differentiation between public and friend-only HELLO

.. _PEERINFO-_002d-Limitations:

PEERINFO - Limitations
----------------------

-  Does not perform HELLO validation

.. _DeveloperPeer-Information:

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:

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:

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:

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_002dService-Protocol:

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.

:index:`libgnunetpeerinfo <single: libgnunet; peerinfo>`
--------------------------------------------------------

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:

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:

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:

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``.
