示例#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
/**
 * Prepare reception of query hit data by building an appropriate RX stack.
 *
 * @return TRUE if we may continue with the download, FALSE if the search
 * was already closed in the GUI.
 */
gboolean
browse_host_dl_receive(
	struct browse_ctx *bc, gnet_host_t *host, wrap_io_t *wio,
	const char *vendor, guint32 flags)
{
	g_assert(bc != NULL);

	if (bc->closed)
		return FALSE;

	gnet_host_copy(&bc->host, host);
	bc->vendor = atom_str_get(vendor);

	/*
	 * Freeing of the RX stack must be asynchronous: each time we establish
	 * a new connection, dismantle the previous stack.  Otherwise the RX
	 * stack will be freed when the corresponding download structure is
	 * reclaimed.
	 */

	if (bc->rx != NULL) {
		rx_free(bc->rx);
		bc->rx = NULL;
	}

	{
		struct rx_link_args args;

		args.cb = &browse_rx_link_cb;
		args.bws = bsched_in_select_by_addr(gnet_host_get_addr(&bc->host));
		args.wio = wio;

		bc->rx = rx_make(bc, &bc->host, rx_link_get_ops(), &args);
	}

	if (flags & BH_DL_CHUNKED) {
		struct rx_chunk_args args;

		args.cb = &browse_rx_chunk_cb;

		bc->rx = rx_make_above(bc->rx, rx_chunk_get_ops(), &args);
	}

	if (flags & BH_DL_INFLATE) {
		struct rx_inflate_args args;

		args.cb = &browse_rx_inflate_cb;

		bc->rx = rx_make_above(bc->rx, rx_inflate_get_ops(), &args);
	}

	rx_set_data_ind(bc->rx, browse_data_ind);
	rx_enable(bc->rx);

	return TRUE;
}
示例#3
0
/**
 * Initialize the browse host context.
 */
struct browse_ctx *
browse_host_dl_create(gpointer owner, gnet_host_t *host, gnet_search_t sh)
{
	struct browse_ctx *bc;

	WALLOC0(bc);
	bc->owner = owner;
	gnet_host_copy(&bc->host, host);
	bc->sh = sh;

	return bc;
}
示例#4
0
/**
 * Initialize the THEX download context.
 */
struct thex_download *
thex_download_create(void *owner, gnet_host_t *host,
	const struct sha1 *sha1, const struct tth *tth, filesize_t filesize)
{
	static const struct thex_download zero_ctx;
	struct thex_download *ctx;

	g_return_val_if_fail(host, NULL);
	g_return_val_if_fail(sha1, NULL);
	g_return_val_if_fail(tth, NULL);

	WALLOC(ctx);
	*ctx = zero_ctx;
	ctx->owner = owner;
	gnet_host_copy(&ctx->host, host);
	ctx->sha1 = atom_sha1_get(sha1);
	ctx->tth = atom_tth_get(tth);
	ctx->filesize = filesize;

	return ctx;
}
示例#5
0
文件: udp.c 项目: MrJoe/gtk-gnutella
/**
 * Upon reception of an UDP pong, check whether we had a matching registered
 * ping bearing the given MUID.
 *
 * If there was a callback atttached to the reception of a reply, invoke it
 * before returning UDP_PONG_HANDLED.
 *
 * The ``host'' paramaeter MUST be a stack or static pointer to a gnet_host_t,
 * and NOT the address of a dynamically allocated host because gnet_host_copy()
 * is going to be used on it.
 *
 * @param n		the gnutella node replying
 * @param host	if non-NULL, filled with the host to whom we sent the ping
 *
 * @return TRUE if indeed this was a reply for a ping we sent.
 */
