示例#1
0
/**
 * Attach meta information to supplied message block, returning a possibly
 * new message block to use.
 */
static pmsg_t *
mq_udp_attach_metadata(pmsg_t *mb, const gnet_host_t *to)
{
	pmsg_t *result;

	if (pmsg_is_extended(mb)) {
		struct mq_udp_info_extended *mi;

		WALLOC(mi);
		gnet_host_copy(&mi->to, to);
		result = mb;

		/*
		 * Replace original free routine with the new one, saving the original
		 * metadata and its free routine in the new metadata for later
		 * transparent dispatching at free time.
		 */

		mi->orig_free = pmsg_replace_ext(mb,
			mq_udp_pmsg_free_extended, mi, &mi->orig_arg);

	} else {
		struct mq_udp_info *mi;

		WALLOC(mi);
		gnet_host_copy(&mi->to, to);
		result = pmsg_clone_extend(mb, mq_udp_pmsg_free, mi);
		pmsg_free(mb);
	}

	g_assert(pmsg_is_extended(result));

	return result;
}
示例#2
0
/**
 * Free routine for plain metadata.
 */
static void
mq_udp_pmsg_free(pmsg_t *mb, void *arg)
{
	struct mq_udp_info *mi = arg;

	g_assert(pmsg_is_extended(mb));

	WFREE(mi);
}
示例#3
0
/**
 * Free routine for extended metadata, invoking the original free routine
 * on the original metadata.
 */
static void
mq_udp_pmsg_free_extended(pmsg_t *mb, void *arg)
{
	struct mq_udp_info_extended *mi = arg;

	g_assert(pmsg_is_extended(mb));

	if (mi->orig_free)
		(*mi->orig_free)(mb, mi->orig_arg);

	WFREE(mi);
}
示例#4
0
/**
 * 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);
}
示例#5
0
/**
 * Shallow cloning of message, result is referencing the same data.
 *
 * This is not the same thing as pmsg_ref() because here a new message block
 * is created (albeit the data are shared with the original message).
 */
pmsg_t *
pmsg_clone(pmsg_t *mb)
{
	if (pmsg_is_extended(mb)) {
		return pmsg_clone_ext(cast_to_pmsg_ext(mb));
	} else {
		pmsg_t *nmb;

		pmsg_check_consistency(mb);
		WALLOC(nmb);
		*nmb = *mb;					/* Struct copy */
		nmb->m_refcnt = 1;
		pdata_addref(nmb->m_data);

		return nmb;
	}
}
示例#6
0
文件: sq.c 项目: MrJoe/gtk-gnutella
/**
 * Free routine for a query message.
 */
static void
sq_pmsg_free(pmsg_t *mb, void *arg)
{
	struct smsg_info *smi = arg;

	g_assert(pmsg_is_extended(mb));

	/*
	 * If we're still in leaf mode, let the search know that we sent a
	 * query for it to the specified node ID.
	 */

	if (settings_is_leaf())
		search_notify_sent(smi->shandle, smi->node_id);

	nid_unref(smi->node_id);
	WFREE(smi);
}
示例#7
0
/**
 * Free routine for query hit message.
 */
static void
dh_pmsg_free(pmsg_t *mb, void *arg)
{
	struct dh_pmsg_info *pmi = arg;
	const struct guid *muid;
	dqhit_t *dh;

	g_assert(pmsg_is_extended(mb));

	muid = gnutella_header_get_muid(pmsg_start(mb));
	dh = dh_locate(muid);

	if (dh == NULL)
		goto cleanup;

	/*
	 * It can happen that an initial query hit comes and is queued for
	 * transmission, but the node is so clogged we don't actually send
	 * it before the entry expires in our tracking tables.  When we later
	 * get the ACK that it was sent, we can therefore get obsolete data.
	 * Hence we're very careful updating the stats, and we can't assert
	 * that we're tracking everything correctly.
	 *		--RAM, 2004-09-04
	 */

	if (pmsg_was_sent(mb))
		dh->hits_sent += pmi->hits;

	if (dh->msg_queued == 0)	/* We did not expect this ACK */
		goto cleanup;

	dh->msg_queued--;

	if (dh->hits_queued >= pmi->hits)
		dh->hits_queued -= pmi->hits;

	/* FALL THROUGH */
cleanup:
	WFREE(pmi);
}
示例#8
0
/**
 * Free all message blocks, and decrease ref count on all data buffers.
 *
 * If the message block is referenced by more than one place, simply
 * decrease its reference count.  No freeing occurs and the free routine
 * is therefore not invoked.
 */
