2006-06-26 00:48:02 +00:00
|
|
|
/*
|
2012-08-24 17:22:53 +00:00
|
|
|
* Channel management functions.
|
2006-06-26 00:48:02 +00:00
|
|
|
*
|
2014-11-27 21:10:04 +00:00
|
|
|
* Copyright 2000-2014 Willy Tarreau <w@1wt.eu>
|
2006-06-26 00:48:02 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-10-10 19:06:03 +00:00
|
|
|
#include <ctype.h>
|
2007-01-01 20:38:07 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
2006-06-26 00:48:02 +00:00
|
|
|
#include <string.h>
|
2006-06-29 16:54:54 +00:00
|
|
|
|
|
|
|
#include <common/config.h>
|
2012-08-24 17:22:53 +00:00
|
|
|
#include <common/buffer.h>
|
2006-06-26 00:48:02 +00:00
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
#include <proto/channel.h>
|
2012-08-24 17:22:53 +00:00
|
|
|
|
2007-05-13 17:56:02 +00:00
|
|
|
|
2012-08-27 22:06:31 +00:00
|
|
|
/* Schedule up to <bytes> more bytes to be forwarded via the channel without
|
|
|
|
* notifying the owner task. Any data pending in the buffer are scheduled to be
|
2016-05-04 12:05:58 +00:00
|
|
|
* sent as well, within the limit of the number of bytes to forward. This must
|
|
|
|
* be the only method to use to schedule bytes to be forwarded. If the requested
|
2012-08-27 22:06:31 +00:00
|
|
|
* number is too large, it is automatically adjusted. The number of bytes taken
|
|
|
|
* into account is returned. Directly touching ->to_forward will cause lockups
|
|
|
|
* when buf->o goes down to zero if nobody is ready to push the remaining data.
|
2011-03-28 14:25:58 +00:00
|
|
|
*/
|
2012-10-25 22:21:52 +00:00
|
|
|
unsigned long long __channel_forward(struct channel *chn, unsigned long long bytes)
|
2011-03-28 14:25:58 +00:00
|
|
|
{
|
2016-05-04 12:05:58 +00:00
|
|
|
unsigned int budget;
|
2012-03-01 17:19:58 +00:00
|
|
|
unsigned int forwarded;
|
2011-03-28 14:25:58 +00:00
|
|
|
|
2016-05-04 12:05:58 +00:00
|
|
|
/* This is more of a safety measure as it's not supposed to happen in
|
|
|
|
* regular code paths.
|
2011-03-28 14:25:58 +00:00
|
|
|
*/
|
2016-05-04 12:05:58 +00:00
|
|
|
if (unlikely(chn->to_forward == CHN_INFINITE_FORWARD)) {
|
2018-06-06 05:13:22 +00:00
|
|
|
c_adv(chn, chn->buf->i);
|
2012-03-01 17:19:58 +00:00
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
2016-05-04 12:05:58 +00:00
|
|
|
/* Bound the transferred size to a 32-bit count since all our values
|
|
|
|
* are 32-bit, and we don't want to reach CHN_INFINITE_FORWARD.
|
|
|
|
*/
|
|
|
|
budget = MIN(bytes, CHN_INFINITE_FORWARD - 1);
|
2011-03-28 14:25:58 +00:00
|
|
|
|
2016-05-04 12:05:58 +00:00
|
|
|
/* transfer as much as we can of buf->i */
|
|
|
|
forwarded = MIN(chn->buf->i, budget);
|
2018-06-06 05:13:22 +00:00
|
|
|
c_adv(chn, forwarded);
|
2016-05-04 12:05:58 +00:00
|
|
|
budget -= forwarded;
|
2011-03-28 14:25:58 +00:00
|
|
|
|
2016-05-04 12:05:58 +00:00
|
|
|
if (!budget)
|
|
|
|
return forwarded;
|
|
|
|
|
|
|
|
/* Now we must ensure chn->to_forward sats below CHN_INFINITE_FORWARD,
|
|
|
|
* which also implies it won't overflow. It's less operations in 64-bit.
|
|
|
|
*/
|
|
|
|
bytes = (unsigned long long)chn->to_forward + budget;
|
|
|
|
if (bytes >= CHN_INFINITE_FORWARD)
|
|
|
|
bytes = CHN_INFINITE_FORWARD - 1;
|
|
|
|
budget = bytes - chn->to_forward;
|
|
|
|
|
|
|
|
chn->to_forward += budget;
|
|
|
|
forwarded += budget;
|
|
|
|
return forwarded;
|
2011-03-28 14:25:58 +00:00
|
|
|
}
|
2006-06-26 00:48:02 +00:00
|
|
|
|
2012-08-27 22:06:31 +00:00
|
|
|
/* writes <len> bytes from message <msg> to the channel's buffer. Returns -1 in
|
|
|
|
* case of success, -2 if the message is larger than the buffer size, or the
|
|
|
|
* number of bytes available otherwise. The send limit is automatically
|
|
|
|
* adjusted to the amount of data written. FIXME-20060521: handle unaligned
|
|
|
|
* data. Note: this function appends data to the buffer's output and possibly
|
|
|
|
* overwrites any pending input data which are assumed not to exist.
|
2006-06-26 00:48:02 +00:00
|
|
|
*/
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
int co_inject(struct channel *chn, const char *msg, int len)
|
2006-06-26 00:48:02 +00:00
|
|
|
{
|
|
|
|
int max;
|
|
|
|
|
2009-08-31 06:09:57 +00:00
|
|
|
if (len == 0)
|
|
|
|
return -1;
|
2006-06-26 00:48:02 +00:00
|
|
|
|
2016-02-25 15:15:19 +00:00
|
|
|
if (len < 0 || len > chn->buf->size) {
|
2009-08-18 05:19:39 +00:00
|
|
|
/* we can't write this chunk and will never be able to, because
|
|
|
|
* it is larger than the buffer. This must be reported as an
|
|
|
|
* error. Then we return -2 so that writers that don't care can
|
|
|
|
* ignore it and go on, and others can check for this value.
|
|
|
|
*/
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2018-06-06 04:42:46 +00:00
|
|
|
c_realign_if_empty(chn);
|
BUG/MEDIUM: buffers: Fix how input/output data are injected into buffers
The function buffer_contig_space is buggy and could lead to pernicious bugs
(never hitted until now, AFAIK). This function should return the number of bytes
that can be written into the buffer at once (without wrapping).
First, this function is used to inject input data (bi_putblk) and to inject
output data (bo_putblk and bo_inject). But there is no context. So it cannot
decide where contiguous space should placed. For input data, it should be after
bi_end(buf) (ie, buf->p + buf->i modulo wrapping calculation). For output data,
it should be after bo_end(buf) (ie, buf->p) and input data are assumed to not
exist (else there is no space at all).
Then, considering we need to inject input data, this function does not always
returns the right value. And when we need to inject output data, we must be sure
to have no input data at all (buf->i == 0), else the result can also be wrong
(but this is the caller responsibility, so everything should be fine here).
The buffer can be in 3 different states:
1) no wrapping
<---- o ----><----- i ----->
+------------+------------+-------------+------------+
| |oooooooooooo|iiiiiiiiiiiii|xxxxxxxxxxxx|
+------------+------------+-------------+------------+
^ <contig_space>
p ^ ^
l r
2) input wrapping
...---> <---- o ----><-------- i -------...
+-----+------------+------------+--------------------+
|iiiii|xxxxxxxxxxxx|oooooooooooo|iiiiiiiiiiiiiiiiiiii|
+-----+------------+------------+--------------------+
<contig_space> ^
^ ^ p
l r
3) output wrapping
...------ o ------><----- i -----> <----...
+------------------+-------------+------------+------+
|oooooooooooooooooo|iiiiiiiiiiiii|xxxxxxxxxxxx|oooooo|
+------------------+-------------+------------+------+
^ <contig_space>
p ^ ^
l r
buffer_contig_space returns (l - r). The cases 1 and 3 are correctly
handled. But for the second case, r is wrong. It points on the buffer's end
(buf->data + buf->size). It should be bo_end(buf) (ie, buf->p - buf->o).
To fix the bug, the function has been splitted. Now, bi_contig_space and
bo_contig_space should be used to know the contiguous space available to insert,
respectively, input data and output data. For bo_contig_space, input data are
assumed to not exist. And the right version is used, depending what we want to
do.
In addition, to clarify the buffer's API, buffer_realign does not return value
anymore. So it has the same API than buffer_slow_realign.
This patch can be backported in 1.7, 1.6 and 1.5.
2017-03-29 09:58:28 +00:00
|
|
|
max = bo_contig_space(chn->buf);
|
2006-06-26 00:48:02 +00:00
|
|
|
if (len > max)
|
|
|
|
return max;
|
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
memcpy(chn->buf->p, msg, len);
|
|
|
|
chn->buf->o += len;
|
|
|
|
chn->buf->p = b_ptr(chn->buf, len);
|
2012-10-12 21:11:02 +00:00
|
|
|
chn->total += len;
|
2008-04-20 19:34:47 +00:00
|
|
|
return -1;
|
2006-06-26 00:48:02 +00:00
|
|
|
}
|
|
|
|
|
2012-08-27 22:06:31 +00:00
|
|
|
/* Tries to copy character <c> into the channel's buffer after some length
|
2012-10-12 21:11:02 +00:00
|
|
|
* controls. The chn->o and to_forward pointers are updated. If the channel
|
2012-08-27 22:06:31 +00:00
|
|
|
* 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.
|
2007-01-01 20:38:07 +00:00
|
|
|
*/
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
int ci_putchr(struct channel *chn, char c)
|
2007-01-01 20:38:07 +00:00
|
|
|
{
|
2012-10-12 21:11:02 +00:00
|
|
|
if (unlikely(channel_input_closed(chn)))
|
2010-09-08 15:04:31 +00:00
|
|
|
return -2;
|
2007-01-01 20:38:07 +00:00
|
|
|
|
2015-03-13 13:00:47 +00:00
|
|
|
if (!channel_may_recv(chn))
|
2008-04-20 19:34:47 +00:00
|
|
|
return -1;
|
2007-01-01 20:38:07 +00:00
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
*bi_end(chn->buf) = c;
|
2010-09-08 15:04:31 +00:00
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
chn->buf->i++;
|
2012-10-12 21:11:02 +00:00
|
|
|
chn->flags |= CF_READ_PARTIAL;
|
2010-09-08 15:04:31 +00:00
|
|
|
|
2012-10-12 21:11:02 +00:00
|
|
|
if (chn->to_forward >= 1) {
|
|
|
|
if (chn->to_forward != CHN_INFINITE_FORWARD)
|
|
|
|
chn->to_forward--;
|
2018-06-06 05:13:22 +00:00
|
|
|
c_adv(chn, 1);
|
2010-09-08 15:04:31 +00:00
|
|
|
}
|
|
|
|
|
2012-10-12 21:11:02 +00:00
|
|
|
chn->total++;
|
2010-09-08 15:04:31 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-08-27 22:06:31 +00:00
|
|
|
/* Tries to copy block <blk> at once into the channel's buffer after length
|
2012-10-12 21:11:02 +00:00
|
|
|
* controls. The chn->o and to_forward pointers are updated. If the channel
|
2012-08-27 22:06:31 +00:00
|
|
|
* 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
|
2015-03-13 13:00:47 +00:00
|
|
|
* transferred.
|
2010-09-08 15:04:31 +00:00
|
|
|
*/
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
int ci_putblk(struct channel *chn, const char *blk, int len)
|
2010-09-08 15:04:31 +00:00
|
|
|
{
|
|
|
|
int max;
|
|
|
|
|
2012-10-12 21:11:02 +00:00
|
|
|
if (unlikely(channel_input_closed(chn)))
|
2010-09-08 15:04:31 +00:00
|
|
|
return -2;
|
|
|
|
|
2016-02-25 15:15:19 +00:00
|
|
|
if (len < 0)
|
|
|
|
return -3;
|
|
|
|
|
2015-01-14 19:21:43 +00:00
|
|
|
max = channel_recv_limit(chn);
|
2012-10-12 21:49:43 +00:00
|
|
|
if (unlikely(len > max - buffer_len(chn->buf))) {
|
2010-08-10 13:28:21 +00:00
|
|
|
/* 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.
|
2009-08-18 05:19:39 +00:00
|
|
|
*/
|
2010-08-10 13:28:21 +00:00
|
|
|
if (len > max)
|
2010-09-08 15:04:31 +00:00
|
|
|
return -3;
|
2009-08-18 05:19:39 +00:00
|
|
|
|
2010-09-08 15:04:31 +00:00
|
|
|
return -1;
|
2010-08-10 13:28:21 +00:00
|
|
|
}
|
2007-01-01 20:38:07 +00:00
|
|
|
|
2010-09-08 15:04:31 +00:00
|
|
|
if (unlikely(len == 0))
|
|
|
|
return 0;
|
|
|
|
|
2010-08-10 13:28:21 +00:00
|
|
|
/* OK so the data fits in the buffer in one or two blocks */
|
BUG/MEDIUM: buffers: Fix how input/output data are injected into buffers
The function buffer_contig_space is buggy and could lead to pernicious bugs
(never hitted until now, AFAIK). This function should return the number of bytes
that can be written into the buffer at once (without wrapping).
First, this function is used to inject input data (bi_putblk) and to inject
output data (bo_putblk and bo_inject). But there is no context. So it cannot
decide where contiguous space should placed. For input data, it should be after
bi_end(buf) (ie, buf->p + buf->i modulo wrapping calculation). For output data,
it should be after bo_end(buf) (ie, buf->p) and input data are assumed to not
exist (else there is no space at all).
Then, considering we need to inject input data, this function does not always
returns the right value. And when we need to inject output data, we must be sure
to have no input data at all (buf->i == 0), else the result can also be wrong
(but this is the caller responsibility, so everything should be fine here).
The buffer can be in 3 different states:
1) no wrapping
<---- o ----><----- i ----->
+------------+------------+-------------+------------+
| |oooooooooooo|iiiiiiiiiiiii|xxxxxxxxxxxx|
+------------+------------+-------------+------------+
^ <contig_space>
p ^ ^
l r
2) input wrapping
...---> <---- o ----><-------- i -------...
+-----+------------+------------+--------------------+
|iiiii|xxxxxxxxxxxx|oooooooooooo|iiiiiiiiiiiiiiiiiiii|
+-----+------------+------------+--------------------+
<contig_space> ^
^ ^ p
l r
3) output wrapping
...------ o ------><----- i -----> <----...
+------------------+-------------+------------+------+
|oooooooooooooooooo|iiiiiiiiiiiii|xxxxxxxxxxxx|oooooo|
+------------------+-------------+------------+------+
^ <contig_space>
p ^ ^
l r
buffer_contig_space returns (l - r). The cases 1 and 3 are correctly
handled. But for the second case, r is wrong. It points on the buffer's end
(buf->data + buf->size). It should be bo_end(buf) (ie, buf->p - buf->o).
To fix the bug, the function has been splitted. Now, bi_contig_space and
bo_contig_space should be used to know the contiguous space available to insert,
respectively, input data and output data. For bo_contig_space, input data are
assumed to not exist. And the right version is used, depending what we want to
do.
In addition, to clarify the buffer's API, buffer_realign does not return value
anymore. So it has the same API than buffer_slow_realign.
This patch can be backported in 1.7, 1.6 and 1.5.
2017-03-29 09:58:28 +00:00
|
|
|
max = bi_contig_space(chn->buf);
|
2012-10-12 21:49:43 +00:00
|
|
|
memcpy(bi_end(chn->buf), blk, MIN(len, max));
|
2009-08-31 06:09:57 +00:00
|
|
|
if (len > max)
|
2012-10-12 21:49:43 +00:00
|
|
|
memcpy(chn->buf->data, blk + max, len - max);
|
2007-01-01 20:38:07 +00:00
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
chn->buf->i += len;
|
2012-10-12 21:11:02 +00:00
|
|
|
chn->total += len;
|
|
|
|
if (chn->to_forward) {
|
2009-09-20 10:07:52 +00:00
|
|
|
unsigned long fwd = len;
|
2012-10-12 21:11:02 +00:00
|
|
|
if (chn->to_forward != CHN_INFINITE_FORWARD) {
|
|
|
|
if (fwd > chn->to_forward)
|
|
|
|
fwd = chn->to_forward;
|
|
|
|
chn->to_forward -= fwd;
|
2009-09-20 10:07:52 +00:00
|
|
|
}
|
2018-06-06 05:13:22 +00:00
|
|
|
c_adv(chn, fwd);
|
2009-08-31 06:09:57 +00:00
|
|
|
}
|
|
|
|
|
2009-09-23 21:47:55 +00:00
|
|
|
/* notify that some data was read from the SI into the buffer */
|
2012-10-12 21:11:02 +00:00
|
|
|
chn->flags |= CF_READ_PARTIAL;
|
2010-09-08 15:04:31 +00:00
|
|
|
return len;
|
2007-01-01 20:38:07 +00:00
|
|
|
}
|
|
|
|
|
2014-12-08 17:14:53 +00:00
|
|
|
/* Tries to copy the whole buffer <buf> into the channel's buffer after length
|
|
|
|
* controls. It will only succeed if the target buffer is empty, in which case
|
|
|
|
* it will simply swap the buffers. The buffer not attached to the channel is
|
|
|
|
* returned so that the caller can store it locally. The chn->buf->o and
|
|
|
|
* to_forward pointers are updated. If the output buffer is a dummy buffer or
|
|
|
|
* if it still contains data <buf> is returned, indicating that nothing could
|
|
|
|
* be done. Channel flag READ_PARTIAL is updated if some data can be transferred.
|
|
|
|
* The chunk's length is updated with the number of bytes sent. On errors, NULL
|
|
|
|
* is returned. Note that only buf->i is considered.
|
|
|
|
*/
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
struct buffer *ci_swpbuf(struct channel *chn, struct buffer *buf)
|
2014-12-08 17:14:53 +00:00
|
|
|
{
|
|
|
|
struct buffer *old;
|
|
|
|
|
|
|
|
if (unlikely(channel_input_closed(chn)))
|
|
|
|
return NULL;
|
|
|
|
|
2015-03-13 13:00:47 +00:00
|
|
|
if (!chn->buf->size || !buffer_empty(chn->buf))
|
2014-12-08 17:14:53 +00:00
|
|
|
return buf;
|
|
|
|
|
|
|
|
old = chn->buf;
|
|
|
|
chn->buf = buf;
|
|
|
|
|
|
|
|
if (!buf->i)
|
|
|
|
return old;
|
|
|
|
|
|
|
|
chn->total += buf->i;
|
|
|
|
|
|
|
|
if (chn->to_forward) {
|
|
|
|
unsigned long fwd = buf->i;
|
|
|
|
if (chn->to_forward != CHN_INFINITE_FORWARD) {
|
|
|
|
if (fwd > chn->to_forward)
|
|
|
|
fwd = chn->to_forward;
|
|
|
|
chn->to_forward -= fwd;
|
|
|
|
}
|
2018-06-06 05:13:22 +00:00
|
|
|
c_adv(chn, fwd);
|
2014-12-08 17:14:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* notify that some data was read from the SI into the buffer */
|
|
|
|
chn->flags |= CF_READ_PARTIAL;
|
|
|
|
return old;
|
|
|
|
}
|
|
|
|
|
2012-08-27 22:06:31 +00:00
|
|
|
/* Gets one text line out of a channel's buffer from a stream interface.
|
2009-09-01 04:41:32 +00:00
|
|
|
* Return values :
|
|
|
|
* >0 : number of bytes read. Includes the \n if present before len or end.
|
2010-09-08 15:04:31 +00:00
|
|
|
* =0 : no '\n' before end found. <str> is left undefined.
|
|
|
|
* <0 : no more bytes readable because output is shut.
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
* The channel status is not changed. The caller must call co_skip() to
|
2009-09-01 04:41:32 +00:00
|
|
|
* update it. The '\n' is waited for as long as neither the buffer nor the
|
|
|
|
* output are full. If either of them is full, the string may be returned
|
|
|
|
* as is, without the '\n'.
|
|
|
|
*/
|
2017-10-19 12:58:40 +00:00
|
|
|
int co_getline(const struct channel *chn, char *str, int len)
|
2009-09-01 04:41:32 +00:00
|
|
|
{
|
|
|
|
int ret, max;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
max = len;
|
2010-09-08 15:04:31 +00:00
|
|
|
|
|
|
|
/* closed or empty + imminent close = -1; empty = 0 */
|
2012-10-12 21:11:02 +00:00
|
|
|
if (unlikely((chn->flags & CF_SHUTW) || channel_is_empty(chn))) {
|
|
|
|
if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW))
|
2009-09-01 04:41:32 +00:00
|
|
|
ret = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2018-06-07 16:16:48 +00:00
|
|
|
p = b_head(chn->buf);
|
2009-09-01 04:41:32 +00:00
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
if (max > chn->buf->o) {
|
|
|
|
max = chn->buf->o;
|
2009-09-23 20:56:07 +00:00
|
|
|
str[max-1] = 0;
|
2009-09-01 04:41:32 +00:00
|
|
|
}
|
|
|
|
while (max) {
|
|
|
|
*str++ = *p;
|
|
|
|
ret++;
|
|
|
|
max--;
|
|
|
|
|
|
|
|
if (*p == '\n')
|
|
|
|
break;
|
2012-10-12 21:49:43 +00:00
|
|
|
p = buffer_wrap_add(chn->buf, p + 1);
|
2009-09-01 04:41:32 +00:00
|
|
|
}
|
2013-12-10 17:58:23 +00:00
|
|
|
if (ret > 0 && ret < len &&
|
2015-01-13 19:20:10 +00:00
|
|
|
(ret < chn->buf->o || channel_may_recv(chn)) &&
|
2009-09-23 20:56:07 +00:00
|
|
|
*(str-1) != '\n' &&
|
2012-10-12 21:11:02 +00:00
|
|
|
!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW)))
|
2009-09-01 04:41:32 +00:00
|
|
|
ret = 0;
|
|
|
|
out:
|
|
|
|
if (max)
|
|
|
|
*str = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-08-27 22:06:31 +00:00
|
|
|
/* Gets one full block of data at once from a channel's buffer, optionally from
|
|
|
|
* a specific offset. Return values :
|
2010-09-08 15:04:31 +00:00
|
|
|
* >0 : number of bytes read, equal to requested size.
|
|
|
|
* =0 : not enough data available. <blk> is left undefined.
|
|
|
|
* <0 : no more bytes readable because output is shut.
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
* The channel status is not changed. The caller must call co_skip() to
|
2010-09-08 15:04:31 +00:00
|
|
|
* update it.
|
|
|
|
*/
|
2017-10-19 12:58:40 +00:00
|
|
|
int co_getblk(const struct channel *chn, char *blk, int len, int offset)
|
2010-09-08 15:04:31 +00:00
|
|
|
{
|
2012-10-12 21:11:02 +00:00
|
|
|
if (chn->flags & CF_SHUTW)
|
2010-09-08 15:04:31 +00:00
|
|
|
return -1;
|
|
|
|
|
2012-10-12 21:49:43 +00:00
|
|
|
if (len + offset > chn->buf->o) {
|
2012-10-12 21:11:02 +00:00
|
|
|
if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW))
|
2010-09-08 15:04:31 +00:00
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-19 12:57:54 +00:00
|
|
|
return bo_getblk(chn->buf, blk, len, offset);
|
2010-09-08 15:04:31 +00:00
|
|
|
}
|
|
|
|
|
2015-02-16 18:26:48 +00:00
|
|
|
/* Gets one or two blocks of data at once from a channel's output buffer.
|
|
|
|
* Return values :
|
|
|
|
* >0 : number of blocks filled (1 or 2). blk1 is always filled before blk2.
|
|
|
|
* =0 : not enough data available. <blk*> are left undefined.
|
|
|
|
* <0 : no more bytes readable because output is shut.
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
* The channel status is not changed. The caller must call co_skip() to
|
2015-02-16 18:26:48 +00:00
|
|
|
* update it. Unused buffers are left in an undefined state.
|
|
|
|
*/
|
2017-10-19 12:58:40 +00:00
|
|
|
int co_getblk_nc(const struct channel *chn, char **blk1, int *len1, char **blk2, int *len2)
|
2015-02-16 18:26:48 +00:00
|
|
|
{
|
|
|
|
if (unlikely(chn->buf->o == 0)) {
|
|
|
|
if (chn->flags & CF_SHUTW)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-19 12:57:54 +00:00
|
|
|
return bo_getblk_nc(chn->buf, blk1, len1, blk2, len2);
|
2015-02-16 18:26:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Gets one text line out of a channel's output buffer from a stream interface.
|
|
|
|
* Return values :
|
|
|
|
* >0 : number of blocks returned (1 or 2). blk1 is always filled before blk2.
|
|
|
|
* =0 : not enough data available.
|
|
|
|
* <0 : no more bytes readable because output is shut.
|
|
|
|
* The '\n' is waited for as long as neither the buffer nor the output are
|
|
|
|
* full. If either of them is full, the string may be returned as is, without
|
|
|
|
* the '\n'. Unused buffers are left in an undefined state.
|
|
|
|
*/
|
2017-10-19 12:58:40 +00:00
|
|
|
int co_getline_nc(const struct channel *chn,
|
2015-02-16 18:26:48 +00:00
|
|
|
char **blk1, int *len1,
|
|
|
|
char **blk2, int *len2)
|
|
|
|
{
|
|
|
|
int retcode;
|
|
|
|
int l;
|
|
|
|
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
retcode = co_getblk_nc(chn, blk1, len1, blk2, len2);
|
2018-04-24 17:20:43 +00:00
|
|
|
if (unlikely(retcode <= 0))
|
2015-02-16 18:26:48 +00:00
|
|
|
return retcode;
|
|
|
|
|
|
|
|
for (l = 0; l < *len1 && (*blk1)[l] != '\n'; l++);
|
|
|
|
if (l < *len1 && (*blk1)[l] == '\n') {
|
|
|
|
*len1 = l + 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retcode >= 2) {
|
|
|
|
for (l = 0; l < *len2 && (*blk2)[l] != '\n'; l++);
|
|
|
|
if (l < *len2 && (*blk2)[l] == '\n') {
|
|
|
|
*len2 = l + 1;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chn->flags & CF_SHUTW) {
|
|
|
|
/* If we have found no LF and the buffer is shut, then
|
|
|
|
* the resulting string is made of the concatenation of
|
|
|
|
* the pending blocks (1 or 2).
|
|
|
|
*/
|
|
|
|
return retcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No LF yet and not shut yet */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Gets one full block of data at once from a channel's input buffer.
|
|
|
|
* This function can return the data slitted in one or two blocks.
|
|
|
|
* Return values :
|
|
|
|
* >0 : number of blocks returned (1 or 2). blk1 is always filled before blk2.
|
|
|
|
* =0 : not enough data available.
|
|
|
|
* <0 : no more bytes readable because input is shut.
|
|
|
|
*/
|
2017-10-19 12:58:40 +00:00
|
|
|
int ci_getblk_nc(const struct channel *chn,
|
2015-02-16 18:26:48 +00:00
|
|
|
char **blk1, int *len1,
|
|
|
|
char **blk2, int *len2)
|
|
|
|
{
|
|
|
|
if (unlikely(chn->buf->i == 0)) {
|
|
|
|
if (chn->flags & CF_SHUTR)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(chn->buf->p + chn->buf->i > chn->buf->data + chn->buf->size)) {
|
|
|
|
*blk1 = chn->buf->p;
|
|
|
|
*len1 = chn->buf->data + chn->buf->size - chn->buf->p;
|
|
|
|
*blk2 = chn->buf->data;
|
|
|
|
*len2 = chn->buf->i - *len1;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
*blk1 = chn->buf->p;
|
|
|
|
*len1 = chn->buf->i;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Gets one text line out of a channel's input buffer from a stream interface.
|
|
|
|
* Return values :
|
|
|
|
* >0 : number of blocks returned (1 or 2). blk1 is always filled before blk2.
|
|
|
|
* =0 : not enough data available.
|
|
|
|
* <0 : no more bytes readable because output is shut.
|
|
|
|
* The '\n' is waited for as long as neither the buffer nor the input are
|
|
|
|
* full. If either of them is full, the string may be returned as is, without
|
|
|
|
* the '\n'. Unused buffers are left in an undefined state.
|
|
|
|
*/
|
2017-10-19 12:58:40 +00:00
|
|
|
int ci_getline_nc(const struct channel *chn,
|
2015-02-16 18:26:48 +00:00
|
|
|
char **blk1, int *len1,
|
|
|
|
char **blk2, int *len2)
|
|
|
|
{
|
|
|
|
int retcode;
|
|
|
|
int l;
|
|
|
|
|
REORG: channel: finally rename the last bi_* / bo_* functions
For HTTP/2 we'll need some buffer-only equivalent functions to some of
the ones applying to channels and still squatting the bi_* / bo_*
namespace. Since these names have kept being misleading for quite some
time now and are really getting annoying, it's time to rename them. This
commit will use "ci/co" as the prefix (for "channel in", "channel out")
instead of "bi/bo". The following ones were renamed :
bi_getblk_nc, bi_getline_nc, bi_putblk, bi_putchr,
bo_getblk, bo_getblk_nc, bo_getline, bo_getline_nc, bo_inject,
bi_putchk, bi_putstr, bo_getchr, bo_skip, bi_swpbuf
2017-10-19 12:32:15 +00:00
|
|
|
retcode = ci_getblk_nc(chn, blk1, len1, blk2, len2);
|
2016-11-12 16:39:58 +00:00
|
|
|
if (unlikely(retcode <= 0))
|
2015-02-16 18:26:48 +00:00
|
|
|
return retcode;
|
|
|
|
|
|
|
|
for (l = 0; l < *len1 && (*blk1)[l] != '\n'; l++);
|
|
|
|
if (l < *len1 && (*blk1)[l] == '\n') {
|
|
|
|
*len1 = l + 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retcode >= 2) {
|
|
|
|
for (l = 0; l < *len2 && (*blk2)[l] != '\n'; l++);
|
|
|
|
if (l < *len2 && (*blk2)[l] == '\n') {
|
|
|
|
*len2 = l + 1;
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chn->flags & CF_SHUTW) {
|
|
|
|
/* If we have found no LF and the buffer is shut, then
|
|
|
|
* the resulting string is made of the concatenation of
|
|
|
|
* the pending blocks (1 or 2).
|
|
|
|
*/
|
|
|
|
return retcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No LF yet and not shut yet */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-06-26 00:48:02 +00:00
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* c-indent-level: 8
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* End:
|
|
|
|
*/
|