Ejemplo n.º 1
0
/**
 * Read data from the message buffer we just received.
 *
 * @return TRUE whilst we think there is more data to read in the buffer.
 */
static gboolean
browse_data_read(struct browse_ctx *bc, pmsg_t *mb)
{
	/*
	 * Read header if it has not been fully fetched yet.
	 */

	if (!bc->has_header) {
		char *w = cast_to_gpointer(&bc->header);

		g_assert(sizeof bc->header >= bc->pos);
		bc->pos += pmsg_read(mb, &w[bc->pos], sizeof bc->header - bc->pos);
		if (bc->pos < sizeof bc->header)
			return FALSE;

		bc->has_header = TRUE;		/* We have read the full header */

		bc->size = gnutella_header_get_size(&bc->header);

		/*
		 * Protect against too large data.
		 */

		if (bc->size > BH_DL_MAX_SIZE) {
			download_stop(bc->owner, GTA_DL_ERROR, "Gnutella payload too big");
			return FALSE;
		}

		/*
		 * Resize payload buffer if needed
		 */

		if (bc->size > bc->data_size) {
			bc->data_size = MAX(BH_DL_DEFAULT_SIZE, bc->size);
			bc->data = hrealloc(bc->data, bc->data_size);
		}

		bc->pos = 0;

		/* FALL THROUGH */
	}

	/*
	 * Read message data, if any.
	 */

	if (bc->size) {
		g_assert(bc->size >= bc->pos);
		bc->pos += pmsg_read(mb, &bc->data[bc->pos], bc->size - bc->pos);
	}

	if (bc->pos >= bc->size) {
		bc->has_header = FALSE;		/* For next message */
		bc->pos = 0;
		return TRUE; /* Must process message and continue */
	} else {
		return FALSE;
	}
}
Ejemplo n.º 2
0
/**
 * Read data from the pmsg list into supplied buffer.  Copied data is
 * removed from the list.
 *
 * @param slist		the pmsg list
 * @param buf		start of buffer where data must be copied
 * @param len		length of buffer
 *
 * @return amount of copied bytes.
 */
size_t
pmsg_slist_read(slist_t *slist, void *buf, size_t len)
{
	slist_iter_t *iter;
	size_t remain = len;
	void *p;

	g_assert(slist != NULL);

	iter = slist_iter_removable_on_head(slist);
	p = buf;

	while (remain != 0 && slist_iter_has_item(iter)) {
		pmsg_t *mb = slist_iter_current(iter);
		int n;

		n = pmsg_read(mb, p, remain);
		remain -= n;
		p = ptr_add_offset(p, n);
		if (0 == pmsg_size(mb)) {			/* Fully copied message */
			pmsg_free(mb);
			slist_iter_remove(iter);		/* Warning: moves to next */
		} else {
			break;		/* No need to continue on partial copy */
		}
	}
	slist_iter_free(&iter);

	return len - remain;
}
Ejemplo n.º 3
0
/**
 * Read data from the message buffer we just received.
 *
 * @return TRUE if there was an error.
 */
static bool
thex_download_data_read(struct thex_download *ctx, pmsg_t *mb)
{
	size_t size;
	
	g_assert(ctx);
	g_assert((NULL != ctx->data) ^ (0 == ctx->data_size));
	g_assert(ctx->pos <= ctx->data_size);

	while ((size = pmsg_size(mb)) > 0) {
		if (ctx->pos + size > ctx->max_size)
			return TRUE;

		if (size > ctx->data_size - ctx->pos) {
			ctx->data_size += MAX(size, ctx->data_size);
			ctx->data = hrealloc(ctx->data, ctx->data_size);
		}
		ctx->pos += pmsg_read(mb, &ctx->data[ctx->pos], size);
	}
	return FALSE;
}
Ejemplo n.º 4
0
/**
 * Writes the browse host data of the context ``ctx'' to the buffer
 * ``dest''. This must be called multiple times to retrieve the complete
 * data until zero is returned i.e., the end of file is reached.
 *
 * This routine deals with query hit data generation.
 *
 * @param ctx an initialized browse host context.
 * @param dest the destination buffer.
 * @param size the amount of bytes ``dest'' can hold.
 *
 * @return -1 on failure, zero at the end-of-file condition or if size
 *         was zero. On success, the amount of bytes copied to ``dest''
 *         is returned.
 */
static ssize_t
browse_host_read_qhits(struct special_upload *ctx,
	void *const dest, size_t size)
{
	struct browse_host_upload *bh = cast_to_browse_host_upload(ctx);
	size_t remain = size;
	char *p = dest;

	/*
	 * If we have no hit pending that we can send, build some more.
	 */

	if (NULL == bh->hits) {
		GSList *files = NULL;
		int i;

		for (i = 0; i < BH_SCAN_AHEAD; i++) {
			const shared_file_t *sf;

			do {
				/* Skip holes in indices */
				bh->file_index++;
				sf = shared_file_sorted(bh->file_index);
			} while (NULL == sf && bh->file_index <= shared_files_scanned());

			if (SHARE_REBUILDING == sf || NULL == sf)
				break;
			
			files = g_slist_prepend(files, deconstify_pointer(sf));
		}

		if (NULL == files)		/* Did not find any more file to include */
			return 0;			/* We're done */

		/*
		 * Now build the query hits containing the files we selected.
		 */

		files = g_slist_reverse(files);			/* Preserve order */

		qhit_build_results(files, i, BH_MAX_QHIT_SIZE,
			browse_host_record_hit, bh, &blank_guid, FALSE, &zero_array);

		g_assert(bh->hits != NULL);		/* At least 1 hit enqueued */

		bh->hits = g_slist_reverse(bh->hits);	/* Preserve order */
 		gm_slist_free_null(&files);
	}

	/*
	 * Read each query hit in turn.
	 */

	while (remain > 0 && NULL != bh->hits) {
		pmsg_t *mb = bh->hits->data;
		int r;

		r = pmsg_read(mb, p, remain);
		p += r;
		remain -= r;

		if (r == 0 || 0 == pmsg_size(mb)) {
			bh->hits = g_slist_remove(bh->hits, mb);
			pmsg_free(mb);
		}
	}

	return size - remain;
}