static gboolean al_option_accesslog_format_parse(liServer *srv, liWorker *wrk, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { GArray *arr; UNUSED(wrk); UNUSED(p); UNUSED(ndx); if (!val) { /* default */ arr = al_parse_format(srv, AL_DEFAULT_FORMAT); } else if (val->type != LI_VALUE_STRING) { ERROR(srv, "accesslog.format option expects a string as parameter, %s given", li_value_type_string(val->type)); return FALSE; } else { arr = al_parse_format(srv, val->data.string->str); } if (!arr) { ERROR(srv, "%s", "failed to parse accesslog format"); return FALSE; } *oval = arr; return TRUE; }
static gboolean balancer_fill_backends(balancer *b, liServer *srv, liValue *val) { if (val->type == LI_VALUE_ACTION) { backend be = { val->data.val_action.action, 0, BE_ALIVE, 0 }; assert(srv == val->data.val_action.srv); li_action_acquire(be.act); g_array_append_val(b->backends, be); return TRUE; } else if (val->type == LI_VALUE_LIST) { guint i; if (val->data.list->len == 0) { ERROR(srv, "%s", "expected non-empty list"); return FALSE; } for (i = 0; i < val->data.list->len; i++) { liValue *oa = g_array_index(val->data.list, liValue*, i); if (oa->type != LI_VALUE_ACTION) { ERROR(srv, "expected action at entry %u of list, got %s", i, li_value_type_string(oa->type)); return FALSE; } assert(srv == oa->data.val_action.srv); { backend be = { oa->data.val_action.action, 0, BE_ALIVE, 0 }; li_action_acquire(be.act); g_array_append_val(b->backends, be); } } return TRUE; } else {
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 {
static gboolean li_parse_optionptr(liServer *srv, liWorker *wrk, liServerOptionPtr *sopt, const char *name, liValue *val, liOptionPtrSet *mark) { liOptionPtrValue *oval; gpointer ptr = NULL; LI_FORCE_ASSERT(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != mark); if (NULL != val && LI_VALUE_LIST == sopt->type && val->type != LI_VALUE_LIST) { li_value_wrap_in_list(val); } if (NULL != val && sopt->type != val->type && sopt->type != LI_VALUE_NONE) { ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s", li_value_type_string(val), li_valuetype_string(sopt->type), name); return FALSE; } if (NULL == sopt->parse_option) { if (NULL == val) { switch (sopt->type) { case LI_VALUE_STRING: ptr = g_string_new((const char*) sopt->default_value); break; default: ptr = NULL; } } else { ptr = li_value_extract_ptr(val); } } else { if (!sopt->parse_option(srv, wrk, sopt->p, sopt->module_index, val, &ptr)) { /* errors should be logged by parse function */ return FALSE; } } if (NULL != ptr) { oval = g_slice_new0(liOptionPtrValue); oval->refcount = 1; oval->sopt = sopt; oval->data.ptr = ptr; } else { oval = NULL; } mark->ndx = sopt->index; mark->value = oval; return TRUE; }
static gboolean progress_ttl(liServer *srv, liPlugin* p, liValue *val, gpointer userdata) { mod_progress_data *pd = p->data; UNUSED(userdata); if (!val) { ERROR(srv, "%s", "progress.ttl expects a number as parameter"); return FALSE; } if (val->type != LI_VALUE_NUMBER) { ERROR(srv, "expected number, got %s", li_value_type_string(val->type)); return FALSE; } pd->ttl = val->data.number; return TRUE; }
static gboolean al_option_accesslog_parse(liServer *srv, liWorker *wrk, liPlugin *p, size_t ndx, liValue *val, gpointer *oval) { UNUSED(wrk); UNUSED(p); UNUSED(ndx); if (!val) { /* default */ return TRUE; } if (val->type != LI_VALUE_STRING) { ERROR(srv, "accesslog option expects a string as parameter, %s given", li_value_type_string(val->type)); return FALSE; } *oval = li_value_extract_string(val); return TRUE; }
static liAction* core_throttle_pool(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { liThrottlePool *pool = NULL; gint64 rate, burst; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_NUMBER != li_value_type(val)) { ERROR(srv, "'io.throttle_pool' action expects a number as parameter, %s given", li_value_type_string(val)); return NULL; } rate = val->data.number; burst = rate; if (!sanity_check(srv, rate, burst)) return NULL; pool = li_throttle_pool_new(srv, rate, burst); return li_action_new_function(core_handle_throttle_pool, NULL, core_throttle_pool_free, pool); }
static gboolean li_parse_option(liServer *srv, liWorker *wrk, liServerOption *sopt, const char *name, liValue *val, liOptionSet *mark) { LI_FORCE_ASSERT(NULL != srv && NULL != wrk && NULL != sopt && NULL != name && NULL != mark); if (NULL != val && LI_VALUE_LIST == sopt->type && val->type != LI_VALUE_LIST) { li_value_wrap_in_list(val); } if (NULL != val && sopt->type != val->type && sopt->type != LI_VALUE_NONE) { ERROR(srv, "Unexpected value type '%s', expected '%s' for option %s", li_value_type_string(val), li_valuetype_string(sopt->type), name); return FALSE; } if (NULL == sopt->parse_option) { switch (sopt->type) { case LI_VALUE_BOOLEAN: mark->value.boolean = (NULL == val) ? GPOINTER_TO_INT(sopt->default_value) : val->data.boolean; break; case LI_VALUE_NUMBER: mark->value.number = (NULL == val) ? GPOINTER_TO_INT(sopt->default_value) : val->data.number; break; default: ERROR(srv, "Invalid scalar option type '%s' for option %s", li_valuetype_string(sopt->type), name); return FALSE; } } else { if (!sopt->parse_option(srv, wrk, sopt->p, sopt->module_index, val, &mark->value)) { /* errors should be logged by parse function */ return FALSE; } } mark->ndx = sopt->index; return TRUE; }
static liAction* vhost_map_regex_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { vhost_map_regex_data *mrd; UNUSED(wrk); UNUSED(userdata); val = li_value_get_single_argument(val); if (NULL == (val = li_value_to_key_value_list(val))) { ERROR(srv, "%s", "vhost.map_regex expects a hashtable/key-value list as parameter"); return NULL; } mrd = g_slice_new0(vhost_map_regex_data); mrd->plugin = p; mrd->list = g_array_new(FALSE, FALSE, sizeof(vhost_map_regex_entry)); LI_VALUE_FOREACH(entry, val) liValue *entryKey = li_value_list_at(entry, 0); liValue *entryValue = li_value_list_at(entry, 1); GString *entryKeyStr; if (LI_VALUE_ACTION != li_value_type(entryValue)) { ERROR(srv, "vhost.map_regex expects a hashtable/key-value list with action values as parameter, %s value given", li_value_type_string(entryValue)); vhost_map_free(srv, mrd); return NULL; } /* we now own the key string: free it in case of failure */ entryKeyStr = li_value_extract_string(entryKey); if (NULL != entryKeyStr && g_str_equal(entryKeyStr->str, "default")) { WARNING(srv, "%s", "vhost.map_regex: found entry with string key \"default\". please convert the parameter to a key-value list and use the keyword default instead."); /* TODO: remove support for "default" (LI_VALUE_HASH) */ g_string_free(entryKeyStr, TRUE); entryKeyStr = NULL; } if (NULL == entryKeyStr) { if (NULL != mrd->default_action) { ERROR(srv, "%s", "vhost.map_regex: already have a default action"); vhost_map_free(srv, mrd); return NULL; } mrd->default_action = li_value_extract(entryValue); } else { GError *err = NULL; vhost_map_regex_entry map_entry; map_entry.regex = g_regex_new(entryKeyStr->str, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err); g_string_free(entryKeyStr, TRUE); if (NULL == map_entry.regex) { assert(NULL != err); vhost_map_regex_free(srv, mrd); ERROR(srv, "vhost.map_regex: error compiling regex \"%s\": %s", entryKeyStr->str, err->message); g_error_free(err); return NULL; } assert(NULL == err); map_entry.action = li_value_extract(entryValue); g_array_append_val(mrd->list, map_entry); } LI_VALUE_END_FOREACH() return li_action_new_function(vhost_map_regex, NULL, vhost_map_regex_free, mrd); }
static liAction* vhost_map_create(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { vhost_map_data *md; UNUSED(wrk); UNUSED(userdata); val = li_value_get_single_argument(val); if (NULL == (val = li_value_to_key_value_list(val))) { ERROR(srv, "%s", "vhost.map expects a hashtable/key-value list as parameter"); return NULL; } md = g_slice_new0(vhost_map_data); md->plugin = p; md->hash = li_value_new_hashtable(); LI_VALUE_FOREACH(entry, val) liValue *entryKey = li_value_list_at(entry, 0); liValue *entryValue = li_value_list_at(entry, 1); GString *entryKeyStr; if (LI_VALUE_ACTION != li_value_type(entryValue)) { ERROR(srv, "vhost.map expects a hashtable/key-value list with action values as parameter, %s value given", li_value_type_string(entryValue)); vhost_map_free(srv, md); return NULL; } /* we now own the key string: free it in case of failure */ entryKeyStr = li_value_extract_string(entryKey); if (NULL != entryKeyStr && g_str_equal(entryKeyStr->str, "default")) { WARNING(srv, "%s", "vhost.map: found entry with string key \"default\". please convert the parameter to a key-value list and use the keyword default instead."); /* TODO: remove support for "default" (LI_VALUE_HASH) */ g_string_free(entryKeyStr, TRUE); entryKeyStr = NULL; } if (NULL == entryKeyStr) { if (NULL != md->default_action) { ERROR(srv, "%s", "vhost.map: already have a default action"); /* key string is NULL, nothing to free */ vhost_map_free(srv, md); return NULL; } md->default_action = li_value_extract(entryValue); } else { if (NULL != g_hash_table_lookup(md->hash, entryKeyStr)) { ERROR(srv, "vhost.map: duplicate entry for '%s'", entryKeyStr->str); g_string_free(entryKeyStr, TRUE); vhost_map_free(srv, md); return NULL; } g_hash_table_insert(md->hash, entryKeyStr, li_value_extract(entryValue)); } LI_VALUE_END_FOREACH() return li_action_new_function(vhost_map, NULL, vhost_map_free, md); }
static gboolean progress_methods_parse(liServer *srv, liWorker *wrk, liPlugin *p, size_t ndx, liValue *val, liOptionValue *oval) { GArray *arr; guint methods = 0; UNUSED(wrk); UNUSED(p); UNUSED(ndx); /* default value */ if (!val) { oval->number = 1 << LI_HTTP_METHOD_POST; return TRUE; } /* Need manual type check, as resulting option type is number */ if (val->type != LI_VALUE_LIST) { ERROR(srv, "progress.methods option expects a list of strings, parameter is of type %s", li_value_type_string(val->type)); return FALSE; } arr = val->data.list; for (guint i = 0; i < arr->len; i++) { liHttpMethod method; liValue *v = g_array_index(arr, liValue*, i); if (v->type != LI_VALUE_STRING) { ERROR(srv, "progress.methods option expects a list of strings, entry #%u is of type %s", i, li_value_type_string(v->type)); return FALSE; } method = li_http_method_from_string(GSTR_LEN(v->data.string)); if (method == LI_HTTP_METHOD_UNSET) { ERROR(srv, "progress.methods: unknown method: %s", v->data.string->str); return FALSE; } methods |= 1 << method; } oval->number = (guint64) methods; return TRUE; }
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 liAction* core_throttle_ip(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { gint64 rate, burst = 0; guint masklen_ipv4 = 32, masklen_ipv6 = 56; throttle_ip_pools *pools; UNUSED(wrk); UNUSED(p); UNUSED(userdata); val = li_value_get_single_argument(val); if (LI_VALUE_NUMBER != li_value_type(val)) { ERROR(srv, "'io.throttle_ip' action expects a positiv integer as parameter, %s given", li_value_type_string(val)); return NULL; } rate = val->data.number; burst = rate; if (!sanity_check(srv, rate, burst)) return NULL; pools = ip_pools_new(p->id, rate, burst, masklen_ipv4, masklen_ipv6); return li_action_new_function(core_handle_throttle_ip, NULL, core_throttle_ip_free, pools); }
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 { ERROR(srv, "expected list, got %s", li_value_type_string(val)); return FALSE; } } static void _balancer_context_backlog_unlink(balancer *b, bcontext *bc) { if (NULL != bc->backlog_link.data) { g_queue_unlink(&b->backlog, &bc->backlog_link); li_job_ref_release(bc->ref); bc->backlog_link.data = NULL; bc->backlog_link.next = bc->backlog_link.prev = NULL; } } static void _balancer_context_backlog_push(balancer *b, gpointer *context, liVRequest *vr) { bcontext *bc = *context;