haproxy/include/haproxy/applet-t.h

151 lines
6.7 KiB
C
Raw Normal View History

/*
* include/haproxy/applet-t.h
* This file describes the applet struct and associated constants.
*
* Copyright (C) 2000-2020 Willy Tarreau - w@1wt.eu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HAPROXY_APPLET_T_H
#define _HAPROXY_APPLET_T_H
#include <haproxy/api-t.h>
#include <haproxy/buf-t.h>
#include <haproxy/dynbuf-t.h>
#include <haproxy/freq_ctr-t.h>
#include <haproxy/obj_type-t.h>
#include <haproxy/show_flags-t.h>
#include <haproxy/task-t.h>
#include <haproxy/xref-t.h>
/* flags for appctx->state */
MINOR: applet: reserve some generic storage in the applet's context Instead of using existing fields and having to put keyword-specific contexts in the applet definition, let's have the appctx provide a generic storage area that's currently large enough for existing CLI commands and small applets, and a function to allocate that storage. The function will be responsible for verifying that the requested size fits in the area so that the caller doesn't need to add specific checks; it is validated during development as this size is static and will not change at runtime. In addition the caller doesn't even need to free() the area since it's part of an existing context. For the caller's convenience, a context pointer "svcctx" for the command is also provided so that the allocated area can be placed there (or possibly any other one in case a larger area is needed). The struct's layout has been temporarily complicated by adding one level of anonymous union on top of the "ctx" one. This will allow us to preserve "ctx" during 2.6 for compatibility with possible external code and get rid of it in 2.7. This explains why the diff extends to the whole "ctx" union, but a "git show -b" shows that only one extra layer was added. In order to make both the svcctx pointer and its storage accessible without further enlarging the appctx structure, both svcctx and the storage share the same storage as the ctx part. This is done by having them placed in the union with a protected overlapping area for svcctx, for which a shadow member is also present in the storage area: union { void* svcctx; // variable accessed by services struct { void *shadow; // shadow of svcctx; char storage[]; // where most services store their data }; union { // older commands store here and ignore svcctx ... } ctx; }; I.e. new applications will use appctx->svcctx while older ones will be able to continue to use appctx->ctx.* The whole area (including the pointer's context) is zeroed before any applet is initialized, and before CLI keyword processor's first invocation, as it is an important part of the existing keyword processors, which makes CLI keywords effectively behave like applets.
2022-05-02 08:57:03 -04:00
/* Room for per-command context (mostly CLI commands but not only) */
#define APPLET_MAX_SVCCTX 128
MINOR: applet: reserve some generic storage in the applet's context Instead of using existing fields and having to put keyword-specific contexts in the applet definition, let's have the appctx provide a generic storage area that's currently large enough for existing CLI commands and small applets, and a function to allocate that storage. The function will be responsible for verifying that the requested size fits in the area so that the caller doesn't need to add specific checks; it is validated during development as this size is static and will not change at runtime. In addition the caller doesn't even need to free() the area since it's part of an existing context. For the caller's convenience, a context pointer "svcctx" for the command is also provided so that the allocated area can be placed there (or possibly any other one in case a larger area is needed). The struct's layout has been temporarily complicated by adding one level of anonymous union on top of the "ctx" one. This will allow us to preserve "ctx" during 2.6 for compatibility with possible external code and get rid of it in 2.7. This explains why the diff extends to the whole "ctx" union, but a "git show -b" shows that only one extra layer was added. In order to make both the svcctx pointer and its storage accessible without further enlarging the appctx structure, both svcctx and the storage share the same storage as the ctx part. This is done by having them placed in the union with a protected overlapping area for svcctx, for which a shadow member is also present in the storage area: union { void* svcctx; // variable accessed by services struct { void *shadow; // shadow of svcctx; char storage[]; // where most services store their data }; union { // older commands store here and ignore svcctx ... } ctx; }; I.e. new applications will use appctx->svcctx while older ones will be able to continue to use appctx->ctx.* The whole area (including the pointer's context) is zeroed before any applet is initialized, and before CLI keyword processor's first invocation, as it is an important part of the existing keyword processors, which makes CLI keywords effectively behave like applets.
2022-05-02 08:57:03 -04:00
/* Appctx Flags */
#define APPCTX_FL_INBLK_ALLOC 0x00000001
#define APPCTX_FL_INBLK_FULL 0x00000002
#define APPCTX_FL_OUTBLK_ALLOC 0x00000004
#define APPCTX_FL_OUTBLK_FULL 0x00000008
#define APPCTX_FL_EOI 0x00000010
#define APPCTX_FL_EOS 0x00000020
#define APPCTX_FL_ERR_PENDING 0x00000040
#define APPCTX_FL_ERROR 0x00000080
#define APPCTX_FL_SHUTDOWN 0x00000100 /* applet was shut down (->release() called if any). No more data exchange with SCs */
#define APPCTX_FL_WANT_DIE 0x00000200 /* applet was running and requested to die */
#define APPCTX_FL_INOUT_BUFS 0x00000400 /* applet uses its own buffers */
#define APPCTX_FL_FASTFWD 0x00000800 /* zero-copy forwarding is in-use, don't fill the outbuf */
#define APPCTX_FL_IN_MAYALLOC 0x00001000 /* applet may try again to allocate its inbuf */
#define APPCTX_FL_OUT_MAYALLOC 0x00002000 /* applet may try again to allocate its outbuf */
struct appctx;
struct proxy;
struct stconn;
struct sedesc;
struct se_abort_info;
struct session;
/* This function is used to report flags in debugging tools. Please reflect
* below any single-bit flag addition above in the same order via the
* __APPEND_FLAG macro. The new end of the buffer is returned.
*/
static forceinline char *appctx_show_flags(char *buf, size_t len, const char *delim, uint flg)
{
#define _(f, ...) __APPEND_FLAG(buf, len, delim, flg, f, #f, __VA_ARGS__)
/* prologue */
_(0);
/* flags */
_(APPCTX_FL_INBLK_ALLOC, _(APPCTX_FL_INBLK_FULL,
_(APPCTX_FL_OUTBLK_ALLOC, _(APPCTX_FL_OUTBLK_FULL,
_(APPCTX_FL_EOI, _(APPCTX_FL_EOS,
_(APPCTX_FL_ERR_PENDING, _(APPCTX_FL_ERROR,
_(APPCTX_FL_SHUTDOWN, _(APPCTX_FL_WANT_DIE, _(APPCTX_FL_INOUT_BUFS,
_(APPCTX_FL_FASTFWD, _(APPCTX_FL_IN_MAYALLOC, _(APPCTX_FL_OUT_MAYALLOC))))))))))))));
/* epilogue */
_(~0U);
return buf;
#undef _
}
/* Applet descriptor */
struct applet {
enum obj_type obj_type; /* object type = OBJ_TYPE_APPLET */
/* 3 unused bytes here */
char *name; /* applet's name to report in logs */
int (*init)(struct appctx *); /* callback to init resources, may be NULL.
expect 0 if ok, -1 if an error occurs. */
void (*fct)(struct appctx *); /* internal I/O handler, may never be NULL */
size_t (*rcv_buf)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* called from the upper layer to get data */
size_t (*snd_buf)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* Called from the upper layet to put data */
size_t (*fastfwd)(struct appctx *appctx, struct buffer *buf, size_t count, unsigned int flags); /* Callback to fast-forward data */
void (*shut)(struct appctx *appctx, unsigned int mode, struct se_abort_info *reason); /* shutdown function */
void (*release)(struct appctx *); /* callback to release resources, may be NULL */
unsigned int timeout; /* execution timeout. */
};
/* Context of a running applet. */
struct appctx {
enum obj_type obj_type; /* OBJ_TYPE_APPCTX */
/* 3 unused bytes here */
unsigned int st0; /* CLI state for stats, session state for peers */
unsigned int st1; /* prompt/payload (bitwise OR of APPCTX_CLI_ST1_*) for stats, session error for peers */
unsigned int flags; /* APPCTX_FL_* */
struct buffer inbuf;
struct buffer outbuf;
size_t to_forward;
struct buffer *chunk; /* used to store unfinished commands */
struct applet *applet; /* applet this context refers to */
struct session *sess; /* session for frontend applets (NULL for backend applets) */
struct sedesc *sedesc; /* stream endpoint descriptor the applet is attached to */
struct act_rule *rule; /* rule associated with the applet. */
int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK */
void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK,
if the command is terminated or the session released */
int cli_severity_output; /* used within the cli_io_handler to format severity output of informational feedback */
int cli_level; /* the level of CLI which can be lowered dynamically */
char cli_payload_pat[8]; /* Payload pattern */
uint32_t cli_anon_key; /* the key to anonymise with the hash in cli */
BUG/MAJOR: Fix how the list of entities waiting for a buffer is handled When an entity tries to get a buffer, if it cannot be allocted, for example because the number of buffers which may be allocated per process is limited, this entity is added in a list (called <buffer_wq>) and wait for an available buffer. Historically, the <buffer_wq> list was logically attached to streams because it were the only entities likely to be added in it. Now, applets can also be waiting for a free buffer. And with filters, we could imagine to have more other entities waiting for a buffer. So it make sense to have a generic list. Anyway, with the current design there is a bug. When an applet failed to get a buffer, it will wait. But we add the stream attached to the applet in <buffer_wq>, instead of the applet itself. So when a buffer is available, we wake up the stream and not the waiting applet. So, it is possible to have waiting applets and never awakened. So, now, <buffer_wq> is independant from streams. And we really add the waiting entity in <buffer_wq>. To be generic, the entity is responsible to define the callback used to awaken it. In addition, applets will still request an input buffer when they become active. But they will not be sleeped anymore if no buffer are available. So this is the responsibility to the applet I/O handler to check if this buffer is allocated or not. This way, an applet can decide if this buffer is required or not and can do additional processing if not. [wt: backport to 1.7 and 1.6]
2016-12-09 11:30:18 -05:00
struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
struct task *t; /* task associated to the applet */
struct freq_ctr call_rate; /* appctx call rate */
struct mt_list wait_entry; /* entry in a list of waiters for an event (e.g. ring events) */
/* The pointer seen by application code is appctx->svcctx. In 2.7 the
* anonymous union and the "ctx" struct disappeared, and the struct
* "svc" became svc_storage, which is never accessed directly by
* application code. Look at "show fd" for an example.
*/
/* here we have the service's context (CLI command, applet, etc) */
void *svcctx; /* pointer to a context used by the command, e.g. <storage> below */
struct {
void *shadow; /* shadow of svcctx above, do not use! */
char storage[APPLET_MAX_SVCCTX]; /* storage of svcctx above */
} svc; /* generic storage for most commands */
};
#endif /* _HAPROXY_APPLET_T_H */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/