enum udp_pong_status
udp_ping_is_registered(const struct gnutella_node *n, gnet_host_t *host)
{
	const struct guid *muid = gnutella_header_get_muid(&n->header);

	if (udp_pings) {
		struct udp_ping *ping;

		ping = hash_list_remove(udp_pings, muid);
		if (ping != NULL) {
			if (host != NULL) {
				/*
				 * Let caller know the exact IP:port of the host we contacted,
				 * since the replying party can use a different port (which
				 * we may not be able to contact, whereas we know the targeted
				 * port did cause a reply).
				 */
				gnet_host_copy(host, ping->host);
			}

			if (ping->callback) {
				(*ping->callback->cb)(UDP_PING_REPLY, n, ping->callback->data);
				if (ping->callback->multiple) {
					ping->callback->got_reply = TRUE;
					ping->added = tm_time();	/* Delay expiration */
					hash_list_append(udp_pings, ping);
				} else {
					udp_ping_free(ping);
				}
				return UDP_PONG_HANDLED;
			}
			udp_ping_free(ping);
			return UDP_PONG_SOLICITED;
		}
	}
	return UDP_PONG_UNSOLICITED;
}
示例#6
0
/**
 * Createion routine for a driver to be stacked above specified lower `ltx'.
 *
 * @return NULL if there is an initialization problem.
 */
txdrv_t *
tx_make_above(txdrv_t *ltx, const struct txdrv_ops *ops, void *args)
{
	txdrv_t *tx;

	tx_check(ltx);
	g_assert(ltx->upper == NULL);		/* Nothing above yet */
	g_assert(ops);

	WALLOC0(tx);
	tx->magic = TXDRV_MAGIC;
	tx->owner = ltx->owner;
	gnet_host_copy(&tx->host, &ltx->host);
	tx->ops = ops;
	tx->upper = NULL;
	tx->lower = ltx;

	if (NULL == TX_INIT(tx, args))		/* Let the heir class initialize */
		return NULL;

	tx_attached(tx->lower, tx);

	return tx;
}
示例#7
0
/**
 * Prepare reception of THEX data by building an appropriate RX stack.
 *
 * @return TRUE if we may continue with the download.
 */
bool
thex_download_receive(struct thex_download *ctx,
	filesize_t content_length,
	gnet_host_t *host, struct wrap_io *wio, uint32 flags)
{
	g_assert(ctx != NULL);

	gnet_host_copy(&ctx->host, host);

	/*
	 * Freeing of the RX stack must be asynchronous: each time we establish
	 * a new connection, dismantle the previous stack.  Otherwise the RX
	 * stack will be freed when the corresponding download structure is
	 * reclaimed.
	 */

	if (ctx->rx != NULL) {
		rx_free(ctx->rx);
		ctx->rx = NULL;
	}

	/*
	 * If there is a Content-Length indication in the HTTP reply, it is
	 * supplied here and will be used as a limit of the data we'll read.
	 *
	 * If there was none (for instance if the output is chunked), then 0
	 * is given and we'll use a hardwired maximum.
	 */

	if (content_length > MAX_INT_VAL(size_t))
		return FALSE;

	ctx->max_size = content_length ?
		(size_t) content_length : THEX_DOWNLOAD_MAX_SIZE;

	{
		struct rx_link_args args;

		args.cb = &thex_rx_link_cb;
		args.bws = bsched_in_select_by_addr(gnet_host_get_addr(&ctx->host));
		args.wio = wio;

		ctx->rx = rx_make(ctx, &ctx->host, rx_link_get_ops(), &args);
	}

	if (flags & THEX_DOWNLOAD_F_CHUNKED) {
		struct rx_chunk_args args;

		args.cb = &thex_rx_chunk_cb;

		ctx->rx = rx_make_above(ctx->rx, rx_chunk_get_ops(), &args);
	}

	if (flags & THEX_DOWNLOAD_F_INFLATE) {
		struct rx_inflate_args args;

		args.cb = &thex_rx_inflate_cb;

		ctx->rx = rx_make_above(ctx->rx, rx_inflate_get_ops(), &args);
	}

	rx_set_data_ind(ctx->rx, thex_download_data_ind);
	rx_enable(ctx->rx);

	return TRUE;
}