Exemple #1
0
liHandlerResult li_chunk_parser_next(liChunkParserCtx *ctx, char **p, char **pe, GError **err) {
	off_t l;
	liHandlerResult res;

	g_return_val_if_fail (err == NULL || *err == NULL, LI_HANDLER_ERROR);

	if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;

	while (ctx->start >= (l = li_chunkiter_length(ctx->curi))) {
		liChunkIter i = ctx->curi;
		 /* Wait at the end of the last chunk if it gets extended */
		if (!li_chunkiter_next(&i)) return LI_HANDLER_WAIT_FOR_EVENT;
		ctx->curi = i;
		ctx->start -= l;
	}

	if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;

	if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(ctx->curi, ctx->start, l - ctx->start, &ctx->buf, &ctx->length, err))) {
		return res;
	}

	*p = ctx->buf;
	*pe = ctx->buf + ctx->length;
	return LI_HANDLER_GO_ON;
}
Exemple #2
0
gboolean li_chunkqueue_extract_to_bytearr(liVRequest *vr, liChunkQueue *cq, goffset len, GByteArray *dest) {
	liChunkIter ci;
	goffset coff, clen;
	g_byte_array_set_size(dest, 0);
	if (len > cq->length) return FALSE;

	g_byte_array_set_size(dest, len);
	g_byte_array_set_size(dest, 0);

	ci = li_chunkqueue_iter(cq);

	while (len > 0) {
		coff = 0;
		clen = li_chunkiter_length(ci);
		while (coff < clen) {
			gchar *buf;
			off_t we_have;
			if (LI_HANDLER_GO_ON != li_chunkiter_read(vr, ci, coff, len, &buf, &we_have)) goto error;
			g_byte_array_append(dest, (guint8*) buf, we_have);
			coff += we_have;
			len -= we_have;
			if (len <= 0) return TRUE;
		}
		li_chunkiter_next(&ci);
	}

	return TRUE;

error:
	g_byte_array_set_size(dest, 0);
	return FALSE;
}
Exemple #3
0
gboolean li_chunk_extract_to(liChunkParserMark from, liChunkParserMark to, GString *dest, GError **err) {
	liChunkParserMark i;

	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);

	g_string_set_size(dest, to.abs_pos - from.abs_pos);
	li_g_string_clear(dest);

	for ( i = from; i.ci.element != to.ci.element; li_chunkiter_next(&i.ci) ) {
		goffset len = li_chunkiter_length(i.ci);
		while (i.pos < len) {
			char *buf;
			off_t we_have;
			if (LI_HANDLER_GO_ON != li_chunkiter_read(i.ci, i.pos, len - i.pos, &buf, &we_have, err)) goto error;
			if (dest->len + we_have < dest->allocated_len) {
				/* "fast" append */
				memcpy(dest->str + dest->len, buf, we_have);
				dest->len += we_have;
				dest->str[dest->len] = '\0';
			} else {
				g_string_append_len(dest, buf, we_have);
			}
			i.pos += we_have;
		}
		i.pos = 0;
	}
	while (i.pos < to.pos) {
		char *buf;
		off_t we_have;
		if (LI_HANDLER_GO_ON != li_chunkiter_read(i.ci, i.pos, to.pos - i.pos, &buf, &we_have, err)) goto error;
		if (dest->len + we_have < dest->allocated_len) {
			/* "fast" append */
			memcpy(dest->str + dest->len, buf, we_have);
			dest->len += we_have;
			dest->str[dest->len] = '\0';
		} else {
			g_string_append_len(dest, buf, we_have);
		}
		i.pos += we_have;
	}

	return TRUE;

