MINOR: applet: Add API functions to get data from the input buffer
There was already functions to pushed data from the applet to the stream by inserting them in the right buffer, depending the applet was using or not the legacy API. Here, functions to retreive data pushed to the applet by the stream were added: * applet_getchar : Gets one character * applet_getblk : Copies a full block of data * applet_getword : Copies one text block representing a word using a custom separator as delimiter * applet_getline : Copies one text line * applet_getblk_nc : Get one or two blocks of data * applet_getword_nc: Gets one or two blocks of text representing a word using a custom separator as delimiter * applet_getline_nc: Gets one or two blocks of text representing a line
This commit is contained in:
parent
0d8ecb1edc
commit
79445766a3
@ -532,6 +532,283 @@ static inline int applet_putchr(struct appctx *appctx, char chr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int applet_may_get(const struct appctx *appctx, size_t len)
|
||||
{
|
||||
if (appctx->flags & APPCTX_FL_INOUT_BUFS) {
|
||||
if (len > b_data(&appctx->inbuf)) {
|
||||
if (se_fl_test(appctx->sedesc, SE_FL_SHW))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const struct stconn *sc = appctx_sc(appctx);
|
||||
|
||||
if ((sc->flags & SC_FL_SHUT_DONE) || len > co_data(sc_oc(sc))) {
|
||||
if (sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* Gets one char from the applet input buffer (see appet_get_inbuf),
|
||||
*
|
||||
* Return values :
|
||||
* 1 : number of bytes read, equal to requested size.
|
||||
* =0 : not enough data available. <c> is left undefined.
|
||||
* <0 : no more bytes readable because output is shut.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getchar(const struct appctx *appctx, char *c)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = applet_may_get(appctx, 1);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
*c = ((appctx->flags & APPCTX_FL_INOUT_BUFS)
|
||||
? *(b_head(&appctx->inbuf))
|
||||
: *(co_head(sc_oc(appctx_sc(appctx)))));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copies one full block of data from the applet input buffer (see
|
||||
* appet_get_inbuf).
|
||||
*
|
||||
* <len> bytes are capied, starting at the offset <offset>.
|
||||
*
|
||||
* Return values :
|
||||
* >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.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getblk(const struct appctx *appctx, char *blk, int len, int offset)
|
||||
{
|
||||
const struct buffer *buf;
|
||||
int ret;
|
||||
|
||||
ret = applet_may_get(appctx, len+offset);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
buf = ((appctx->flags & APPCTX_FL_INOUT_BUFS)
|
||||
? &appctx->inbuf
|
||||
: sc_ob(appctx_sc(appctx)));
|
||||
return b_getblk(buf, blk, len, offset);
|
||||
}
|
||||
|
||||
/* Gets one text block representing a word from the applet input buffer (see
|
||||
* appet_get_inbuf).
|
||||
*
|
||||
* The separator is waited for as long as some data can still be received and the
|
||||
* destination is not full. Otherwise, the string may be returned as is, without
|
||||
* the separator.
|
||||
*
|
||||
* Return values :
|
||||
* >0 : number of bytes read. Includes the separator if present before len or end.
|
||||
* =0 : no separator before end found. <str> is left undefined.
|
||||
* <0 : no more bytes readable because output is shut.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getword(const struct appctx *appctx, char *str, int len, char sep)
|
||||
{
|
||||
const struct buffer *buf;
|
||||
char *p;
|
||||
size_t input, max = len;
|
||||
int ret = 0;
|
||||
|
||||
ret = applet_may_get(appctx, 1);
|
||||
if (ret <= 0)
|
||||
goto out;
|
||||
|
||||
if (appctx->flags & APPCTX_FL_INOUT_BUFS) {
|
||||
buf = &appctx->inbuf;
|
||||
input = b_data(buf);
|
||||
}
|
||||
else {
|
||||
struct stconn *sc = appctx_sc(appctx);
|
||||
|
||||
buf = sc_ob(sc);
|
||||
input = co_data(sc_oc(sc));
|
||||
}
|
||||
|
||||
if (max > input) {
|
||||
max = input;
|
||||
str[max-1] = 0;
|
||||
}
|
||||
|
||||
p = b_head(buf);
|
||||
|
||||
while (max) {
|
||||
*str++ = *p;
|
||||
ret++;
|
||||
max--;
|
||||
if (*p == sep)
|
||||
goto out;
|
||||
p = b_next(buf, p);
|
||||
}
|
||||
|
||||
if (appctx->flags & APPCTX_FL_INOUT_BUFS) {
|
||||
if (ret < len && (ret < input || b_room(buf)) &&
|
||||
!se_fl_test(appctx->sedesc, SE_FL_SHW))
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
struct stconn *sc = appctx_sc(appctx);
|
||||
|
||||
if (ret < len && (ret < input || channel_may_recv(sc_oc(sc))) &&
|
||||
!(sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)))
|
||||
ret = 0;
|
||||
}
|
||||
out:
|
||||
if (max)
|
||||
*str = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Gets one text block representing a line from the applet input buffer (see
|
||||
* appet_get_inbuf).
|
||||
*
|
||||
* The '\n' is waited for as long as some data can still be received and the
|
||||
* destination is not full. Otherwise, the string may be returned as is, without
|
||||
* the '\n'.
|
||||
*
|
||||
* Return values :
|
||||
* >0 : number of bytes read. Includes the \n if present before len or end.
|
||||
* =0 : no '\n' before end found. <str> is left undefined.
|
||||
* <0 : no more bytes readable because output is shut.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getline(const struct appctx *appctx, char *str, int len)
|
||||
{
|
||||
return applet_getword(appctx, str, len, '\n');
|
||||
}
|
||||
|
||||
/* Gets one or two blocks of data at once from the applet input buffer (see appet_get_inbuf),
|
||||
*
|
||||
* Data are not copied.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getblk_nc(const struct appctx *appctx, const char **blk1, size_t *len1, const char **blk2, size_t *len2)
|
||||
{
|
||||
const struct buffer *buf;
|
||||
size_t max;
|
||||
int ret;
|
||||
|
||||
ret = applet_may_get(appctx, 1);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (appctx->flags & APPCTX_FL_INOUT_BUFS) {
|
||||
buf = &appctx->inbuf;
|
||||
max = b_data(buf);
|
||||
}
|
||||
else {
|
||||
struct stconn *sc = appctx_sc(appctx);
|
||||
|
||||
buf = sc_ob(sc);
|
||||
max = co_data(sc_oc(sc));
|
||||
}
|
||||
|
||||
return b_getblk_nc(buf, blk1, len1, blk2, len2, 0, max);
|
||||
}
|
||||
|
||||
/* Gets one or two blocks of text representing a word from the applet input
|
||||
* buffer (see appet_get_inbuf).
|
||||
*
|
||||
* Data are not copied. The separator is waited for as long as some data can
|
||||
* still be received and the destination is not full. Otherwise, the string may
|
||||
* be returned as is, without the separator.
|
||||
*
|
||||
* Return values :
|
||||
* >0 : number of bytes read. Includes the separator if present before len or end.
|
||||
* =0 : no separator before end found. <str> is left undefined.
|
||||
* <0 : no more bytes readable because output is shut.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getword_nc(const struct appctx *appctx, const char **blk1, size_t *len1, const char **blk2, size_t *len2, char sep)
|
||||
{
|
||||
int ret;
|
||||
size_t l;
|
||||
|
||||
ret = applet_getblk_nc(appctx, blk1, len1, blk2, len2);
|
||||
if (unlikely(ret <= 0))
|
||||
return ret;
|
||||
|
||||
for (l = 0; l < *len1 && (*blk1)[l] != sep; l++);
|
||||
if (l < *len1 && (*blk1)[l] == sep) {
|
||||
*len1 = l + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret >= 2) {
|
||||
for (l = 0; l < *len2 && (*blk2)[l] != sep; l++);
|
||||
if (l < *len2 && (*blk2)[l] == sep) {
|
||||
*len2 = l + 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have found no LF and the buffer is full or the SC is shut, then
|
||||
* the resulting string is made of the concatenation of the pending
|
||||
* blocks (1 or 2).
|
||||
*/
|
||||
if (appctx->flags & APPCTX_FL_INOUT_BUFS) {
|
||||
if (b_full(&appctx->inbuf) || se_fl_test(appctx->sedesc, SE_FL_SHW))
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
struct stconn *sc = appctx_sc(appctx);
|
||||
|
||||
if (!channel_may_recv(sc_oc(sc)) || sc->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED))
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* No LF yet and not shut yet */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Gets one or two blocks of text representing a line from the applet input
|
||||
* buffer (see appet_get_inbuf).
|
||||
*
|
||||
* Data are not copied. The '\n' is waited for as long as some data can still be
|
||||
* received and the destination is not full. Otherwise, the string may be
|
||||
* returned as is, without the '\n'.
|
||||
*
|
||||
* Return values :
|
||||
* >0 : number of bytes read. Includes the \n if present before len or end.
|
||||
* =0 : no '\n' before end found. <str> is left undefined.
|
||||
* <0 : no more bytes readable because output is shut.
|
||||
*
|
||||
* The status of the corresponding buffer is not changed. The caller must call
|
||||
* applet_skip_input() to update it.
|
||||
*/
|
||||
static inline int applet_getline_nc(const struct appctx *appctx, const char **blk1, size_t *len1, const char **blk2, size_t *len2)
|
||||
{
|
||||
return applet_getword_nc(appctx, blk1, len1, blk2, len2, '\n');
|
||||
}
|
||||
|
||||
#endif /* _HAPROXY_APPLET_H */
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user