⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 topology.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of GNUnet.     (C) 2001, 2002, 2003, 2004, 2006, 2007 Christian Grothoff (and other contributing authors)     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 2, 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., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file topology_default/topology.c * @brief create the GNUnet mesh topology (essentially, *   try to connect to a large diverse, random set of peers) * @author Christian Grothoff * * Topology is implemented as both a service and an * application to allow users to force loading it * (which is probably a very good idea -- otherwise * the peer will end up rather disconnected :-) */#include "platform.h"#include "gnunet_core.h"#include "gnunet_directories.h"#include "gnunet_protocols.h"#include "gnunet_identity_service.h"#include "gnunet_state_service.h"#include "gnunet_topology_service.h"#include "gnunet_transport_service.h"#include "gnunet_pingpong_service.h"#define DEBUG_TOPOLOGY GNUNET_NO#define DEBUG_LIVENESS GNUNET_NO/** * After 2 minutes on an inactive connection, probe the other * node with a ping if we have achieved less than 50% of our * connectivity goal. */#define SECONDS_PINGATTEMPT 120/** * How often should the cron-job scan for free slots (to establish * new connections)? */#define LIVE_SCAN_FREQUENCY 500 * GNUNET_CRON_MILLISECONDS/** * Value > 1 that determines the chance (1:LSE) that the cron job * actually tries to do something for a given slot. */#define LIVE_SCAN_EFFECTIVENESS 10/** * Value < 1 that determines the chance (1:LPE) that the cron job * actually tries to ping a peer that is about to time-out. */#define LIVE_PING_EFFECTIVENESS 20static GNUNET_CoreAPIForPlugins *coreAPI;static GNUNET_Identity_ServiceAPI *identity;static GNUNET_Transport_ServiceAPI *transport;static GNUNET_Pingpong_ServiceAPI *pingpong;/** * How many peers are we connected to in relation * to our ideal number?  (ideal = 1.0, too few: < 1, * too many: > 1). Maybe 0! */static double saturation = 0.0;/** * Array of our friends. */static GNUNET_PeerIdentity *friends;/** * Number of friends that we have. */static unsigned int friendCount;/** * Minimum number of friends to have in the * connection set. */static unsigned int minimum_friend_count;/** * Flag to disallow non-friend connections (pure F2F mode). */static int friends_only;/** * Record for state maintanance between scanHelperCount, * scanHelperSelect and scanForHosts. */typedef struct{  unsigned int index;  unsigned int matchCount;  long long costSelector;  GNUNET_PeerIdentity match;} IndexMatch;/** * Here in this scanning for applicable hosts, we also want to take * the protocols into account and prefer "cheap" protocols, * i.e. protocols with a low overhead. * * @param id which peer are we currently looking at * @param proto what transport protocol are we looking at * @param im updated structure used to select the peer */static intscanHelperCount (const GNUNET_PeerIdentity * id,                 unsigned short proto, int confirmed, void *data){  IndexMatch *im = data;  if (0 == memcmp (coreAPI->my_identity, id, sizeof (GNUNET_PeerIdentity)))    return GNUNET_OK;  if (coreAPI->core_slot_index_get (id) != im->index)    return GNUNET_OK;  if (GNUNET_OK == coreAPI->p2p_connection_status_check (id, NULL, NULL))    return GNUNET_OK;  if (GNUNET_YES == transport->test_available (proto))    {      im->matchCount++;      im->costSelector += transport->cost_get (proto);    }  return GNUNET_OK;}/** * Select the peer and transport that was selected based on transport * cost. * * @param id the current peer * @param proto the protocol of the current peer * @param im structure responsible for the selection process */static intscanHelperSelect (const GNUNET_PeerIdentity * id,                  unsigned short proto, int confirmed, void *data){  IndexMatch *im = data;  if (0 == memcmp (coreAPI->my_identity, id, sizeof (GNUNET_PeerIdentity)))    return GNUNET_OK;  if (coreAPI->core_slot_index_get (id) != im->index)    return GNUNET_OK;  if (GNUNET_OK == coreAPI->p2p_connection_status_check (id, NULL, NULL))    return GNUNET_OK;  if (GNUNET_YES == transport->test_available (proto))    {      im->costSelector -= transport->cost_get (proto);      if ((im->matchCount == 0) || (im->costSelector < 0))        {          im->match = *id;          return GNUNET_SYSERR;        }      im->matchCount--;    }  return GNUNET_OK;}/** * Look in the list for known hosts; pick a random host of minimal * transport cost for the hosttable at index index. When called, the * mutex of at the given index must not be hold. * * @param index for which entry in the connection table *   are we looking for peers? */static voidscanForHosts (unsigned int index){  IndexMatch indexMatch;  GNUNET_CronTime now;#if DEBUG_TOPOLOGY  GNUNET_EncName enc;#endif  if (GNUNET_network_monitor_get_load      (coreAPI->load_monitor, GNUNET_ND_UPLOAD) > 100)    return;                     /* bandwidth saturated, do not                                   push it higher! */  now = GNUNET_get_time ();  indexMatch.index = index;  indexMatch.matchCount = 0;  indexMatch.costSelector = 0;  identity->forEachHost (now, &scanHelperCount, &indexMatch);  if (indexMatch.matchCount == 0)    {#if DEBUG_TOPOLOGY      GNUNET_GE_LOG (coreAPI->ectx,                     GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |                     GNUNET_GE_DEVELOPER, "No peers found for slot %u\n",                     index);#endif      return;                   /* no matching peers found! */    }  if (indexMatch.costSelector > 0)    indexMatch.costSelector =      GNUNET_random_u64 (GNUNET_RANDOM_QUALITY_WEAK, indexMatch.costSelector);  indexMatch.match = *(coreAPI->my_identity);  identity->forEachHost (now, &scanHelperSelect, &indexMatch);  if (0 == memcmp (coreAPI->my_identity,                   &indexMatch.match, sizeof (GNUNET_PeerIdentity)))    return;                     /* should happen really rarely */  if (coreAPI->core_slot_index_get (&indexMatch.match) != index)    {      GNUNET_GE_BREAK (NULL, 0);        /* should REALLY not happen */      return;    }  if (GNUNET_OK ==      coreAPI->p2p_connection_status_check (&indexMatch.match, NULL, NULL))    {      GNUNET_GE_BREAK (NULL, 0);        /* should REALLY not happen */      return;    }#if DEBUG_TOPOLOGY  IF_GELOG (coreAPI->ectx,            GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER |            GNUNET_GE_DEVELOPER,            GNUNET_hash_to_enc (&indexMatch.match.hashPubKey, &enc));  GNUNET_GE_LOG (coreAPI->ectx,                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER |                 GNUNET_GE_DEVELOPER, "Trying to connect to peer `%s'\n",                 &enc);#endif  if (GNUNET_NO == identity->isBlacklisted (&indexMatch.match, GNUNET_YES))    {      coreAPI->ciphertext_send (&indexMatch.match, NULL, 0, 0);      identity->blacklistHost (&indexMatch.match, (unsigned int) (saturation * 5 * 60 * 60),    /* 5 hours at full saturation */                               GNUNET_NO);    }}/** * We received a GNUNET_RSA_sign of life from this host. * * @param hostId the peer that gave a GNUNET_RSA_sign of live */static voidnotifyPONG (void *cls){  GNUNET_PeerIdentity *hostId = cls;#if DEBUG_TOPOLOGY || DEBUG_LIVENESS  GNUNET_EncName enc;  IF_GELOG (coreAPI->ectx,            GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,            GNUNET_hash_to_enc (&hostId->hashPubKey, &enc));  GNUNET_GE_LOG (coreAPI->ectx,                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,                 "Received liveness confirmation from `%s'.\n", &enc);#endif  coreAPI->p2p_connection_confirm (hostId);  GNUNET_free (hostId);}/** * Check the liveness of the peer and possibly ping it. */static voidcheckNeedForPing (const GNUNET_PeerIdentity * peer, void *unused){  GNUNET_CronTime now;  GNUNET_CronTime act;  GNUNET_PeerIdentity *hi;  int ran;  ran =    GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, LIVE_PING_EFFECTIVENESS);  if (ran != 0)    return;  now = GNUNET_get_time ();  if (GNUNET_SYSERR == coreAPI->p2p_connection_last_activity_get (peer, &act))    {      GNUNET_GE_BREAK (coreAPI->ectx, 0);      return;                   /* this should not happen... */    }  if (now - act > SECONDS_PINGATTEMPT * GNUNET_CRON_SECONDS)    {      /* if we have less than 75% of the number of connections         that we would like to have, try ping-ing the other side         to keep the connection open instead of hanging up */#if DEBUG_TOPOLOGY || DEBUG_LIVENESS      GNUNET_EncName enc;      IF_GELOG (coreAPI->ectx,                GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_DEVELOPER,                GNUNET_hash_to_enc (&peer->hashPubKey, &enc));      GNUNET_GE_LOG (coreAPI->ectx,                     GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |                     GNUNET_GE_DEVELOPER,                     "Peer `%s' was inactive for %llus.  Sending PING.\n",                     &enc, (now - act) / GNUNET_CRON_SECONDS);#endif      hi = GNUNET_malloc (sizeof (GNUNET_PeerIdentity));      *hi = *peer;      if (GNUNET_OK !=          pingpong->ping (peer, &notifyPONG, hi, GNUNET_NO, rand ()))        GNUNET_free (hi);    }}#define MAX_PEERS_PER_SLOT 10/** * Call this method periodically to decrease liveness of hosts. * * @param unused not used, just to make signature type nicely */static voidcronCheckLiveness (void *unused){  int i;  int slotCount;  int active;  unsigned int minint;  int autoconnect;  autoconnect = GNUNET_GC_get_configuration_value_yesno (coreAPI->cfg,                                                         "GNUNETD",                                                         "DISABLE-AUTOCONNECT",                                                         GNUNET_NO);  slotCount = coreAPI->core_slots_count ();  if ((GNUNET_NO == autoconnect) && (saturation < 1))    {      if (saturation * MAX_PEERS_PER_SLOT >= 1)        minint = (unsigned int) (1 / saturation);      else        minint = MAX_PEERS_PER_SLOT;    /* never put more than 10 peers into a slot */      for (i = slotCount - 1; i >= 0; i--)        {          if (GNUNET_random_u32              (GNUNET_RANDOM_QUALITY_WEAK, LIVE_SCAN_EFFECTIVENESS) != 0)            continue;          if (minint > coreAPI->core_slot_test_used (i))            scanForHosts (i);        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -