📄 traffic.c
字号:
/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2006 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 applications/traffic/traffic.c * @brief tracks current traffic patterns * @author Christian Grothoff * * Module to keep track of recent amounts of p2p traffic on the local * GNUnet node. Uses roughly 6 kb of memory given the current * settings. The current settings allow the minimal anonymity * requirements that can be confirmed to reach 15 peers in the last 32 * minutes (for any given message type). If significantly higher * levels are required, the current code would need to be recompiled * with different values. I currently do not belive we should make * better traffic tracking even an option. */#include "platform.h"#include "gnunet_util.h"#include "gnunet_protocols.h"#include "gnunet_traffic_service.h"#include "gnunet_stats_service.h"#include "traffic.h"#define DEBUG 0/** * How many time-units back do we keep the history of? (must really * be <=32 since we use the 32 bit in an unsigned int). The memory * impact of this value n is 4 * 3 * MAX_MESSAGE_ID * n, which is for * the default of n=32 with the current MAX_MESSAGE_ID being roughly a * dozen less than 2k. */#define HISTORY_SIZE 32static GNUNET_Stats_ServiceAPI *stats;static int stat_traffic_received_by_type[GNUNET_P2P_PROTO_MAX_USED];static int stat_pt_traffic_received_by_type[GNUNET_P2P_PROTO_MAX_USED];static int stat_traffic_transmitted_by_type[GNUNET_P2P_PROTO_MAX_USED];/** * Macro to access the slot at time "t" in the history. */#define HS_SLOT(a) ((a) % HISTORY_SIZE)/** * Of how many peers do we keep track per message type * about "recent" interactions? The memory impact of * this value n is 8 * 3 * MAX_MESSAGE_ID * n. The current * number of messages is roughly a dozen, so the memory * impact is about 200 bytes * n, or for the default * of n=15 it is 3kb. */#define MAX_PEER_IDs 15/** * Information about when a peer was last involved * in a message of the given type. */typedef struct{ /** * The ".a" member of the Host identity of the peer. */ int peerIdentity_a; /** * The time of the interaction. */ unsigned int time;} PeerDate;/** * Numbers for one receive/send/self-send type. */typedef struct{ /** * When was this record last updated? */ GNUNET_CronTime lastUpdate; /** * Time slots for processing (shifted bitvector) */ unsigned int slots; /** * "peerCount" identities of the peers that we interacted with * most recently (abreviated identities plus timestamps) */ PeerDate peers[MAX_PEER_IDs]; /** * How many messages were processed? (rotating buffer) */ unsigned int count[HISTORY_SIZE]; /** * Average sizes (rotating buffer) */ double avgSize[HISTORY_SIZE];} DirectedTrafficCounter;/** * Type of the internal traffic counters. */typedef struct{ /** * Statistics for sending */ DirectedTrafficCounter send; /** * Statistics for receiving */ DirectedTrafficCounter receive;} TrafficCounter;/** * Lock to synchronize access. */static struct GNUNET_Mutex *lock;/** * Highest message type seen so far. */static unsigned int max_message_type = 0;/** * The actual counters. */static TrafficCounter **counters = NULL;#if DEBUGstatic unsigned long long server_port;#endifstatic GNUNET_CoreAPIForPlugins *coreAPI;/** * Update the use table dtc. A message of the given * size was processed interacting with a peer with * the given peerId. */static voidupdateUse (DirectedTrafficCounter * dtc, unsigned short size, int peerId, int expireOnly){ GNUNET_CronTime now; GNUNET_CronTime delta; unsigned int unitNow; unsigned int deltaUnits; unsigned int minPeerId; unsigned int minPeerTime; unsigned int i; unsigned int slot; now = GNUNET_get_time (); unitNow = now / GNUNET_TRAFFIC_TIME_UNIT; delta = now - dtc->lastUpdate; dtc->lastUpdate = now; deltaUnits = delta / GNUNET_TRAFFIC_TIME_UNIT; if (GNUNET_NO == expireOnly) { /* update peer identities */ minPeerTime = 0; minPeerId = 0; for (i = 0; i < MAX_PEER_IDs; i++) { if (dtc->peers[i].time < minPeerTime) minPeerId = i; if (dtc->peers[i].peerIdentity_a == peerId) { minPeerId = i; break; /* if the peer is already listed, re-use that slot & update the time! */ } } dtc->peers[minPeerId].time = unitNow; dtc->peers[minPeerId].peerIdentity_a = peerId; } /* update expired slots: set appropriate slots to 0 */ if (deltaUnits > HISTORY_SIZE) deltaUnits = HISTORY_SIZE; for (i = 0; i < deltaUnits; i++) { dtc->count[HS_SLOT (unitNow - HISTORY_SIZE - i)] = 0; dtc->avgSize[HS_SLOT (unitNow - HISTORY_SIZE - i)] = 0.0; } if (GNUNET_NO == expireOnly) { int devideBy; /* update slots */ dtc->slots = 0x80000000 | (dtc->slots >> deltaUnits); /* recompute average, increment count */ slot = HS_SLOT (unitNow); dtc->count[slot]++; devideBy = dtc->count[slot]; if (devideBy <= 0) dtc->avgSize[slot] = 0; /* how can this happen? */ else dtc->avgSize[slot] = ((dtc->avgSize[slot] * (dtc->count[slot] - 1)) + size) / devideBy; }}/** * Build the traffic counter summary to send it over * the network. * @param res where to write the summary to * @param dtc the internal traffic counter to convert * @param tcType the type of the counter (for the flags) * @param countTimeUnits for how long ago should we take * the history into consideration (max is HISTORY_SIZE). * @param msgType what is the type of the message that the dtc is for? */static voidbuildSummary (TRAFFIC_COUNTER * res, DirectedTrafficCounter * dtc, unsigned int tcType, unsigned int countTimeUnits, unsigned short msgType){ unsigned int i; unsigned short peerCount; GNUNET_CronTime now; unsigned int unitNow; unsigned int msgCount; unsigned long long totalMsgSize; updateUse (dtc, 0, 0, GNUNET_YES); /* expire old entries */ now = GNUNET_get_time (); unitNow = now / GNUNET_TRAFFIC_TIME_UNIT; /* count number of peers that we interacted with in the last countTimeUnits */ peerCount = 0; for (i = 0; i < MAX_PEER_IDs; i++) if (dtc->peers[i].time > now - countTimeUnits) peerCount++; res->flags = htons (tcType | peerCount); /* determine number of messages and average size */ msgCount = 0; totalMsgSize = 0; for (i = 0; i < countTimeUnits; i++) { unsigned int slot = HS_SLOT (unitNow - i); totalMsgSize += dtc->count[slot] * dtc->avgSize[slot]; msgCount += dtc->count[slot]; } res->count = htonl (msgCount); res->type = htons (msgType); if (msgCount > 0) res->avrg_size = htonl (totalMsgSize / msgCount); else res->avrg_size = 0; res->time_slots = htonl (dtc->slots);}/** * Build a reply message for the client. */static CS_traffic_info_MESSAGE *buildReply (unsigned int countTimeUnits){ CS_traffic_info_MESSAGE *reply; unsigned int count; unsigned int i; GNUNET_mutex_lock (lock); count = 0; for (i = 0; i < max_message_type; i++) if (counters[i] != NULL) { if (counters[i]->send.slots != 0) count++; if (counters[i]->receive.slots != 0) count++; } reply = GNUNET_malloc (sizeof (CS_traffic_info_MESSAGE) + count * sizeof (TRAFFIC_COUNTER)); reply->header.type = htons (GNUNET_CS_PROTO_TRAFFIC_INFO); reply->header.size = htons (sizeof (CS_traffic_info_MESSAGE) + count * sizeof (TRAFFIC_COUNTER)); reply->count = htonl (count); count = 0; for (i = 0; i < max_message_type; i++) if (counters[i] != NULL) { if (counters[i]->send.slots != 0) buildSummary (&((CS_traffic_info_MESSAGE_GENERIC *) reply)->counters [count++], &counters[i]->send, GNUNET_TRAFFIC_TYPE_SENT, countTimeUnits, i); if (counters[i]->receive.slots != 0) buildSummary (&((CS_traffic_info_MESSAGE_GENERIC *) reply)->counters [count++], &counters[i]->receive, GNUNET_TRAFFIC_TYPE_RECEIVED, countTimeUnits, i); } GNUNET_mutex_unlock (lock); return reply;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -