Esempio n. 1
0
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;
}
Esempio n. 2
0
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 {
Esempio n. 3
0
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 {
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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);
}
Esempio n. 10
0
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);
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
			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;