/** * Send a message to target node. * * @param n the G2 node to which message should be sent * @param mb the message to sent (ownership taken, will be freed later) */ void g2_node_send(const gnutella_node_t *n, pmsg_t *mb) { node_check(n); g_assert(NODE_TALKS_G2(n)); if (NODE_IS_UDP(n)) mq_udp_node_putq(n->outq, mb, n); else if (NODE_IS_WRITABLE(n)) mq_tcp_putq(n->outq, mb, NULL); else goto drop; if (GNET_PROPERTY(log_sending_g2)) { g_debug("%s(): sending %s to %s", G_STRFUNC, g2_msg_infostr_mb(mb), node_infostr(n)); } return; drop: if (GNET_PROPERTY(log_sending_g2)) { g_debug("%s(): aborting sending %s to %s", G_STRFUNC, g2_msg_infostr_mb(mb), node_infostr(n)); } pmsg_free(mb); /* Cannot send it, free it now */ }
/** * Free routine for the extended message blocks we send to the UDP layer. */ static void g2_qh2_pmsg_free(pmsg_t *mb, void *arg) { struct g2_qh2_pmsg_info *pmi = arg; gnutella_node_t *n; g2_qh2_pmsg_info_check(pmi); g_assert(pmsg_is_extended(mb)); if (pmsg_was_sent(mb)) goto done; /* * Message was unsent, probably because the UDP address in the /Q2 was * wrong for some reason. * * If we're still connected to the hub which passed us this /Q2, then * we can relay back the /QH2 to the hub and it will hopefully be able * to deliver it back to the querying node. */ n = node_by_id(pmi->hub_id); if (NULL == n) { if (GNET_PROPERTY(g2_debug) > 1) { g_debug("%s(): could not send %s, relaying hub is gone, dropping.", G_STRFUNC, g2_msg_infostr_mb(mb)); } gnet_stats_inc_general(GNR_UDP_G2_HITS_UNDELIVERED); goto done; } else { pmsg_t *nmb; if (GNET_PROPERTY(g2_debug) > 1) { g_debug("%s(): could not send %s, giving back to %s for relaying", G_STRFUNC, g2_msg_infostr_mb(mb), node_infostr(n)); } nmb = pmsg_clone_plain(mb); pmsg_clear_reliable(nmb); g2_node_send(n, nmb); gnet_stats_inc_general(GNR_UDP_G2_HITS_REROUTED_TO_HUB); } done: nid_unref(pmi->hub_id); pmi->magic = 0; WFREE(pmi); }