Beispiel #1
0
/* Tries to copy block <blk> at once into the channel's buffer after length
 * controls. The chn->o and to_forward pointers are updated. If the channel
 * input is closed, -2 is returned. If the block is too large for this buffer,
 * -3 is returned. If there is not enough room left in the buffer, -1 is
 * returned. Otherwise the number of bytes copied is returned (0 being a valid
 * number). Channel flag READ_PARTIAL is updated if some data can be
 * transferred.
 */
int ci_putblk(struct channel *chn, const char *blk, int len)
{
	int max;

	if (unlikely(channel_input_closed(chn)))
		return -2;

	if (len < 0)
		return -3;

	max = channel_recv_limit(chn);
	if (unlikely(len > max - c_data(chn))) {
		/* we can't write this chunk right now because the buffer is
		 * almost full or because the block is too large. Return the
		 * available space or -2 if impossible.
		 */
		if (len > max)
			return -3;

		return -1;
	}

	if (unlikely(len == 0))
		return 0;

	/* OK so the data fits in the buffer in one or two blocks */
	max = b_contig_space(&chn->buf);
	memcpy(ci_tail(chn), blk, MIN(len, max));
	if (len > max)
		memcpy(c_orig(chn), blk + max, len - max);

	b_add(&chn->buf, len);
	channel_add_input(chn, len);
	return len;
}
Beispiel #2
0
/* Tries to copy block <blk> at once into the channel's buffer after length
 * controls. The chn->o and to_forward pointers are updated. If the channel
 * input is closed, -2 is returned. If the block is too large for this buffer,
 * -3 is returned. If there is not enough room left in the buffer, -1 is
 * returned. Otherwise the number of bytes copied is returned (0 being a valid
 * number). Channel flag READ_PARTIAL is updated if some data can be
 * transferred.
 */
int ci_putblk(struct channel *chn, const char *blk, int len)
{
	int max;

	if (unlikely(channel_input_closed(chn)))
		return -2;

	if (len < 0)
		return -3;

	max = channel_recv_limit(chn);
	if (unlikely(len > max - c_data(chn))) {
		/* we can't write this chunk right now because the buffer is
		 * almost full or because the block is too large. Return the
		 * available space or -2 if impossible.
		 */
		if (len > max)
			return -3;

		return -1;
	}

	if (unlikely(len == 0))
		return 0;

	/* OK so the data fits in the buffer in one or two blocks */
	max = b_contig_space(&chn->buf);
	memcpy(ci_tail(chn), blk, MIN(len, max));
	if (len > max)
		memcpy(c_orig(chn), blk + max, len - max);

	b_add(&chn->buf, len);
	chn->total += len;
	if (chn->to_forward) {
		unsigned long fwd = len;
		if (chn->to_forward != CHN_INFINITE_FORWARD) {
			if (fwd > chn->to_forward)
				fwd = chn->to_forward;
			chn->to_forward -= fwd;
		}
		c_adv(chn, fwd);
	}

	/* notify that some data was read from the SI into the buffer */
	chn->flags |= CF_READ_PARTIAL;
	return len;
}
Beispiel #3
0
/* Tries to copy character <c> into the channel's buffer after some length
 * controls. The chn->o and to_forward pointers are updated. If the channel
 * input is closed, -2 is returned. If there is not enough room left in the
 * buffer, -1 is returned. Otherwise the number of bytes copied is returned
 * (1). Channel flag READ_PARTIAL is updated if some data can be transferred.
 */
int ci_putchr(struct channel *chn, char c)
{
	if (unlikely(channel_input_closed(chn)))
		return -2;

	if (!channel_may_recv(chn))
		return -1;

	*ci_tail(chn) = c;

	b_add(&chn->buf, 1);
	chn->flags |= CF_READ_PARTIAL;

	if (chn->to_forward >= 1) {
		if (chn->to_forward != CHN_INFINITE_FORWARD)
			chn->to_forward--;
		c_adv(chn, 1);
	}

	chn->total++;
	return 1;
}
Beispiel #4
0
/* extracts some payload at a fixed position and length */
static int
smp_fetch_payload(struct proxy *px, struct session *s, void *l7, unsigned int opt,
                  const struct arg *arg_p, struct sample *smp, const char *kw)
{
	unsigned int buf_offset = arg_p[0].data.uint;
	unsigned int buf_size = arg_p[1].data.uint;
	struct channel *chn;

	if (!s)
		return 0;

	chn = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? s->rep : s->req;

	if (!chn)
		return 0;

	if (buf_size > chn->buf->size || buf_offset + buf_size > chn->buf->size) {
		/* will never match */
		smp->flags = 0;
		return 0;
	}

	if (buf_offset + buf_size > chn->buf->i)
		goto too_short;

	/* init chunk as read only */
	smp->type = SMP_T_CBIN;
	chunk_initlen(&smp->data.str, chn->buf->p + buf_offset, 0, buf_size ? buf_size : (chn->buf->i - buf_offset));
	smp->flags = SMP_F_VOLATILE;
	if (!buf_size && !channel_full(chn) && !channel_input_closed(chn))
		smp->flags |= SMP_F_MAY_CHANGE;

	return 1;

 too_short:
	smp->flags = SMP_F_MAY_CHANGE;
	return 0;
}
Beispiel #5
0
/* Tries to copy character <c> into the channel's buffer after some length
 * controls. The chn->o and to_forward pointers are updated. If the channel
 * input is closed, -2 is returned. If there is not enough room left in the
 * buffer, -1 is returned. Otherwise the number of bytes copied is returned
 * (1). Channel flag READ_PARTIAL is updated if some data can be transferred.
 * Channel flag CF_WAKE_WRITE is set if the write fails because the buffer is
 * full.
 */
int bi_putchr(struct channel *chn, char c)
{
	if (unlikely(channel_input_closed(chn)))
		return -2;

	if (channel_full(chn)) {
		chn->flags |= CF_WAKE_WRITE;
		return -1;
	}

	*bi_end(chn->buf) = c;

	chn->buf->i++;
	chn->flags |= CF_READ_PARTIAL;

	if (chn->to_forward >= 1) {
		if (chn->to_forward != CHN_INFINITE_FORWARD)
			chn->to_forward--;
		b_adv(chn->buf, 1);
	}

	chn->total++;
	return 1;
}