mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MEDIUM: spoe: Parse new "spoe-group" section in SPOE config file
For now, this section is only parsed. It should have the following format: spoe-group <grp-name> messages <msg-name> ... And then SPOE groups must be referenced in spoe-agent section: spoe-agnt <name> ... groups <grp-name> ... The purpose of these groups is to trigger messages sending from TCP or HTTP rules, directly from HAProxy configuration, and not on specific event. This part will be added in another patch. It is important to note that a message belongs at most to a group.
This commit is contained in:
parent
7ee8667c99
commit
11610f3b5a
66
doc/SPOE.txt
66
doc/SPOE.txt
@ -16,7 +16,8 @@ SUMMARY
|
|||||||
2.1. SPOE scope
|
2.1. SPOE scope
|
||||||
2.2. "spoe-agent" section
|
2.2. "spoe-agent" section
|
||||||
2.3. "spoe-message" section
|
2.3. "spoe-message" section
|
||||||
2.4. Example
|
2.4. "spoe-group" section
|
||||||
|
2.5. Example
|
||||||
3. SPOP specification
|
3. SPOP specification
|
||||||
3.1. Data types
|
3.1. Data types
|
||||||
3.2. Frames
|
3.2. Frames
|
||||||
@ -99,9 +100,8 @@ line, you completly disable the feature, including the parsing of sections
|
|||||||
reserved to SPOE. This is also a way to keep the HAProxy configuration clean.
|
reserved to SPOE. This is also a way to keep the HAProxy configuration clean.
|
||||||
|
|
||||||
A SPOE configuration file must contains, at least, the SPOA configuration
|
A SPOE configuration file must contains, at least, the SPOA configuration
|
||||||
("spoe-agent" section) and SPOE messages ("spoe-message" section) attached to
|
("spoe-agent" section) and SPOE messages/groups ("spoe-message" or "spoe-group"
|
||||||
this agent. Unused messages (not reference in "spoe-agent" section) will be
|
sections) attached to this agent.
|
||||||
ignored.
|
|
||||||
|
|
||||||
IMPORTANT : The configuration of a SPOE filter must be located in a dedicated
|
IMPORTANT : The configuration of a SPOE filter must be located in a dedicated
|
||||||
file. But the backend used by a SPOA must be declared in HAProxy configuration
|
file. But the backend used by a SPOA must be declared in HAProxy configuration
|
||||||
@ -114,8 +114,8 @@ If you specify an engine name on the SPOE filter line, then you need to define
|
|||||||
scope in the SPOE configuration with the same name. You can have several SPOE
|
scope in the SPOE configuration with the same name. You can have several SPOE
|
||||||
scope in the same file. In each scope, you must define one and only one
|
scope in the same file. In each scope, you must define one and only one
|
||||||
"spoe-agent" section to configure the SPOA linked to your SPOE and several
|
"spoe-agent" section to configure the SPOA linked to your SPOE and several
|
||||||
"spoe-message" sections to describe messages sent to servers mananged by your
|
"spoe-message" and "spoe-group" sections to describe, respecively, messages and
|
||||||
SPOA.
|
group of messages sent to servers mananged by your SPOA.
|
||||||
|
|
||||||
A SPOE scope starts with this kind of line :
|
A SPOE scope starts with this kind of line :
|
||||||
|
|
||||||
@ -132,6 +132,10 @@ scope ends when the file ends or when another scope is found.
|
|||||||
...
|
...
|
||||||
spoe-message msg2
|
spoe-message msg2
|
||||||
...
|
...
|
||||||
|
spoe-group grp1
|
||||||
|
...
|
||||||
|
spoe-group grp2
|
||||||
|
...
|
||||||
|
|
||||||
[my-second-engine]
|
[my-second-engine]
|
||||||
...
|
...
|
||||||
@ -159,6 +163,7 @@ spoe-agent <name>
|
|||||||
<name> is the name of the agent section.
|
<name> is the name of the agent section.
|
||||||
|
|
||||||
following keywords are supported :
|
following keywords are supported :
|
||||||
|
- groups
|
||||||
- maxconnrate
|
- maxconnrate
|
||||||
- maxerrrate
|
- maxerrrate
|
||||||
- max-frame-size
|
- max-frame-size
|
||||||
@ -173,6 +178,18 @@ spoe-agent <name>
|
|||||||
- use-backend
|
- use-backend
|
||||||
|
|
||||||
|
|
||||||
|
groups <grp-name> ...
|
||||||
|
Declare the list of SPOE groups that an agent will handle.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
<grp-name> is the name of a SPOE group.
|
||||||
|
|
||||||
|
Groups delcared here must be found in the same engine scope, else an error is
|
||||||
|
triggered during the configuration parsing. You can have many "groups" lines.
|
||||||
|
|
||||||
|
See also: "spoe-group" section.
|
||||||
|
|
||||||
|
|
||||||
maxconnrate <number>
|
maxconnrate <number>
|
||||||
Set the maximum number of connections per second to <number>. The SPOE will
|
Set the maximum number of connections per second to <number>. The SPOE will
|
||||||
stop to open new connections if the maximum is reached and will wait to
|
stop to open new connections if the maximum is reached and will wait to
|
||||||
@ -407,7 +424,42 @@ event <name> [ { if | unless } <condition> ]
|
|||||||
See section "Events & Messages" for more details about supported events.
|
See section "Events & Messages" for more details about supported events.
|
||||||
See section 7 about ACL usage in the HAProxy Configuration Manual.
|
See section 7 about ACL usage in the HAProxy Configuration Manual.
|
||||||
|
|
||||||
2.4. Example
|
2.4. "spoe-group" section
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
This section can be used to declare a group of SPOE messages. Unlike messages
|
||||||
|
referenced in a "spoe-agent" section, messages inside a group are not sent on a
|
||||||
|
specific event. The sending must be triggered by TCP or HTTP rules, from the
|
||||||
|
HAProxy configuration.
|
||||||
|
|
||||||
|
|
||||||
|
spoe-group <name>
|
||||||
|
Create a new SPOE group with the name <name>.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
<name> is the name of the SPOE group.
|
||||||
|
|
||||||
|
Here you define a group of SPOE messages that can be referenced in a
|
||||||
|
"spoe-agent" section. Following keywords are supported :
|
||||||
|
- messages
|
||||||
|
|
||||||
|
See also: "spoe-agent" and "spoe-message" sections.
|
||||||
|
|
||||||
|
|
||||||
|
messages <msg-name> ...
|
||||||
|
Declare the list of SPOE messages belonging to the group.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
<msg-name> is the name of a SPOE message.
|
||||||
|
|
||||||
|
Messages declared here must be found in the same engine scope, else an error
|
||||||
|
is triggered during the configuration parsing. Furthermore, a message belongs
|
||||||
|
at most to a group. You can have many "messages" lines.
|
||||||
|
|
||||||
|
See also: "spoe-message" section.
|
||||||
|
|
||||||
|
|
||||||
|
2.5. Example
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Here is a simple but complete example that sends client-ip address to a ip
|
Here is a simple but complete example that sends client-ip address to a ip
|
||||||
|
@ -164,29 +164,50 @@ struct spoe_arg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Used during the config parsing only because, when a SPOE agent section is
|
/* Used during the config parsing only because, when a SPOE agent section is
|
||||||
* parsed, messages can be undefined. */
|
* parsed, messages/groups can be undefined. */
|
||||||
struct spoe_msg_placeholder {
|
struct spoe_placeholder {
|
||||||
char *id; /* SPOE message placeholder id */
|
char *id; /* SPOE placeholder id */
|
||||||
struct list list; /* Use to chain SPOE message placeholders */
|
struct list list; /* Use to chain SPOE placeholders */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Describe a message that will be sent in a NOTIFY frame. A message has a name,
|
/* Describe a message that will be sent in a NOTIFY frame. A message has a name,
|
||||||
* an argument list (see above) and it is linked to a specific event. */
|
* an argument list (see above) and it is linked to a specific event. */
|
||||||
struct spoe_message {
|
struct spoe_message {
|
||||||
char *id; /* SPOE message id */
|
char *id; /* SPOE message id */
|
||||||
unsigned int id_len; /* The message id length */
|
unsigned int id_len; /* The message id length */
|
||||||
struct spoe_agent *agent; /* SPOE agent owning this SPOE message */
|
struct spoe_agent *agent; /* SPOE agent owning this SPOE message */
|
||||||
|
struct spoe_group *group; /* SPOE group owning this SPOE message (can be NULL) */
|
||||||
struct {
|
struct {
|
||||||
char *file; /* file where the SPOE message appears */
|
char *file; /* file where the SPOE message appears */
|
||||||
int line; /* line where the SPOE message appears */
|
int line; /* line where the SPOE message appears */
|
||||||
} conf; /* config information */
|
} conf; /* config information */
|
||||||
unsigned int nargs; /* # of arguments */
|
unsigned int nargs; /* # of arguments */
|
||||||
struct list args; /* Arguments added when the SPOE messages is sent */
|
struct list args; /* Arguments added when the SPOE messages is sent */
|
||||||
struct list list; /* Used to chain SPOE messages */
|
struct list list; /* Used to chain SPOE messages */
|
||||||
|
struct list by_evt; /* By event list */
|
||||||
|
struct list by_grp; /* By group list */
|
||||||
|
|
||||||
struct list acls; /* ACL declared on this message */
|
struct list acls; /* ACL declared on this message */
|
||||||
struct acl_cond *cond; /* acl condition to meet */
|
struct acl_cond *cond; /* acl condition to meet */
|
||||||
enum spoe_event event; /* SPOE_EV_* */
|
enum spoe_event event; /* SPOE_EV_* */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Describe a group of messages that will be sent in a NOTIFY frame. A group has
|
||||||
|
* a name and a list of messages. It can be used by HAProxy, outside events
|
||||||
|
* processing, mainly in (tcp|http) rules. */
|
||||||
|
struct spoe_group {
|
||||||
|
char *id; /* SPOE group id */
|
||||||
|
struct spoe_agent *agent; /* SPOE agent owning this SPOE group */
|
||||||
|
struct {
|
||||||
|
char *file; /* file where the SPOE group appears */
|
||||||
|
int line; /* line where the SPOE group appears */
|
||||||
|
} conf; /* config information */
|
||||||
|
|
||||||
|
struct list phs; /* List of placeholders used during conf parsing */
|
||||||
|
struct list messages; /* List of SPOE messages that will be sent by this
|
||||||
|
* group */
|
||||||
|
|
||||||
|
struct list list; /* Used to chain SPOE groups */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Describe a SPOE agent. */
|
/* Describe a SPOE agent. */
|
||||||
@ -217,9 +238,13 @@ struct spoe_agent {
|
|||||||
unsigned int min_applets; /* Minimum # applets alive at a time */
|
unsigned int min_applets; /* Minimum # applets alive at a time */
|
||||||
unsigned int max_fpa; /* Maximum # of frames handled per applet at once */
|
unsigned int max_fpa; /* Maximum # of frames handled per applet at once */
|
||||||
|
|
||||||
struct list messages[SPOE_EV_EVENTS]; /* List of SPOE messages that will be sent
|
struct list events[SPOE_EV_EVENTS]; /* List of SPOE messages that will be sent
|
||||||
* for each supported events */
|
* for each supported events */
|
||||||
|
|
||||||
|
struct list groups; /* List of available SPOE groups */
|
||||||
|
|
||||||
|
struct list messages; /* list of all messages attached to this SPOE agent */
|
||||||
|
|
||||||
/* running info */
|
/* running info */
|
||||||
unsigned int frame_size; /* current maximum frame size, only used to encode messages */
|
unsigned int frame_size; /* current maximum frame size, only used to encode messages */
|
||||||
unsigned int applets_act; /* # of applets alive at a time */
|
unsigned int applets_act; /* # of applets alive at a time */
|
||||||
@ -250,7 +275,8 @@ struct spoe_context {
|
|||||||
struct filter *filter; /* The SPOE filter */
|
struct filter *filter; /* The SPOE filter */
|
||||||
struct stream *strm; /* The stream that should be offloaded */
|
struct stream *strm; /* The stream that should be offloaded */
|
||||||
|
|
||||||
struct list *messages; /* List of messages that will be sent during the stream processing */
|
struct list *events; /* List of messages that will be sent during the stream processing */
|
||||||
|
|
||||||
struct buffer *buffer; /* Buffer used to store a encoded messages */
|
struct buffer *buffer; /* Buffer used to store a encoded messages */
|
||||||
struct buffer_wait buffer_wait; /* position in the list of ressources waiting for a buffer */
|
struct buffer_wait buffer_wait; /* position in the list of ressources waiting for a buffer */
|
||||||
struct list list;
|
struct list list;
|
||||||
|
332
src/flt_spoe.c
332
src/flt_spoe.c
@ -74,14 +74,16 @@ struct proxy *curproxy = NULL;
|
|||||||
char *curengine = NULL;
|
char *curengine = NULL;
|
||||||
|
|
||||||
/* SPOE agent used during the parsing */
|
/* SPOE agent used during the parsing */
|
||||||
struct spoe_agent *curagent = NULL;
|
/* SPOE agent/group/message used during the parsing */
|
||||||
|
struct spoe_agent *curagent = NULL;
|
||||||
/* SPOE message used during the parsing */
|
struct spoe_group *curgrp = NULL;
|
||||||
struct spoe_message *curmsg = NULL;
|
struct spoe_message *curmsg = NULL;
|
||||||
|
|
||||||
/* list of SPOE messages and placeholders used during the parsing */
|
/* list of SPOE messages and placeholders used during the parsing */
|
||||||
struct list curmsgs;
|
struct list curmsgs;
|
||||||
struct list curmps;
|
struct list curgrps;
|
||||||
|
struct list curmphs;
|
||||||
|
struct list curgphs;
|
||||||
|
|
||||||
/* Pools used to allocate SPOE structs */
|
/* Pools used to allocate SPOE structs */
|
||||||
static struct pool_head *pool2_spoe_ctx = NULL;
|
static struct pool_head *pool2_spoe_ctx = NULL;
|
||||||
@ -97,12 +99,12 @@ static void spoe_release_buffer(struct buffer **buf, struct buffer_wait *buffer_
|
|||||||
* helper functions/globals
|
* helper functions/globals
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
static void
|
static void
|
||||||
spoe_release_msg_placeholder(struct spoe_msg_placeholder *mp)
|
spoe_release_placeholder(struct spoe_placeholder *ph)
|
||||||
{
|
{
|
||||||
if (!mp)
|
if (!ph)
|
||||||
return;
|
return;
|
||||||
free(mp->id);
|
free(ph->id);
|
||||||
free(mp);
|
free(ph);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -133,11 +135,21 @@ spoe_release_message(struct spoe_message *msg)
|
|||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spoe_release_group(struct spoe_group *grp)
|
||||||
|
{
|
||||||
|
if (!grp)
|
||||||
|
return;
|
||||||
|
free(grp->id);
|
||||||
|
free(grp->conf.file);
|
||||||
|
free(grp);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spoe_release_agent(struct spoe_agent *agent)
|
spoe_release_agent(struct spoe_agent *agent)
|
||||||
{
|
{
|
||||||
struct spoe_message *msg, *back;
|
struct spoe_message *msg, *msgback;
|
||||||
int i;
|
struct spoe_group *grp, *grpback;
|
||||||
|
|
||||||
if (!agent)
|
if (!agent)
|
||||||
return;
|
return;
|
||||||
@ -146,11 +158,13 @@ spoe_release_agent(struct spoe_agent *agent)
|
|||||||
free(agent->var_pfx);
|
free(agent->var_pfx);
|
||||||
free(agent->engine_id);
|
free(agent->engine_id);
|
||||||
free(agent->var_on_error);
|
free(agent->var_on_error);
|
||||||
for (i = 0; i < SPOE_EV_EVENTS; ++i) {
|
list_for_each_entry_safe(msg, msgback, &agent->messages, list) {
|
||||||
list_for_each_entry_safe(msg, back, &agent->messages[i], list) {
|
LIST_DEL(&msg->list);
|
||||||
LIST_DEL(&msg->list);
|
spoe_release_message(msg);
|
||||||
spoe_release_message(msg);
|
}
|
||||||
}
|
list_for_each_entry_safe(grp, grpback, &agent->groups, list) {
|
||||||
|
LIST_DEL(&grp->list);
|
||||||
|
spoe_release_group(grp);
|
||||||
}
|
}
|
||||||
free(agent);
|
free(agent);
|
||||||
}
|
}
|
||||||
@ -2105,7 +2119,7 @@ spoe_encode_messages(struct stream *s, struct spoe_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Loop on messages */
|
/* Loop on messages */
|
||||||
list_for_each_entry(msg, messages, list) {
|
list_for_each_entry(msg, messages, by_evt) {
|
||||||
ctx->frag_ctx.curmsg = msg;
|
ctx->frag_ctx.curmsg = msg;
|
||||||
ctx->frag_ctx.curarg = NULL;
|
ctx->frag_ctx.curarg = NULL;
|
||||||
ctx->frag_ctx.curoff = UINT_MAX;
|
ctx->frag_ctx.curoff = UINT_MAX;
|
||||||
@ -2466,7 +2480,7 @@ spoe_process_event(struct stream *s, struct spoe_context *ctx,
|
|||||||
|
|
||||||
dir = ((ev < SPOE_EV_ON_SERVER_SESS) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES);
|
dir = ((ev < SPOE_EV_ON_SERVER_SESS) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES);
|
||||||
|
|
||||||
if (LIST_ISEMPTY(&(ctx->messages[ev])))
|
if (LIST_ISEMPTY(&(ctx->events[ev])))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (ctx->state == SPOE_CTX_ST_ERROR)
|
if (ctx->state == SPOE_CTX_ST_ERROR)
|
||||||
@ -2511,7 +2525,7 @@ spoe_process_event(struct stream *s, struct spoe_context *ctx,
|
|||||||
if (ctx->state == SPOE_CTX_ST_ENCODING_MSGS) {
|
if (ctx->state == SPOE_CTX_ST_ENCODING_MSGS) {
|
||||||
if (!spoe_acquire_buffer(&ctx->buffer, &ctx->buffer_wait))
|
if (!spoe_acquire_buffer(&ctx->buffer, &ctx->buffer_wait))
|
||||||
goto out;
|
goto out;
|
||||||
ret = spoe_encode_messages(s, ctx, &(ctx->messages[ev]), dir);
|
ret = spoe_encode_messages(s, ctx, &(ctx->events[ev]), dir);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@ -2640,7 +2654,7 @@ spoe_create_context(struct filter *filter)
|
|||||||
ctx->state = SPOE_CTX_ST_NONE;
|
ctx->state = SPOE_CTX_ST_NONE;
|
||||||
ctx->status_code = SPOE_CTX_ERR_NONE;
|
ctx->status_code = SPOE_CTX_ERR_NONE;
|
||||||
ctx->flags = 0;
|
ctx->flags = 0;
|
||||||
ctx->messages = conf->agent->messages;
|
ctx->events = conf->agent->events;
|
||||||
ctx->buffer = &buf_empty;
|
ctx->buffer = &buf_empty;
|
||||||
LIST_INIT(&ctx->buffer_wait.list);
|
LIST_INIT(&ctx->buffer_wait.list);
|
||||||
ctx->buffer_wait.target = ctx;
|
ctx->buffer_wait.target = ctx;
|
||||||
@ -2834,22 +2848,22 @@ spoe_start(struct stream *s, struct filter *filter)
|
|||||||
ctx->state = SPOE_CTX_ST_READY;
|
ctx->state = SPOE_CTX_ST_READY;
|
||||||
filter->ctx = ctx;
|
filter->ctx = ctx;
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&ctx->messages[SPOE_EV_ON_TCP_REQ_FE]))
|
if (!LIST_ISEMPTY(&ctx->events[SPOE_EV_ON_TCP_REQ_FE]))
|
||||||
filter->pre_analyzers |= AN_REQ_INSPECT_FE;
|
filter->pre_analyzers |= AN_REQ_INSPECT_FE;
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&ctx->messages[SPOE_EV_ON_TCP_REQ_BE]))
|
if (!LIST_ISEMPTY(&ctx->events[SPOE_EV_ON_TCP_REQ_BE]))
|
||||||
filter->pre_analyzers |= AN_REQ_INSPECT_BE;
|
filter->pre_analyzers |= AN_REQ_INSPECT_BE;
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&ctx->messages[SPOE_EV_ON_TCP_RSP]))
|
if (!LIST_ISEMPTY(&ctx->events[SPOE_EV_ON_TCP_RSP]))
|
||||||
filter->pre_analyzers |= AN_RES_INSPECT;
|
filter->pre_analyzers |= AN_RES_INSPECT;
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&ctx->messages[SPOE_EV_ON_HTTP_REQ_FE]))
|
if (!LIST_ISEMPTY(&ctx->events[SPOE_EV_ON_HTTP_REQ_FE]))
|
||||||
filter->pre_analyzers |= AN_REQ_HTTP_PROCESS_FE;
|
filter->pre_analyzers |= AN_REQ_HTTP_PROCESS_FE;
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&ctx->messages[SPOE_EV_ON_HTTP_REQ_BE]))
|
if (!LIST_ISEMPTY(&ctx->events[SPOE_EV_ON_HTTP_REQ_BE]))
|
||||||
filter->pre_analyzers |= AN_REQ_HTTP_PROCESS_BE;
|
filter->pre_analyzers |= AN_REQ_HTTP_PROCESS_BE;
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&ctx->messages[SPOE_EV_ON_HTTP_RSP]))
|
if (!LIST_ISEMPTY(&ctx->events[SPOE_EV_ON_HTTP_RSP]))
|
||||||
filter->pre_analyzers |= AN_RES_HTTP_PROCESS_FE;
|
filter->pre_analyzers |= AN_RES_HTTP_PROCESS_FE;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -3083,7 +3097,9 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
|
|||||||
curagent->max_fpa = 100;
|
curagent->max_fpa = 100;
|
||||||
|
|
||||||
for (i = 0; i < SPOE_EV_EVENTS; ++i)
|
for (i = 0; i < SPOE_EV_EVENTS; ++i)
|
||||||
LIST_INIT(&curagent->messages[i]);
|
LIST_INIT(&curagent->events[i]);
|
||||||
|
LIST_INIT(&curagent->groups);
|
||||||
|
LIST_INIT(&curagent->messages);
|
||||||
|
|
||||||
curagent->frame_size = curagent->max_frame_size;
|
curagent->frame_size = curagent->max_frame_size;
|
||||||
curagent->applets_act = 0;
|
curagent->applets_act = 0;
|
||||||
@ -3109,24 +3125,48 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
|
|||||||
else if (!strcmp(args[0], "messages")) {
|
else if (!strcmp(args[0], "messages")) {
|
||||||
int cur_arg = 1;
|
int cur_arg = 1;
|
||||||
while (*args[cur_arg]) {
|
while (*args[cur_arg]) {
|
||||||
struct spoe_msg_placeholder *mp = NULL;
|
struct spoe_placeholder *ph = NULL;
|
||||||
|
|
||||||
list_for_each_entry(mp, &curmps, list) {
|
list_for_each_entry(ph, &curmphs, list) {
|
||||||
if (!strcmp(mp->id, args[cur_arg])) {
|
if (!strcmp(ph->id, args[cur_arg])) {
|
||||||
Alert("parsing [%s:%d]: spoe-message message '%s' already declared.\n",
|
Alert("parsing [%s:%d]: spoe-message '%s' already used.\n",
|
||||||
file, linenum, args[cur_arg]);
|
file, linenum, args[cur_arg]);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mp = calloc(1, sizeof(*mp))) == NULL) {
|
if ((ph = calloc(1, sizeof(*ph))) == NULL) {
|
||||||
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
|
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
|
||||||
err_code |= ERR_ALERT | ERR_ABORT;
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
mp->id = strdup(args[cur_arg]);
|
ph->id = strdup(args[cur_arg]);
|
||||||
LIST_ADDQ(&curmps, &mp->list);
|
LIST_ADDQ(&curmphs, &ph->list);
|
||||||
|
cur_arg++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(args[0], "groups")) {
|
||||||
|
int cur_arg = 1;
|
||||||
|
while (*args[cur_arg]) {
|
||||||
|
struct spoe_placeholder *ph = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(ph, &curgphs, list) {
|
||||||
|
if (!strcmp(ph->id, args[cur_arg])) {
|
||||||
|
Alert("parsing [%s:%d]: spoe-group '%s' already used.\n",
|
||||||
|
file, linenum, args[cur_arg]);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ph = calloc(1, sizeof(*ph))) == NULL) {
|
||||||
|
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
|
||||||
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ph->id = strdup(args[cur_arg]);
|
||||||
|
LIST_ADDQ(&curgphs, &ph->list);
|
||||||
cur_arg++;
|
cur_arg++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3323,6 +3363,94 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm)
|
|||||||
out:
|
out:
|
||||||
return err_code;
|
return err_code;
|
||||||
}
|
}
|
||||||
|
static int
|
||||||
|
cfg_parse_spoe_group(const char *file, int linenum, char **args, int kwm)
|
||||||
|
{
|
||||||
|
struct spoe_group *grp;
|
||||||
|
const char *err;
|
||||||
|
int err_code = 0;
|
||||||
|
|
||||||
|
if ((cfg_scope == NULL && curengine != NULL) ||
|
||||||
|
(cfg_scope != NULL && curengine == NULL) ||
|
||||||
|
(curengine != NULL && cfg_scope != NULL && strcmp(curengine, cfg_scope)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!strcmp(args[0], "spoe-group")) { /* new spoe-group section */
|
||||||
|
if (!*args[1]) {
|
||||||
|
Alert("parsing [%s:%d] : missing name for spoe-group section.\n",
|
||||||
|
file, linenum);
|
||||||
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
|
||||||
|
err_code |= ERR_ABORT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = invalid_char(args[1]);
|
||||||
|
if (err) {
|
||||||
|
Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
|
||||||
|
file, linenum, *err, args[0], args[1]);
|
||||||
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(grp, &curgrps, list) {
|
||||||
|
if (!strcmp(grp->id, args[1])) {
|
||||||
|
Alert("parsing [%s:%d]: spoe-group section '%s' has the same"
|
||||||
|
" name as another one declared at %s:%d.\n",
|
||||||
|
file, linenum, args[1], grp->conf.file, grp->conf.line);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((curgrp = calloc(1, sizeof(*curgrp))) == NULL) {
|
||||||
|
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
|
||||||
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
curgrp->id = strdup(args[1]);
|
||||||
|
curgrp->conf.file = strdup(file);
|
||||||
|
curgrp->conf.line = linenum;
|
||||||
|
LIST_INIT(&curgrp->phs);
|
||||||
|
LIST_INIT(&curgrp->messages);
|
||||||
|
LIST_ADDQ(&curgrps, &curgrp->list);
|
||||||
|
}
|
||||||
|
else if (!strcmp(args[0], "messages")) {
|
||||||
|
int cur_arg = 1;
|
||||||
|
while (*args[cur_arg]) {
|
||||||
|
struct spoe_placeholder *ph = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(ph, &curgrp->phs, list) {
|
||||||
|
if (!strcmp(ph->id, args[cur_arg])) {
|
||||||
|
Alert("parsing [%s:%d]: spoe-message '%s' already used.\n",
|
||||||
|
file, linenum, args[cur_arg]);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ph = calloc(1, sizeof(*ph))) == NULL) {
|
||||||
|
Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
|
||||||
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ph->id = strdup(args[cur_arg]);
|
||||||
|
LIST_ADDQ(&curgrp->phs, &ph->list);
|
||||||
|
cur_arg++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*args[0]) {
|
||||||
|
Alert("parsing [%s:%d] : unknown keyword '%s' in spoe-group section.\n",
|
||||||
|
file, linenum, args[0]);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return err_code;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cfg_parse_spoe_message(const char *file, int linenum, char **args, int kwm)
|
cfg_parse_spoe_message(const char *file, int linenum, char **args, int kwm)
|
||||||
@ -3382,6 +3510,8 @@ cfg_parse_spoe_message(const char *file, int linenum, char **args, int kwm)
|
|||||||
curmsg->nargs = 0;
|
curmsg->nargs = 0;
|
||||||
LIST_INIT(&curmsg->args);
|
LIST_INIT(&curmsg->args);
|
||||||
LIST_INIT(&curmsg->acls);
|
LIST_INIT(&curmsg->acls);
|
||||||
|
LIST_INIT(&curmsg->by_evt);
|
||||||
|
LIST_INIT(&curmsg->by_grp);
|
||||||
LIST_ADDQ(&curmsgs, &curmsg->list);
|
LIST_ADDQ(&curmsgs, &curmsg->list);
|
||||||
}
|
}
|
||||||
else if (!strcmp(args[0], "args")) {
|
else if (!strcmp(args[0], "args")) {
|
||||||
@ -3518,7 +3648,8 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
struct list backup_sections;
|
struct list backup_sections;
|
||||||
struct spoe_config *conf;
|
struct spoe_config *conf;
|
||||||
struct spoe_message *msg, *msgback;
|
struct spoe_message *msg, *msgback;
|
||||||
struct spoe_msg_placeholder *mp, *mpback;
|
struct spoe_group *grp, *grpback;
|
||||||
|
struct spoe_placeholder *ph, *phback;
|
||||||
char *file = NULL, *engine = NULL;
|
char *file = NULL, *engine = NULL;
|
||||||
int ret, pos = *cur_arg + 1;
|
int ret, pos = *cur_arg + 1;
|
||||||
|
|
||||||
@ -3561,7 +3692,8 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
/* backup sections and register SPOE sections */
|
/* backup sections and register SPOE sections */
|
||||||
LIST_INIT(&backup_sections);
|
LIST_INIT(&backup_sections);
|
||||||
cfg_backup_sections(&backup_sections);
|
cfg_backup_sections(&backup_sections);
|
||||||
cfg_register_section("spoe-agent", cfg_parse_spoe_agent, NULL);
|
cfg_register_section("spoe-agent", cfg_parse_spoe_agent, NULL);
|
||||||
|
cfg_register_section("spoe-group", cfg_parse_spoe_group, NULL);
|
||||||
cfg_register_section("spoe-message", cfg_parse_spoe_message, NULL);
|
cfg_register_section("spoe-message", cfg_parse_spoe_message, NULL);
|
||||||
|
|
||||||
/* Parse SPOE filter configuration file */
|
/* Parse SPOE filter configuration file */
|
||||||
@ -3569,6 +3701,10 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
curproxy = px;
|
curproxy = px;
|
||||||
curagent = NULL;
|
curagent = NULL;
|
||||||
curmsg = NULL;
|
curmsg = NULL;
|
||||||
|
LIST_INIT(&curmsgs);
|
||||||
|
LIST_INIT(&curgrps);
|
||||||
|
LIST_INIT(&curmphs);
|
||||||
|
LIST_INIT(&curgphs);
|
||||||
ret = readcfgfile(file);
|
ret = readcfgfile(file);
|
||||||
curproxy = NULL;
|
curproxy = NULL;
|
||||||
|
|
||||||
@ -3622,18 +3758,20 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
if (curagent->engine_id == NULL)
|
if (curagent->engine_id == NULL)
|
||||||
curagent->engine_id = generate_pseudo_uuid();
|
curagent->engine_id = generate_pseudo_uuid();
|
||||||
|
|
||||||
if (LIST_ISEMPTY(&curmps)) {
|
if (LIST_ISEMPTY(&curmphs) && LIST_ISEMPTY(&curgphs)) {
|
||||||
Warning("Proxy '%s': No message used by SPOE agent '%s' declared at %s:%d.\n",
|
Warning("Proxy '%s': No message/group used by SPOE agent '%s' declared at %s:%d.\n",
|
||||||
px->id, curagent->id, curagent->conf.file, curagent->conf.line);
|
px->id, curagent->id, curagent->conf.file, curagent->conf.line);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_safe(mp, mpback, &curmps, list) {
|
/* Replace placeholders by the corresponding messages for the SPOE
|
||||||
list_for_each_entry_safe(msg, msgback, &curmsgs, list) {
|
* agent */
|
||||||
|
list_for_each_entry(ph, &curmphs, list) {
|
||||||
|
list_for_each_entry(msg, &curmsgs, list) {
|
||||||
struct spoe_arg *arg;
|
struct spoe_arg *arg;
|
||||||
unsigned int where;
|
unsigned int where;
|
||||||
|
|
||||||
if (!strcmp(msg->id, mp->id)) {
|
if (!strcmp(msg->id, ph->id)) {
|
||||||
if ((px->cap & (PR_CAP_FE|PR_CAP_BE)) == (PR_CAP_FE|PR_CAP_BE)) {
|
if ((px->cap & (PR_CAP_FE|PR_CAP_BE)) == (PR_CAP_FE|PR_CAP_BE)) {
|
||||||
if (msg->event == SPOE_EV_ON_TCP_REQ_BE)
|
if (msg->event == SPOE_EV_ON_TCP_REQ_BE)
|
||||||
msg->event = SPOE_EV_ON_TCP_REQ_FE;
|
msg->event = SPOE_EV_ON_TCP_REQ_FE;
|
||||||
@ -3645,12 +3783,12 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
msg->event == SPOE_EV_ON_HTTP_REQ_FE)) {
|
msg->event == SPOE_EV_ON_HTTP_REQ_FE)) {
|
||||||
Warning("Proxy '%s': frontend event used on a backend proxy at %s:%d.\n",
|
Warning("Proxy '%s': frontend event used on a backend proxy at %s:%d.\n",
|
||||||
px->id, msg->conf.file, msg->conf.line);
|
px->id, msg->conf.file, msg->conf.line);
|
||||||
goto next;
|
goto next_mph;
|
||||||
}
|
}
|
||||||
if (msg->event == SPOE_EV_NONE) {
|
if (msg->event == SPOE_EV_NONE) {
|
||||||
Warning("Proxy '%s': Ignore SPOE message without event at %s:%d.\n",
|
Warning("Proxy '%s': Ignore SPOE message without event at %s:%d.\n",
|
||||||
px->id, msg->conf.file, msg->conf.line);
|
px->id, msg->conf.file, msg->conf.line);
|
||||||
goto next;
|
goto next_mph;
|
||||||
}
|
}
|
||||||
|
|
||||||
where = 0;
|
where = 0;
|
||||||
@ -3711,37 +3849,93 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
px->id, msg->conf.file, msg->conf.line,
|
px->id, msg->conf.file, msg->conf.line,
|
||||||
sample_ckp_names(arg->expr->fetch->use),
|
sample_ckp_names(arg->expr->fetch->use),
|
||||||
sample_ckp_names(where));
|
sample_ckp_names(where));
|
||||||
goto next;
|
goto next_mph;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->agent = curagent;
|
msg->agent = curagent;
|
||||||
LIST_DEL(&msg->list);
|
LIST_ADDQ(&curagent->events[msg->event], &msg->by_evt);
|
||||||
LIST_ADDQ(&curagent->messages[msg->event], &msg->list);
|
goto next_mph;
|
||||||
goto next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memprintf(err, "SPOE agent '%s' try to use undefined SPOE message '%s' at %s:%d",
|
memprintf(err, "SPOE agent '%s' try to use undefined SPOE message '%s' at %s:%d",
|
||||||
curagent->id, mp->id, curagent->conf.file, curagent->conf.line);
|
curagent->id, ph->id, curagent->conf.file, curagent->conf.line);
|
||||||
goto error;
|
goto error;
|
||||||
next:
|
next_mph:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
/* Replace placeholders by the corresponding groups for the SPOE
|
||||||
conf->id = strdup(engine ? engine : curagent->id);
|
* agent */
|
||||||
conf->agent = curagent;
|
list_for_each_entry(ph, &curgphs, list) {
|
||||||
list_for_each_entry_safe(mp, mpback, &curmps, list) {
|
list_for_each_entry_safe(grp, grpback, &curgrps, list) {
|
||||||
LIST_DEL(&mp->list);
|
if (!strcmp(grp->id, ph->id)) {
|
||||||
spoe_release_msg_placeholder(mp);
|
grp->agent = curagent;
|
||||||
}
|
LIST_DEL(&grp->list);
|
||||||
list_for_each_entry_safe(msg, msgback, &curmsgs, list) {
|
LIST_ADDQ(&curagent->groups, &grp->list);
|
||||||
Warning("Proxy '%s': Ignore unused SPOE messages '%s' declared at %s:%d.\n",
|
goto next_aph;
|
||||||
px->id, msg->id, msg->conf.file, msg->conf.line);
|
}
|
||||||
LIST_DEL(&msg->list);
|
}
|
||||||
spoe_release_message(msg);
|
memprintf(err, "SPOE agent '%s' try to use undefined SPOE group '%s' at %s:%d",
|
||||||
|
curagent->id, ph->id, curagent->conf.file, curagent->conf.line);
|
||||||
|
goto error;
|
||||||
|
next_aph:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace placeholders by the corresponding message for each SPOE
|
||||||
|
* group of the SPOE agent */
|
||||||
|
list_for_each_entry(grp, &curagent->groups, list) {
|
||||||
|
list_for_each_entry_safe(ph, phback, &grp->phs, list) {
|
||||||
|
list_for_each_entry(msg, &curmsgs, list) {
|
||||||
|
if (!strcmp(msg->id, ph->id)) {
|
||||||
|
if (msg->group != NULL) {
|
||||||
|
memprintf(err, "SPOE message '%s' already belongs to "
|
||||||
|
"the SPOE group '%s' declare at %s:%d",
|
||||||
|
msg->id, msg->group->id,
|
||||||
|
msg->group->conf.file,
|
||||||
|
msg->group->conf.line);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scope for arguments are not checked for now. We will check
|
||||||
|
* them only if a rule use the corresponding SPOE group. */
|
||||||
|
msg->agent = curagent;
|
||||||
|
msg->group = grp;
|
||||||
|
LIST_DEL(&ph->list);
|
||||||
|
LIST_ADDQ(&grp->messages, &msg->by_grp);
|
||||||
|
goto next_mph_grp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memprintf(err, "SPOE group '%s' try to use undefined SPOE message '%s' at %s:%d",
|
||||||
|
grp->id, ph->id, curagent->conf.file, curagent->conf.line);
|
||||||
|
goto error;
|
||||||
|
next_mph_grp:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
/* move curmsgs to the agent message list */
|
||||||
|
curmsgs.n->p = &curagent->messages;
|
||||||
|
curmsgs.p->n = &curagent->messages;
|
||||||
|
curagent->messages = curmsgs;
|
||||||
|
LIST_INIT(&curmsgs);
|
||||||
|
|
||||||
|
conf->id = strdup(engine ? engine : curagent->id);
|
||||||
|
conf->agent = curagent;
|
||||||
|
list_for_each_entry_safe(ph, phback, &curmphs, list) {
|
||||||
|
LIST_DEL(&ph->list);
|
||||||
|
spoe_release_placeholder(ph);
|
||||||
|
}
|
||||||
|
list_for_each_entry_safe(ph, phback, &curgphs, list) {
|
||||||
|
LIST_DEL(&ph->list);
|
||||||
|
spoe_release_placeholder(ph);
|
||||||
|
}
|
||||||
|
list_for_each_entry_safe(grp, grpback, &curgrps, list) {
|
||||||
|
LIST_DEL(&grp->list);
|
||||||
|
spoe_release_group(grp);
|
||||||
|
}
|
||||||
*cur_arg = pos;
|
*cur_arg = pos;
|
||||||
fconf->id = spoe_filter_id;
|
fconf->id = spoe_filter_id;
|
||||||
fconf->ops = &spoe_ops;
|
fconf->ops = &spoe_ops;
|
||||||
@ -3750,9 +3944,17 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
spoe_release_agent(curagent);
|
spoe_release_agent(curagent);
|
||||||
list_for_each_entry_safe(mp, mpback, &curmps, list) {
|
list_for_each_entry_safe(ph, phback, &curmphs, list) {
|
||||||
LIST_DEL(&mp->list);
|
LIST_DEL(&ph->list);
|
||||||
spoe_release_msg_placeholder(mp);
|
spoe_release_placeholder(ph);
|
||||||
|
}
|
||||||
|
list_for_each_entry_safe(ph, phback, &curgphs, list) {
|
||||||
|
LIST_DEL(&ph->list);
|
||||||
|
spoe_release_placeholder(ph);
|
||||||
|
}
|
||||||
|
list_for_each_entry_safe(grp, grpback, &curgrps, list) {
|
||||||
|
LIST_DEL(&grp->list);
|
||||||
|
spoe_release_group(grp);
|
||||||
}
|
}
|
||||||
list_for_each_entry_safe(msg, msgback, &curmsgs, list) {
|
list_for_each_entry_safe(msg, msgback, &curmsgs, list) {
|
||||||
LIST_DEL(&msg->list);
|
LIST_DEL(&msg->list);
|
||||||
@ -3775,8 +3977,6 @@ static void __spoe_init(void)
|
|||||||
{
|
{
|
||||||
flt_register_keywords(&flt_kws);
|
flt_register_keywords(&flt_kws);
|
||||||
|
|
||||||
LIST_INIT(&curmsgs);
|
|
||||||
LIST_INIT(&curmps);
|
|
||||||
pool2_spoe_ctx = create_pool("spoe_ctx", sizeof(struct spoe_context), MEM_F_SHARED);
|
pool2_spoe_ctx = create_pool("spoe_ctx", sizeof(struct spoe_context), MEM_F_SHARED);
|
||||||
pool2_spoe_appctx = create_pool("spoe_appctx", sizeof(struct spoe_appctx), MEM_F_SHARED);
|
pool2_spoe_appctx = create_pool("spoe_appctx", sizeof(struct spoe_appctx), MEM_F_SHARED);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user