/*
This file is part of GNUnet.
Copyright (C) 2007-2016 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/**
* @file topology/gnunet-daemon-topology.c
* @brief code for maintaining the overlay topology
* @author Christian Grothoff
*
* This daemon combines three functions:
* - suggesting to ATS which peers we might want to connect to
* - enforcing the F2F restrictions (by blacklisting)
* - gossping HELLOs
*
* All three require similar information (who are our friends
* impacts connectivity suggestions; connectivity suggestions
* should consider blacklisting; connectivity suggestions
* should consider available/known HELLOs; gossip requires
* connectivity data; connectivity suggestions require
* connectivity data), which is why they are combined in this
* program.
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_friends_lib.h"
#include "gnunet_constants.h"
#include "gnunet_core_service.h"
#include "gnunet_protocols.h"
#include "gnunet_peerinfo_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
#include "gnunet_ats_service.h"
/**
* At what frequency do we sent HELLOs to a peer?
*/
#define HELLO_ADVERTISEMENT_MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
/**
* After what time period do we expire the HELLO Bloom filter?
*/
#define HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
/**
* Record for neighbours, friends and blacklisted peers.
*/
struct Peer
{
/**
* Which peer is this entry about?
*/
struct GNUNET_PeerIdentity pid;
/**
* Our handle for transmitting to this peer; NULL
* if peer is not connected.
*/
struct GNUNET_MQ_Handle *mq;
/**
* Pointer to the HELLO message of this peer; can be NULL.
*/
struct GNUNET_HELLO_Message *hello;
/**
* Bloom filter used to mark which peers already got the HELLO
* from this peer.
*/
struct GNUNET_CONTAINER_BloomFilter *filter;
/**
* Next time we are allowed to transmit a HELLO to this peer?
*/
struct GNUNET_TIME_Absolute next_hello_allowed;
/**
* When should we reset the bloom filter of this entry?
*/
struct GNUNET_TIME_Absolute filter_expiration;
/**
* ID of task we use to wait for the time to send the next HELLO
* to this peer.
*/
struct GNUNET_SCHEDULER_Task *hello_delay_task;
/**
* Handle for our connectivity suggestion for this peer.
*/
struct GNUNET_ATS_ConnectivitySuggestHandle *sh;
/**
* How much would we like to connect to this peer?
*/
uint32_t strength;
/**
* Is this peer listed here because he is a friend?
*/
int is_friend;
};
/**
* Our peerinfo notification context. We use notification
* to instantly learn about new peers as they are discovered.
*/
static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify;
/**
* Our configuration.
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
* Handle to the CORE service.
*/
static struct GNUNET_CORE_Handle *handle;
/**
* Handle to the PEERINFO service.
*/
static struct GNUNET_PEERINFO_Handle *pi;
/**
* Handle to the ATS service.
*/
static struct GNUNET_ATS_ConnectivityHandle *ats;
/**
* Identity of this peer.
*/
static struct GNUNET_PeerIdentity my_identity;
/**
* All of our friends, all of our current neighbours and all peers for
* which we have HELLOs. So pretty much everyone. Maps peer identities
* to `struct Peer *` values.
*/
static struct GNUNET_CONTAINER_MultiPeerMap *peers;
/**
* Handle for reporting statistics.
*/
static struct GNUNET_STATISTICS_Handle *stats;
/**
* Blacklist (NULL if we have none).
*/
static struct GNUNET_TRANSPORT_Blacklist *blacklist;
/**
* Task scheduled to asynchronously reconsider adding/removing
* peer connectivity suggestions.
*/
static struct GNUNET_SCHEDULER_Task *add_task;
/**
* Active HELLO offering to transport service.
*/
static struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
/**
* Flag to disallow non-friend connections (pure F2F mode).
*/
static int friends_only;
/**
* Minimum number of friends to have in the
* connection set before we allow non-friends.
*/
static unsigned int minimum_friend_count;
/**
* Number of peers (friends and others) that we are currently connected to.
*/
static unsigned int connection_count