return out;
}
+/** Return a newly allocated string holding our bridge usage stats by
+ * country in a format suitable for inclusion in our heartbeat
+ * message. Return NULL on failure. */
+char *
+format_client_stats_heartbeat(time_t now)
+{
+ char *out = NULL;
+ int n_clients = 0;
+ clientmap_entry_t **ent;
+ double elapsed_time = 0;
+
+ if (!start_of_bridge_stats_interval)
+ return NULL; /* Not initialized. */
+
+ /* count unique IPs */
+ HT_FOREACH(ent, clientmap, &client_history) {
+ /* only count directly connecting clients */
+ if ((*ent)->action != GEOIP_CLIENT_CONNECT)
+ continue;
+ n_clients++;
+ }
+
+ elapsed_time = difftime(now, start_of_bridge_stats_interval);
+
+ tor_asprintf(&out, "Heartbeat: "
+ "Since the last %ld hours, I have seen %d unique clients.",
+ tor_lround(elapsed_time / 3600),
+ n_clients);
+
+ return out;
+}
+
/** Write bridge statistics to $DATADIR/stats/bridge-stats and return
* when we should next try to write statistics. */
time_t
void geoip_bridge_stats_term(void);
const char *geoip_get_bridge_stats_extrainfo(time_t);
char *geoip_get_bridge_stats_controller(time_t);
+char *format_client_stats_heartbeat(time_t now);
#endif
#include "router.h"
#include "circuitlist.h"
#include "main.h"
+#include "geoip.h"
/** Return the total number of circuits. */
static int
const routerinfo_t *me;
const or_options_t *options = get_options();
- (void)now;
if (public_server_mode(options)) {
/* Let's check if we are in the current cached consensus. */
100*(U64_TO_DBL(stats_n_data_bytes_packaged) /
U64_TO_DBL(stats_n_data_cells_packaged*RELAY_PAYLOAD_SIZE)) );
+ if (options->BridgeRelay) {
+ char *msg = NULL;
+ msg = format_client_stats_heartbeat(now);
+ if (msg)
+ log_notice(LD_HEARTBEAT, "%s", msg);
+ tor_free(msg);
+ }
+
tor_free(uptime);
tor_free(bw_sent);
tor_free(bw_rcvd);