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