error:
	li_g_string_clear(dest);
	return FALSE;
}
Exemple #4
0
liHandlerResult li_chunk_parser_next(liVRequest *vr, liChunkParserCtx *ctx, char **p, char **pe) {
	off_t l;
	liHandlerResult res;

	if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;

	while (ctx->start >= (l = li_chunkiter_length(ctx->curi))) {
		liChunkIter i = ctx->curi;
		 /* Wait at the end of the last chunk if it gets extended */
		if (!li_chunkiter_next(&i)) return LI_HANDLER_WAIT_FOR_EVENT;
		ctx->curi = i;
		ctx->start -= l;
	}

	if (NULL == ctx->curi.element) return LI_HANDLER_WAIT_FOR_EVENT;

	if (LI_HANDLER_GO_ON != (res = li_chunkiter_read(vr, ctx->curi, ctx->start, l - ctx->start, &ctx->buf, &ctx->length))) {
		return res;
	}

	*p = ctx->buf;
	*pe = ctx->buf + ctx->length;
	return LI_HANDLER_GO_ON;
}
Exemple #5
0
/* first chunk must be a STRING_CHUNK ! */
liNetworkStatus li_network_backend_writev(int fd, liChunkQueue *cq, goffset *write_max, GError **err) {
	off_t we_have;
	ssize_t r;
	gboolean did_write_something = FALSE;
	liChunkIter ci;
	liChunk *c;
	liNetworkStatus res = LI_NETWORK_STATUS_FATAL_ERROR;

	GArray *chunks = g_array_sized_new(FALSE, TRUE, sizeof(struct iovec), UIO_MAXIOV);

	if (0 == cq->length) goto cleanup; /* FATAL ERROR */

	do {
		ci = li_chunkqueue_iter(cq);

		if (STRING_CHUNK != (c = li_chunkiter_chunk(ci))->type && MEM_CHUNK != c->type && BUFFER_CHUNK != c->type) {
			res = did_write_something ? LI_NETWORK_STATUS_SUCCESS : LI_NETWORK_STATUS_FATAL_ERROR;
			goto cleanup;
		}

		we_have = 0;
		do {
			guint i = chunks->len;
			off_t len = li_chunk_length(c);
			struct iovec *v;
			g_array_set_size(chunks, i + 1);
			v = &g_array_index(chunks, struct iovec, i);
			if (c->type == STRING_CHUNK) {
				v->iov_base = c->data.str->str + c->offset;
			} else if (c->type == MEM_CHUNK) {
				v->iov_base = c->mem->data + c->offset;
			} else { /* if (c->type == BUFFER_CHUNK) */
				v->iov_base = c->data.buffer.buffer->addr + c->data.buffer.offset + c->offset;
			}
			if (len > *write_max - we_have) len = *write_max - we_have;
			v->iov_len = len;
			we_have += len;
		} while (we_have < *write_max &&
		         li_chunkiter_next(&ci) &&
		         (STRING_CHUNK == (c = li_chunkiter_chunk(ci))->type || MEM_CHUNK == c->type || BUFFER_CHUNK == c->type) &&
		         chunks->len < UIO_MAXIOV);

		while (-1 == (r = writev(fd, (struct iovec*) chunks->data, chunks->len))) {
			switch (errno) {
			case EAGAIN:
#if EWOULDBLOCK != EAGAIN
			case EWOULDBLOCK:
#endif
				res = LI_NETWORK_STATUS_WAIT_FOR_EVENT;
				goto cleanup;
			case ECONNRESET:
			case EPIPE:
			case ETIMEDOUT:
				res = LI_NETWORK_STATUS_CONNECTION_CLOSE;
				goto cleanup;
			case EINTR:
				break; /* try again */
			default:
				g_set_error(err, LI_NETWORK_ERROR, 0, "li_network_backend_writev: oops, write to fd=%d failed: %s", fd, g_strerror(errno));
				goto cleanup;
			}
		}
		if (0 == r) {
			res = LI_NETWORK_STATUS_WAIT_FOR_EVENT;
			goto cleanup;
		}
		li_chunkqueue_skip(cq, r);
		*write_max -= r;

		if (r != we_have) {
			res = LI_NETWORK_STATUS_WAIT_FOR_EVENT;
			goto cleanup;
		}

		if (0 == cq->length) {
			res = LI_NETWORK_STATUS_SUCCESS;
			goto cleanup;
		}

		did_write_something = TRUE;
		g_array_set_size(chunks, 0);
	} while (*write_max > 0);

	res = LI_NETWORK_STATUS_SUCCESS;

cleanup:
	g_array_free(chunks, TRUE);
	return res;
}