void
pmsg_free(pmsg_t *mb)
{
	pdata_t *db = mb->m_data;

	pmsg_check_consistency(mb);
	g_assert(mb->m_refcnt != 0);

	/*
	 * Don't free anything if refcnt != 1.
	 */

	if (mb->m_refcnt > 1U) {
		mb->m_refcnt--;
		return;
	}

	/*
	 * Invoke free routine on extended message block.
	 */

	if (pmsg_is_extended(mb)) {
		pmsg_ext_t *emb = cast_to_pmsg_ext(mb);
		if (emb->m_free)
			(*emb->m_free)(mb, emb->m_arg);
		WFREE0(emb);
	} else {
		WFREE0(mb);
	}

	/*
	 * Unref buffer data only after possible free routine was
	 * invoked, since it may cause a free, preventing access to
	 * memory from within the free routine.
	 */

	pdata_unref(db);
}
示例#9
0
/**
 * Free routine for our extended message blocks.
 */
static void
revent_pmsg_free(pmsg_t *mb, void *arg)
{
	struct revent_pmsg_info *pmi = arg;
	struct revent_ops *ops;
	void *obj;

	pmi_check(pmi);
	g_assert(pmsg_is_extended(mb));

	ops = pmi->ops;

	/*
	 * It is possible that whilst the message was in the message queue,
	 * the operation was terminated.  Therefore, we need to ensure that the
	 * recorded user is still alive.
	 */

	obj = (*ops->is_alive)(pmi->rid);
	if (NULL == obj) {
		if (*ops->debug > 2)
			g_debug("DHT %s[%s] late UDP message %s",
				ops->name, nid_to_string(&pmi->rid),
				pmsg_was_sent(mb) ? "sending" : "dropping");
		goto cleanup;
	}

	/*
	 * Signal message freeing, so that user structure can decrement the
	 * amount of pending messsages if necessary.
	 */

	if (ops->freeing_msg)
		(*ops->freeing_msg)(obj);

	/*
	 * If the RPC callback triggered before the UDP message queue could
	 * process the message on the way out, then we don't need to do anything
	 * as the RPC is already dead and has been processed as such...
	 */

	if (pmi->rpc_done)
		goto cleanup;

	pmi->rpi->pmi = NULL;			/* Break x-ref as message was processed */

	if (pmsg_was_sent(mb)) {
		knode_t *kn = pmi->kn;

		/*
		 * Message was successfully sent from the queue.
		 */

		kn->last_sent = tm_time();

		if (ops->msg_sent)
			(*ops->msg_sent)(obj, mb);

		if (*ops->debug > 4)
			g_debug("DHT %s[%s] sent %s (%d bytes) to %s, RTT=%u",
				ops->name, nid_to_string(&pmi->rid),
				kmsg_infostr(pmsg_phys_base(mb)),
				pmsg_written_size(mb), knode_to_string(kn), kn->rtt);
	} else {
		knode_t *kn = pmi->kn;
		guid_t *muid;

		if (*ops->debug > 2)
			g_debug("DHT %s[%s] message %s%u to %s dropped by UDP queue",
				ops->name, nid_to_string(&pmi->rid),
				ops->udata_name, pmi->rpi->udata,
				knode_to_string(kn));

		/*
		 * Message was not sent and dropped by the queue.
		 */

		if (ops->msg_dropped)
			(*ops->msg_dropped)(obj, kn, mb);

		/*
		 * Cancel the RPC, since the message was never sent out...
		 * The MUID is at the start of the message.
		 */

		g_assert(pmsg_written_size(mb) > GUID_RAW_SIZE);

		muid = cast_to_guid_ptr(pmsg_phys_base(mb));
		dht_rpc_cancel(muid);

		if (ops->rpc_cancelled)
			(*ops->rpc_cancelled)(obj, pmi->rpi->udata);

		revent_rpi_free(pmi->rpi);	/* Cancel does not invoke RPC callback */
	}

cleanup:
	revent_pmi_free(pmi);
}