static liAction* redirect_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { redirect_data *rd; UNUSED(wrk); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_STRING != li_value_type(val) && LI_VALUE_LIST != li_value_type(val)) { ERROR(srv, "%s", "redirect expects a either a string, a tuple of strings or a list of string tuples"); return NULL; } rd = g_slice_new(redirect_data); rd->p = p; rd->rules = g_array_new(FALSE, FALSE, sizeof(redirect_rule)); if (LI_VALUE_STRING == li_value_type(val)) { redirect_rule rule; /* redirect "/foo/bar"; */ if (!redirect_rule_parse(srv, NULL, val->data.string, &rule)) { redirect_free(NULL, rd); return NULL; } g_array_append_val(rd->rules, rule); } else if (li_value_list_has_len(val, 2) && LI_VALUE_STRING == li_value_list_type_at(val, 0) && LI_VALUE_STRING == li_value_list_type_at(val, 1)) { redirect_rule rule; /* only one rule */ if (!redirect_rule_parse(srv, li_value_list_at(val, 0)->data.string, li_value_list_at(val, 1)->data.string, &rule)) { redirect_free(NULL, rd); return NULL; } g_array_append_val(rd->rules, rule); } else { /* probably multiple rules */ LI_VALUE_FOREACH(v, val) redirect_rule rule; if (!li_value_list_has_len(v, 2) || LI_VALUE_STRING != li_value_list_type_at(v, 0) || LI_VALUE_STRING != li_value_list_type_at(v, 1)) { redirect_free(NULL, rd); ERROR(srv, "%s", "redirect expects a either a tuple of strings or a list of those"); return NULL; } if (!redirect_rule_parse(srv, li_value_list_at(v, 0)->data.string, li_value_list_at(v, 1)->data.string, &rule)) { redirect_free(NULL, rd); return NULL; } g_array_append_val(rd->rules, rule); LI_VALUE_END_FOREACH() } return li_action_new_function(redirect, NULL, redirect_free, rd); }
static liAction* mod_limit_action_create(liServer *srv, liPlugin *p, mod_limit_context_type type, liValue *val) { const char* act_names[] = { "limit.con", "limit.con_ip", "limit.req", "limit.req_ip" }; mod_limit_context *ctx; gint limit = 0; liAction *action_limit_reached = NULL; val = li_value_get_single_argument(val); val = li_value_get_single_argument(val); if (LI_VALUE_NUMBER == li_value_type(val) && val->data.number > 0) { /* limit.* N; */ limit = val->data.number; action_limit_reached = NULL; } else if (LI_VALUE_LIST == li_value_type(val) && li_value_list_has_len(val, 2) && LI_VALUE_NUMBER == li_value_list_type_at(val, 0) && li_value_list_at(val, 0)->data.number > 0 && LI_VALUE_ACTION == li_value_list_type_at(val, 1)) { limit = li_value_list_at(val, 0)->data.number; action_limit_reached = li_value_extract_action(li_value_list_at(val, 1)); } else { ERROR(srv, "%s expects either an integer > 0 as parameter, or a list of (int > 0,action)", act_names[type]); return NULL; } ctx = mod_limit_context_new(type, limit, action_limit_reached, p); return li_action_new_function(mod_limit_action_handle, NULL, mod_limit_action_free, ctx); }
static liAction* core_throttle_connection(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { liThrottleParam *param; guint64 rate, burst; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); val = li_value_get_single_argument(val); if (li_value_list_has_len(val, 2)) { liValue *v1 = li_value_list_at(val, 0); liValue *v2 = li_value_list_at(val, 1); if (LI_VALUE_NUMBER != li_value_type(v1) || LI_VALUE_NUMBER != li_value_type(v2)) { ERROR(srv, "%s", "'io.throttle' action expects a positiv integer or a pair of those as parameter"); return NULL; } rate = v2->data.number; burst = v1->data.number; } else if (LI_VALUE_NUMBER == li_value_type(val)) { rate = val->data.number; burst = 2 * rate; } else { ERROR(srv, "'io.throttle' action expects a positiv integer or a pair of those as parameter, %s given", li_value_type_string(val)); return NULL; } if ((rate != 0 || burst != 0) && !sanity_check(srv, rate, burst)) return NULL; param = g_slice_new(liThrottleParam); param->rate = rate; param->burst = burst; return li_action_new_function(core_handle_throttle_connection, NULL, core_throttle_connection_free, param); }
static gboolean balancer_fill_backends(balancer *b, liServer *srv, liValue *val) { val = li_value_get_single_argument(val); if (LI_VALUE_ACTION == li_value_type(val)) { backend be; be.act = val->data.val_action.action; be.load = 0; be.state = BE_ALIVE; be.wake = 0; assert(srv == val->data.val_action.srv); li_action_acquire(be.act); g_array_append_val(b->backends, be); return TRUE; } else if (LI_VALUE_LIST == li_value_type(val)) { if (li_value_list_has_len(val, 0)) { ERROR(srv, "%s", "expected non-empty list"); return FALSE; } LI_VALUE_FOREACH(oa, val) if (LI_VALUE_ACTION != li_value_type(oa)) { ERROR(srv, "expected action at entry %u of list, got %s", _oa_i, li_value_type_string(oa)); return FALSE; } assert(srv == oa->data.val_action.srv); { backend be; be.act = oa->data.val_action.action; be.load = 0; be.state = BE_ALIVE; be.wake = 0; li_action_acquire(be.act); g_array_append_val(b->backends, be); } LI_VALUE_END_FOREACH() return TRUE; } else {
liValue* li_value_to_key_value_list(liValue *val) { if (NULL == val) return NULL; if (LI_VALUE_LIST == val->type) { if (li_value_list_has_len(val, 2) && (LI_VALUE_STRING == li_value_list_type_at(val, 0) || LI_VALUE_NONE == li_value_list_type_at(val, 0))) { /* single key-value pair */ li_value_wrap_in_list(val); return val; } /* verify key-value list properties */ LI_VALUE_FOREACH(lentry, val) if (!li_value_list_has_len(lentry, 2)) return NULL; if (LI_VALUE_STRING != li_value_list_type_at(lentry, 0) && LI_VALUE_NONE != li_value_list_type_at(lentry, 0)) return NULL; LI_VALUE_END_FOREACH() return val; } return NULL; }
static liValue* option_value(liValue *val) { if (li_value_list_has_len(val, 1)) return li_value_list_at(val, 0); if (li_value_list_has_len(val, 0)) return NULL; return val; }