📄 advertising.c
字号:
#endif return GNUNET_SYSERR; } /* Ok, must play PING-PONG. Add the hello to the temporary (in-memory only) buffer to make it available for a short time in order to play PING-PONG */ identity->addHostTemporarily (msg); now = GNUNET_get_time (); if ((sender != NULL) && ((now - lasthelloMsg) / GNUNET_CRON_SECONDS) * (GNUNET_network_monitor_get_limit (coreAPI->load_monitor, GNUNET_ND_DOWNLOAD)) < GNUNET_sizeof_hello (msg) * 10) { /* do not use more than about 10% of the available bandwidth to VERIFY hellos (by sending our own with a PING). This does not affect the hello advertising. Sure, we should not advertise much more than what other peers can verify, but the problem is that buggy/ malicious peers can spam us with hellos, and we don't want to follow that up with massive hello-ing by ourselves. */#if DEBUG_ADVERTISING GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_BULK | GNUNET_GE_USER, "Not enough resources to verify HELLO message at this time (%u * %u < %u * 10)\n", (unsigned int) ((now - lasthelloMsg) / GNUNET_CRON_SECONDS), (unsigned int) GNUNET_network_monitor_get_limit (coreAPI->load_monitor, GNUNET_ND_DOWNLOAD), (unsigned int) GNUNET_sizeof_hello (msg));#endif if (stats != NULL) stats->change (stat_hello_discard, 1); return GNUNET_SYSERR; } lasthelloMsg = now; /* Establish session as advertised in the hello */ tsession = transport->connect (msg, __FILE__, GNUNET_NO); if (tsession == NULL) { if (stats != NULL) stats->change (stat_hello_no_transport, 1);#if DEBUG_ADVERTISING IF_GELOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, GNUNET_hash_to_enc (&msg->senderIdentity.hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Failed to connect to `%s'. Verification failed.\n", &enc);#endif return GNUNET_SYSERR; /* could not connect */ } /* build message to send, ping must contain return-information, such as a selection of our hellos... */ mtu = transport->mtu_get (tsession->ttype); if (mtu == 0) { mtu = 2048; /* bound size */ } else { GNUNET_GE_ASSERT (ectx, mtu > GNUNET_P2P_MESSAGE_OVERHEAD); mtu -= GNUNET_P2P_MESSAGE_OVERHEAD; } copy = GNUNET_malloc (GNUNET_sizeof_hello (msg)); memcpy (copy, msg, GNUNET_sizeof_hello (msg)); ping = pingpong->pingUser (&msg->senderIdentity, &callAddHost, copy, GNUNET_YES, rand ()); if (ping == NULL) { res = GNUNET_SYSERR; GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, _("Could not send HELLO+PING, ping buffer full.\n")); transport->disconnect (tsession, __FILE__); if (stats != NULL) stats->change (stat_hello_ping_busy, 1); return GNUNET_SYSERR; } buffer = GNUNET_malloc (mtu); if (mtu > ntohs (ping->size)) { helloEnd = transport->hello_advertisements_get (mtu - ntohs (ping->size), buffer); GNUNET_GE_ASSERT (ectx, mtu - ntohs (ping->size) >= helloEnd); } else { helloEnd = -2; } if (helloEnd <= 0) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER, _ ("Failed to create an advertisement for this peer. Will not send PING.\n")); GNUNET_free (buffer); if (stats != NULL) stats->change (stat_hello_noselfad, 1); transport->disconnect (tsession, __FILE__);#if DEBUG_ADVERTISING IF_GELOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, GNUNET_hash_to_enc (&msg->senderIdentity.hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Failed to connect advertisement for myself. Verification failed.\n", &enc);#endif return GNUNET_SYSERR; } res = GNUNET_OK; memcpy (&buffer[helloEnd], ping, ntohs (ping->size)); helloEnd += ntohs (ping->size); GNUNET_free (ping); /* ok, finally we can send! */ if ((res == GNUNET_OK) && (GNUNET_SYSERR == coreAPI->plaintext_send (tsession, buffer, helloEnd))) { if (stats != NULL) stats->change (stat_hello_send_error, 1);#if DEBUG_ADVERTISING IF_GELOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, GNUNET_hash_to_enc (&msg->senderIdentity.hashPubKey, &enc)); GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Failed to transmit advertisement for myself. Verification failed.\n", &enc);#endif res = GNUNET_SYSERR; } if (res == GNUNET_OK) { if (stats != NULL) stats->change (stat_plaintextPingSent, 1); } GNUNET_free (buffer); if (GNUNET_SYSERR == transport->disconnect (tsession, __FILE__)) res = GNUNET_SYSERR; return res;}typedef struct{ /* the hello message */ GNUNET_MessageHello *m; /* send the hello in 1 out of n cases */ int n;} SendData;static intbroadcastHelper (const GNUNET_PeerIdentity * hi, const unsigned short proto, int confirmed, void *cls){ SendData *sd = cls; GNUNET_MessageHello *hello; GNUNET_TSession *tsession; int prio;#if DEBUG_ADVERTISING GNUNET_EncName other;#endif if (confirmed == GNUNET_NO) return GNUNET_OK; if (proto == GNUNET_TRANSPORT_PROTOCOL_NUMBER_NAT) { sd->n--; return GNUNET_OK; /* don't advertise NAT addresses via broadcast */ } if ((sd->n != 0) && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, sd->n) != 0)) return GNUNET_OK;#if DEBUG_ADVERTISING IF_GELOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, GNUNET_hash_to_enc (&hi->hashPubKey, &other)); GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Entering with target `%s'.\n", &other);#endif if (0 == memcmp (hi, coreAPI->my_identity, sizeof (GNUNET_PeerIdentity))) return GNUNET_OK; /* never advertise to myself... */ prio = (int) getConnectPriority (); if (prio >= GNUNET_EXTREME_PRIORITY) prio = GNUNET_EXTREME_PRIORITY / 4; if (GNUNET_OK == coreAPI->p2p_connection_status_check (hi, NULL, NULL)) { coreAPI->ciphertext_send (hi, &sd->m->header, prio, HELLO_BROADCAST_FREQUENCY); if (stats != NULL) stats->change (stat_hello_out, 1); return GNUNET_OK; } /* with even lower probability (with n peers trying to contact with a probability of 1/n^2, we get a probability of 1/n for this, which is what we want: fewer attempts to contact fresh peers as the network grows): */ if ((sd->n != 0) && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, sd->n) != 0)) return GNUNET_OK; /* establish short-lived connection, send, tear down */ hello = identity->identity2Hello (hi, proto, GNUNET_NO); if (NULL == hello) return GNUNET_OK; tsession = transport->connect (hello, __FILE__, GNUNET_YES); GNUNET_free (hello); if (tsession == NULL) return GNUNET_OK; /* could not connect */ if (stats != NULL) stats->change (stat_hello_out, 1); coreAPI->plaintext_send (tsession, (char *) &sd->m->header, GNUNET_sizeof_hello (sd->m)); transport->disconnect (tsession, __FILE__); return GNUNET_OK;}/** * Tell a couple of random hosts on the currentKnownHost list * that we exist (called for each transport)... */static voidbroadcasthelloTransport (GNUNET_TransportAPI * tapi, void *cls){ const int *prob = cls; SendData sd; GNUNET_CronTime now; if (GNUNET_network_monitor_get_load (coreAPI->load_monitor, GNUNET_ND_UPLOAD) > 100) return; /* network load too high... */ if (((*prob) != 0) && (0 != GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, *prob))) return; /* ignore */ now = GNUNET_get_time (); sd.n = identity->forEachHost (now, NULL, NULL); /* just count */ sd.m = transport->hello_create (tapi->protocol_number); if (sd.m == NULL) return;#if DEBUG_ADVERTISING GNUNET_GE_LOG (ectx, GNUNET_GE_INFO | GNUNET_GE_REQUEST | GNUNET_GE_USER, _("Advertising my transport %d to selected peers.\n"), tapi->protocol_number);#endif identity->addHost (sd.m); if (sd.n < 1) { if (identity->forEachHost (0, NULL, NULL) == 0) GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER, _("Announcing ourselves pointless: " "no other peers are known to us so far.\n")); GNUNET_free (sd.m); return; /* no point in trying... */ } identity->forEachHost (now, &broadcastHelper, &sd); GNUNET_free (sd.m);}/** * Tell a couple of random hosts on the currentKnownHost list * that we exist... */static voidbroadcasthello (void *unused){ unsigned int i; if (GNUNET_network_monitor_get_load (coreAPI->load_monitor, GNUNET_ND_UPLOAD) > 100) return; /* network load too high... */ if (GNUNET_cpu_get_load (coreAPI->ectx, coreAPI->cfg) > 100) return; /* CPU load too high... */ i = transport->iterate_available (NULL, NULL); if (i > 0) transport->iterate_available (&broadcasthelloTransport, &i);}typedef struct{ GNUNET_MessageHello *msg; int prob;} FCC;static voidforwardCallback (const GNUNET_PeerIdentity * peer, void *cls){ FCC *fcc = cls; if (GNUNET_network_monitor_get_load (coreAPI->load_monitor, GNUNET_ND_UPLOAD) > 100) return; /* network load too high... */ if ((fcc->prob != 0) && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, fcc->prob) != 0)) return; /* only forward with a certain chance */ if (0 == memcmp (&peer->hashPubKey, &fcc->msg->senderIdentity.hashPubKey, sizeof (GNUNET_HashCode))) return; /* do not bounce the hello of a peer back to the same peer! */ if (stats != NULL) stats->change (stat_hello_fwd, 1); coreAPI->ciphertext_send (peer, &fcc->msg->header, 0, /* priority */ HELLO_BROADCAST_FREQUENCY);}/** * Forward hellos from all known hosts to all connected hosts. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -