diff --git a/include/types/action.h b/include/types/action.h index 09c14c504..713631ed0 100644 --- a/include/types/action.h +++ b/include/types/action.h @@ -32,6 +32,12 @@ enum act_from { ACT_F_HTTP_RES, /* http-response */ }; +enum act_return { + ACT_RET_CONT, /* continue processing. */ + ACT_RET_YIELD, /* call me again. */ + ACT_RET_ERR, /* processing error. */ +}; + enum act_name { ACT_ACTION_CONT = 0, ACT_ACTION_STOP, @@ -78,8 +84,8 @@ struct act_rule { enum act_name action; /* ACT_ACTION_* */ enum act_from from; /* ACT_F_* */ short deny_status; /* HTTP status to return to user when denying */ - int (*action_ptr)(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s); /* ptr to custom action */ + enum act_return (*action_ptr)(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s); /* ptr to custom action */ union { struct { char *realm; diff --git a/src/hlua.c b/src/hlua.c index 16ebc8d07..5395b6d30 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -4270,8 +4270,8 @@ static int hlua_parse_rule(const char **args, int *cur_arg, struct proxy *px, * return 0 if the function must be called again because the LUA * returns a yield. */ -static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, - struct stream *s, unsigned int analyzer) +static enum act_return hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, + struct stream *s, unsigned int analyzer) { char **arg; @@ -4284,7 +4284,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, send_log(px, LOG_ERR, "Lua action '%s': can't initialize Lua context.", rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) Alert("Lua action '%s': can't initialize Lua context.\n", rule->fcn.name); - return 1; + return ACT_RET_CONT; } /* If it is the first run, initialize the data for the call. */ @@ -4294,7 +4294,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, send_log(px, LOG_ERR, "Lua function '%s': full stack.", rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) Alert("Lua function '%s': full stack.\n", rule->fcn.name); - return 1; + return ACT_RET_CONT; } /* Restore the function in the stack. */ @@ -4305,7 +4305,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, send_log(px, LOG_ERR, "Lua function '%s': full stack.", rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) Alert("Lua function '%s': full stack.\n", rule->fcn.name); - return 1; + return ACT_RET_CONT; } s->hlua.nargs = 1; @@ -4315,7 +4315,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, send_log(px, LOG_ERR, "Lua function '%s': full stack.", rule->fcn.name); if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) Alert("Lua function '%s': full stack.\n", rule->fcn.name); - return 1; + return ACT_RET_CONT; } lua_pushstring(s->hlua.T, *arg); s->hlua.nargs++; @@ -4332,7 +4332,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, switch (hlua_ctx_resume(&s->hlua, 1)) { /* finished. */ case HLUA_E_OK: - return 1; + return ACT_RET_CONT; /* yield. */ case HLUA_E_AGAIN: @@ -4354,7 +4354,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, } if (HLUA_IS_WAKEREQWR(&s->hlua)) s->req.flags |= CF_WAKE_WRITE; - return 0; + return ACT_RET_YIELD; /* finished with error. */ case HLUA_E_ERRMSG: @@ -4363,7 +4363,7 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) Alert("Lua function '%s': %s.\n", rule->fcn.name, lua_tostring(s->hlua.T, -1)); lua_pop(s->hlua.T, 1); - return 1; + return ACT_RET_CONT; case HLUA_E_ERR: /* Display log. */ @@ -4372,15 +4372,15 @@ static int hlua_request_act_wrapper(struct hlua_rule *rule, struct proxy *px, Alert("Lua function '%s' return an unknown error.\n", rule->fcn.name); default: - return 1; + return ACT_RET_CONT; } } /* Lua execution wrapper for "tcp-request". This function uses * "hlua_request_act_wrapper" for executing the LUA code. */ -int hlua_tcp_req_act_wrapper(struct act_rule *act_rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return hlua_tcp_req_act_wrapper(struct act_rule *act_rule, struct proxy *px, + struct session *sess, struct stream *s) { return hlua_request_act_wrapper(act_rule->arg.hlua_rule, px, s, AN_REQ_INSPECT_FE); } @@ -4388,8 +4388,8 @@ int hlua_tcp_req_act_wrapper(struct act_rule *act_rule, struct proxy *px, /* Lua execution wrapper for "tcp-response". This function uses * "hlua_request_act_wrapper" for executing the LUA code. */ -int hlua_tcp_res_act_wrapper(struct act_rule *act_rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return hlua_tcp_res_act_wrapper(struct act_rule *act_rule, struct proxy *px, + struct session *sess, struct stream *s) { return hlua_request_act_wrapper(act_rule->arg.hlua_rule, px, s, AN_RES_INSPECT); } @@ -4398,8 +4398,8 @@ int hlua_tcp_res_act_wrapper(struct act_rule *act_rule, struct proxy *px, * This function uses "hlua_request_act_wrapper" for executing * the LUA code. */ -int hlua_http_req_act_wrapper(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return hlua_http_req_act_wrapper(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { return hlua_request_act_wrapper(rule->arg.hlua_rule, px, s, AN_REQ_HTTP_PROCESS_FE); } @@ -4408,8 +4408,8 @@ int hlua_http_req_act_wrapper(struct act_rule *rule, struct proxy *px, * This function uses "hlua_request_act_wrapper" for executing * the LUA code. */ -int hlua_http_res_act_wrapper(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return hlua_http_res_act_wrapper(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { return hlua_request_act_wrapper(rule->arg.hlua_rule, px, s, AN_RES_HTTP_PROCESS_BE); } diff --git a/src/proto_http.c b/src/proto_http.c index 6bd73b1cd..ce43ec599 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3627,15 +3627,24 @@ resume_execution: } case ACT_ACTION_CONT: - if (!rule->action_ptr(rule, px, s->sess, s)) { + switch (rule->action_ptr(rule, px, s->sess, s)) { + case ACT_RET_ERR: + case ACT_RET_CONT: + break; + case ACT_RET_YIELD: s->current_rule = rule; return HTTP_RULE_RES_YIELD; } break; case ACT_ACTION_STOP: - rule->action_ptr(rule, px, s->sess, s); - return HTTP_RULE_RES_DONE; + switch (rule->action_ptr(rule, px, s->sess, s)) { + case ACT_RET_YIELD: + case ACT_RET_ERR: + case ACT_RET_CONT: + return HTTP_RULE_RES_DONE; + } + break; case ACT_ACTION_TRK_SC0 ... ACT_ACTION_TRK_SCMAX: /* Note: only the first valid tracking parameter of each @@ -3907,7 +3916,11 @@ resume_execution: return HTTP_RULE_RES_DONE; case ACT_ACTION_CONT: - if (!rule->action_ptr(rule, px, s->sess, s)) { + switch (rule->action_ptr(rule, px, s->sess, s)) { + case ACT_RET_ERR: + case ACT_RET_CONT: + break; + case ACT_RET_YIELD: s->current_rule = rule; return HTTP_RULE_RES_YIELD; } @@ -12246,8 +12259,8 @@ int http_replace_req_line(int action, const char *replace, int len, * http_action_set_req_line_exec(). It always returns 1. If an error occurs * the action is canceled, but the rule processing continue. */ -int http_action_set_req_line(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return http_action_set_req_line(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { chunk_reset(&trash); @@ -12257,7 +12270,7 @@ int http_action_set_req_line(struct act_rule *rule, struct proxy *px, trash.len += build_logline(s, trash.str + trash.len, trash.size - trash.len, &rule->arg.http.logfmt); http_replace_req_line(rule->arg.http.action, trash.str, trash.len, px, s); - return 1; + return ACT_RET_CONT; } /* parse an http-request action among : @@ -12320,8 +12333,8 @@ int parse_set_req_line(const char **args, int *orig_arg, struct proxy *px, struc * returns 1. If an error occurs the action is cancelled, but the rule * processing continues. */ -int http_action_req_capture(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return http_action_req_capture(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { struct sample *key; struct cap_hdr *h = rule->arg.cap.hdr; @@ -12330,13 +12343,13 @@ int http_action_req_capture(struct act_rule *rule, struct proxy *px, key = sample_fetch_as_type(s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.cap.expr, SMP_T_STR); if (!key) - return 1; + return ACT_RET_CONT; if (cap[h->index] == NULL) cap[h->index] = pool_alloc2(h->pool); if (cap[h->index] == NULL) /* no more capture memory */ - return 1; + return ACT_RET_CONT; len = key->data.u.str.len; if (len > h->len) @@ -12344,7 +12357,7 @@ int http_action_req_capture(struct act_rule *rule, struct proxy *px, memcpy(cap[h->index], key->data.u.str.str, len); cap[h->index][len] = 0; - return 1; + return ACT_RET_CONT; } /* This function executes the "capture" action and store the result in a @@ -12352,8 +12365,8 @@ int http_action_req_capture(struct act_rule *rule, struct proxy *px, * into a string and puts it in a capture slot. It always returns 1. If an * error occurs the action is cancelled, but the rule processing continues. */ -int http_action_req_capture_by_id(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return http_action_req_capture_by_id(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { struct sample *key; struct cap_hdr *h; @@ -12367,17 +12380,17 @@ int http_action_req_capture_by_id(struct act_rule *rule, struct proxy *px, h != NULL && i != rule->arg.capid.idx ; i--, h = h->next); if (!h) - return 1; + return ACT_RET_CONT; key = sample_fetch_as_type(s->be, sess, s, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->arg.capid.expr, SMP_T_STR); if (!key) - return 1; + return ACT_RET_CONT; if (cap[h->index] == NULL) cap[h->index] = pool_alloc2(h->pool); if (cap[h->index] == NULL) /* no more capture memory */ - return 1; + return ACT_RET_CONT; len = key->data.u.str.len; if (len > h->len) @@ -12385,7 +12398,7 @@ int http_action_req_capture_by_id(struct act_rule *rule, struct proxy *px, memcpy(cap[h->index], key->data.u.str.str, len); cap[h->index][len] = 0; - return 1; + return ACT_RET_CONT; } /* parse an "http-request capture" action. It takes a single argument which is @@ -12519,8 +12532,8 @@ int parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, s * into a string and puts it in a capture slot. It always returns 1. If an * error occurs the action is cancelled, but the rule processing continues. */ -int http_action_res_capture_by_id(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +enum act_return http_action_res_capture_by_id(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { struct sample *key; struct cap_hdr *h; @@ -12534,17 +12547,17 @@ int http_action_res_capture_by_id(struct act_rule *rule, struct proxy *px, h != NULL && i != rule->arg.capid.idx ; i--, h = h->next); if (!h) - return 1; + return ACT_RET_CONT; key = sample_fetch_as_type(s->be, sess, s, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->arg.capid.expr, SMP_T_STR); if (!key) - return 1; + return ACT_RET_CONT; if (cap[h->index] == NULL) cap[h->index] = pool_alloc2(h->pool); if (cap[h->index] == NULL) /* no more capture memory */ - return 1; + return ACT_RET_CONT; len = key->data.u.str.len; if (len > h->len) @@ -12552,7 +12565,7 @@ int http_action_res_capture_by_id(struct act_rule *rule, struct proxy *px, memcpy(cap[h->index], key->data.u.str.str, len); cap[h->index][len] = 0; - return 1; + return ACT_RET_CONT; } /* parse an "http-response capture" action. It takes a single argument which is diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 3c70357da..f797042fd 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -1231,9 +1231,15 @@ resume_execution: } else { /* Custom keywords. */ - if (rule->action_ptr && !rule->action_ptr(rule, s->be, s->sess, s)) { - s->current_rule = rule; - goto missing_data; + if (rule->action_ptr) { + switch (rule->action_ptr(rule, s->be, s->sess, s)) { + case ACT_RET_ERR: + case ACT_RET_CONT: + break; + case ACT_RET_YIELD: + s->current_rule = rule; + goto missing_data; + } } /* accept */ @@ -1356,10 +1362,16 @@ resume_execution: } else { /* Custom keywords. */ - if (rule->action_ptr && !rule->action_ptr(rule, s->be, s->sess, s)) { - channel_dont_close(rep); - s->current_rule = rule; - return 0; + if (rule->action_ptr) { + switch (rule->action_ptr(rule, s->be, s->sess, s)) { + case ACT_RET_ERR: + case ACT_RET_CONT: + break; + case ACT_RET_YIELD: + channel_dont_close(rep); + s->current_rule = rule; + return 0; + } } /* accept */ @@ -1441,7 +1453,19 @@ int tcp_exec_req_rules(struct session *sess) else { /* Custom keywords. */ if (rule->action_ptr) { - rule->action_ptr(rule, sess->fe, sess, NULL); + switch (rule->action_ptr(rule, sess->fe, sess, NULL)) { + case ACT_RET_YIELD: + /* yield is not allowed at this point. If this return code is + * used it is a bug, so I prefer to abort the process. + */ + send_log(sess->fe, LOG_WARNING, + "Internal error: yield not allowed with tcp-request connection actions."); + case ACT_RET_CONT: + break; + case ACT_RET_ERR: + result = 0; + break; + } if (rule->action == ACT_ACTION_CONT) continue; } diff --git a/src/vars.c b/src/vars.c index 86ac93b7b..430801232 100644 --- a/src/vars.c +++ b/src/vars.c @@ -482,49 +482,49 @@ int vars_get_by_desc(const struct var_desc *var_desc, struct stream *strm, struc /* Returns 0 if we need to come back later to complete the sample's retrieval, * otherwise 1. For now all processing is considered final so we only return 1. */ -static inline int action_store(struct sample_expr *expr, const char *name, - enum vars_scope scope, struct proxy *px, - struct stream *s, int sens) +static inline enum act_return action_store(struct sample_expr *expr, const char *name, + enum vars_scope scope, struct proxy *px, + struct stream *s, int sens) { struct sample smp; /* Process the expression. */ memset(&smp, 0, sizeof(smp)); if (!sample_process(px, s->sess, s, sens|SMP_OPT_FINAL, expr, &smp)) - return 1; + return ACT_RET_CONT; /* Store the sample, and ignore errors. */ sample_store_stream(name, scope, s, &smp); - return 1; + return ACT_RET_CONT; } /* Wrapper for action_store */ -static int action_tcp_req_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +static enum act_return action_tcp_req_store(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { return action_store(rule->arg.vars.expr, rule->arg.vars.name, rule->arg.vars.scope, px, s, SMP_OPT_DIR_REQ); } /* Wrapper for action_store */ -static int action_tcp_res_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +static enum act_return action_tcp_res_store(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { return action_store(rule->arg.vars.expr, rule->arg.vars.name, rule->arg.vars.scope, px, s, SMP_OPT_DIR_RES); } /* Wrapper for action_store */ -static int action_http_req_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +static enum act_return action_http_req_store(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { return action_store(rule->arg.vars.expr, rule->arg.vars.name, rule->arg.vars.scope, px, s, SMP_OPT_DIR_REQ); } /* Wrapper for action_store */ -static int action_http_res_store(struct act_rule *rule, struct proxy *px, - struct session *sess, struct stream *s) +static enum act_return action_http_res_store(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s) { return action_store(rule->arg.vars.expr, rule->arg.vars.name, rule->arg.vars.scope, px, s, SMP_OPT_DIR_RES);