void hsep_process_msg(struct gnutella_node *n, time_t now) { unsigned int i, j, k, max, msgmax, length; hsep_triple *messaget; hsep_ctx_t *hsep; g_assert(n); g_assert(n->hsep); hsep = n->hsep; length = n->size; /* note the offset between message and local data by 1 triple */ messaget = cast_to_pointer(n->data); if (length == 0) { /* error, at least 1 triple must be present */ if (GNET_PROPERTY(hsep_debug) > 1) printf("HSEP: Node %s sent empty message\n", host_addr_port_to_string(n->addr, n->port)); return; } if (length % 24) { /* error, # of triples not an integer */ if (GNET_PROPERTY(hsep_debug) > 1) printf("HSEP: Node %s sent broken message\n", host_addr_port_to_string(n->addr, n->port)); return; } /* get N_MAX of peer servent (other_n_max) */ msgmax = length / 24; if (NODE_IS_LEAF(n) && msgmax > 1) { if (GNET_PROPERTY(hsep_debug) > 1) { printf( "HSEP: Node %s is a leaf, but sent %u triples instead of 1\n", host_addr_port_to_string(n->addr, n->port), msgmax); } return; } /* truncate if peer servent sent more triples than we need */ max = MIN(msgmax, HSEP_N_MAX); hsep_fix_endian(messaget, max); /* * Perform sanity check on received message. */ if (messaget[0][HSEP_IDX_NODES] != 1) { /* # of nodes for 1 hop must be 1 */ if (GNET_PROPERTY(hsep_debug) > 1) printf("HSEP: Node %s's message's #nodes for 1 hop is not 1\n", host_addr_port_to_string(n->addr, n->port)); return; } if (!hsep_check_monotony(messaget, max)) { if (GNET_PROPERTY(hsep_debug) > 1) printf("HSEP: Node %s's message's monotony check failed\n", host_addr_port_to_string(n->addr, n->port)); return; } if (GNET_PROPERTY(hsep_debug) > 1) { printf("HSEP: Received %d %s from node %s (msg #%u): ", max, max == 1 ? "triple" : "triples", host_addr_port_to_string(n->addr, n->port), hsep->msgs_received + 1); } /* * Update global and per-connection tables. */ for (k = 0, i = 1; k < max; k++, i++) { if (GNET_PROPERTY(hsep_debug) > 1) { char buf[G_N_ELEMENTS(messaget[0])][32]; for (j = 0; j < G_N_ELEMENTS(buf); j++) uint64_to_string_buf(messaget[k][j], buf[j], sizeof buf[0]); STATIC_ASSERT(3 == G_N_ELEMENTS(buf)); printf("(%s, %s, %s) ", buf[0], buf[1], buf[2]); } for (j = 0; j < G_N_ELEMENTS(hsep_global_table[0]); j++) { hsep_global_table[i][j] += messaget[k][j] - hsep->table[i][j]; hsep->table[i][j] = messaget[k][j]; } } if (GNET_PROPERTY(hsep_debug) > 1) puts("\n"); /* * If the peer servent sent less triples than we need, * repeat the last triple until we have enough triples */ /* Go back to last triple */ if (k > 0) k--; for (/* NOTHING */; i < G_N_ELEMENTS(hsep_global_table); i++) { for (j = 0; j < G_N_ELEMENTS(hsep_global_table[0]); j++) { hsep_global_table[i][j] += messaget[k][j] - hsep->table[i][j]; hsep->table[i][j] = messaget[k][j]; } } /* * Update counters and timestamps. */ hsep->msgs_received++; hsep->triples_received += msgmax; hsep->last_received = now; if (GNET_PROPERTY(hsep_debug) > 1) hsep_dump_table(); hsep_fire_global_table_changed(now); }
/** * Displays horizon size information. */ enum shell_reply shell_exec_horizon(struct gnutella_shell *sh, int argc, const char *argv[]) { const char *all; const option_t options[] = { { "a", &all }, }; char buf[200]; hsep_triple globaltable[HSEP_N_MAX + 1]; hsep_triple non_hsep[1]; int parsed; unsigned num_hsep, num_total; shell_check(sh); g_assert(argv); g_assert(argc > 0); parsed = shell_options_parse(sh, argv, options, G_N_ELEMENTS(options)); if (parsed < 0) return REPLY_ERROR; shell_write(sh, "100~\n"); hsep_get_global_table(globaltable, G_N_ELEMENTS(globaltable)); hsep_get_non_hsep_triple(non_hsep); num_hsep = globaltable[1][HSEP_IDX_NODES]; num_total = globaltable[1][HSEP_IDX_NODES] + non_hsep[0][HSEP_IDX_NODES]; str_bprintf(buf, sizeof buf, _("Total horizon size (%u/%u nodes support HSEP):"), num_hsep, num_total); shell_write(sh, buf); shell_write(sh, "\n\n"); print_hsep_table(sh, globaltable, HSEP_N_MAX, non_hsep); if (all) { const pslist_t *sl; hsep_triple table[HSEP_N_MAX + 1]; PSLIST_FOREACH(node_all_gnet_nodes(), sl) { const gnutella_node_t *n = sl->data; if ((!NODE_IS_ESTABLISHED(n)) || !(n->attrs & NODE_A_CAN_HSEP)) continue; shell_write(sh, "\n"); str_bprintf(buf, sizeof buf, _("Horizon size via HSEP node %s (%s):"), node_addr(n), node_peermode_to_string(n->peermode)); shell_write(sh, buf); shell_write(sh, "\n\n"); hsep_get_connection_table(n, table, G_N_ELEMENTS(table)); print_hsep_table(sh, table, NODE_IS_LEAF(n) ? 1 : HSEP_N_MAX, NULL); } } shell_write(sh, ".\n"); return REPLY_READY; }