g2_node_drop(const char *routine, gnutella_node_t *n, const g2_tree_t *t, const char *fmt, ...) { if (GNET_PROPERTY(g2_debug) || GNET_PROPERTY(log_dropped_g2)) { va_list args; char buf[256]; va_start(args, fmt); if (fmt != NULL) str_vbprintf(ARYLEN(buf), fmt, args); else buf[0] = '\0'; g_debug("%s(): dropping /%s from %s%s%s", routine, g2_tree_name(t), node_infostr(n), NULL == fmt ? "" : ": ", buf); va_end(args); } gnet_stats_count_dropped(n, MSG_DROP_G2_UNEXPECTED); if (GNET_PROPERTY(log_dropped_g2)) { g2_tfmt_tree_dump(t, stderr, G2FMT_O_PAYLEN); } }
/** * Flush current /QH2. * * Depending how the QH2 builder is configured, this either sends the message * to the target node or invokes a processing callback. */ static void g2_build_qh2_flush(struct g2_qh2_builder *ctx) { pmsg_t *mb; g_assert(ctx != NULL); g_assert(ctx->t != NULL); g_assert((ctx->n != NULL) ^ (ctx->cb != NULL)); /* * Restore the order of children in the root packet to be the order we * used when we added the nodes, since we prepend new children. */ g2_tree_reverse_children(ctx->t); /* * If sending over UDP, ask for reliable delivery of the query hit. * To be able to monitor the fate of the message, we asssociate a free * routine to it. */ if (ctx->to_udp) { struct g2_qh2_pmsg_info *pmi; WALLOC0(pmi); pmi->magic = G2_QH2_PMI_MAGIC; pmi->hub_id = nid_ref(NODE_ID(ctx->hub)); mb = g2_build_pmsg_extended(ctx->t, g2_qh2_pmsg_free, pmi); pmsg_mark_reliable(mb); } else { mb = g2_build_pmsg(ctx->t); } if (GNET_PROPERTY(g2_debug) > 3) { g_debug("%s(): flushing the following hit for " "Q2 #%s to %s%s (%d bytes):", G_STRFUNC, guid_hex_str(ctx->muid), NULL == ctx->n ? stacktrace_function_name(ctx->cb) : node_infostr(ctx->n), NULL == ctx->n ? "()" : "", pmsg_size(mb)); g2_tfmt_tree_dump(ctx->t, stderr, G2FMT_O_PAYLOAD | G2FMT_O_PAYLEN); } if (ctx->n != NULL) g2_node_send(ctx->n, mb); else (*ctx->cb)(mb, ctx->arg); ctx->messages++; ctx->current_size = 0; g2_tree_free_null(&ctx->t); }
/** * Handle message coming from G2 node. */ void g2_node_handle(gnutella_node_t *n) { g2_tree_t *t; size_t plen; enum g2_msg type; node_check(n); g_assert(NODE_TALKS_G2(n)); t = g2_frame_deserialize(n->data, n->size, &plen, FALSE); if (NULL == t) { if (GNET_PROPERTY(g2_debug) > 0 || GNET_PROPERTY(log_bad_g2)) { g_warning("%s(): cannot deserialize /%s from %s", G_STRFUNC, g2_msg_raw_name(n->data, n->size), node_infostr(n)); } if (GNET_PROPERTY(log_bad_g2)) dump_hex(stderr, "G2 Packet", n->data, n->size); return; } else if (plen != n->size) { if (GNET_PROPERTY(g2_debug) > 0 || GNET_PROPERTY(log_bad_g2)) { g_warning("%s(): consumed %zu bytes but /%s from %s had %u", G_STRFUNC, plen, g2_msg_raw_name(n->data, n->size), node_infostr(n), n->size); } if (GNET_PROPERTY(log_bad_g2)) dump_hex(stderr, "G2 Packet", n->data, n->size); hostiles_dynamic_add(n->addr, "cannot parse incoming messages", HSTL_GIBBERISH); goto done; } else if (GNET_PROPERTY(g2_debug) > 19) { g_debug("%s(): received packet from %s", G_STRFUNC, node_infostr(n)); g2_tfmt_tree_dump(t, stderr, G2FMT_O_PAYLEN); } type = g2_msg_name_type(g2_tree_name(t)); switch (type) { case G2_MSG_PI: g2_node_handle_ping(n, t); break; case G2_MSG_PO: g2_node_handle_pong(n, t); break; case G2_MSG_LNI: g2_node_handle_lni(n, t); break; case G2_MSG_KHL: g2_node_handle_khl(t); break; case G2_MSG_PUSH: handle_push_request(n, t); break; case G2_MSG_Q2: g2_node_handle_q2(n, t); break; case G2_MSG_QA: case G2_MSG_QKA: g2_node_handle_rpc_answer(n, t, type); break; case G2_MSG_QH2: search_g2_results(n, t); break; default: g2_node_drop(G_STRFUNC, n, t, "default"); break; } done: g2_tree_free_null(&t); }