/** * 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; } }
/** * 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; }
/** * 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; }
/** * 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; }