From 4f16479482f4902aecefdbcd16f3d6e3bf6b67a4 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 19 May 2022 21:18:25 +0800 Subject: HTTP: generalized uri encoding. No functional changes. --- src/nxt_http.h | 10 ++++ src/nxt_http_request.c | 83 ++++++++++++++++++++++++++++++ src/nxt_http_route.c | 136 ++++++++++++------------------------------------- 3 files changed, 126 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/nxt_http.h b/src/nxt_http.h index d299fdd4..37c27325 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -207,6 +207,13 @@ typedef struct { } nxt_http_name_value_t; +typedef enum { + NXT_HTTP_URI_ENCODING_NONE = 0, + NXT_HTTP_URI_ENCODING, + NXT_HTTP_URI_ENCODING_PLUS +} nxt_http_uri_encoding_t; + + typedef struct nxt_http_route_s nxt_http_route_t; typedef struct nxt_http_route_rule_s nxt_http_route_rule_t; typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; @@ -324,6 +331,9 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r); nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); +int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, + nxt_bool_t case_sensitive, uint8_t encoding); + nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); nxt_http_action_t *nxt_http_action_create(nxt_task_t *task, diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 04a6f7f3..0eacf627 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -1024,3 +1024,86 @@ nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, return nv; } + + +int64_t +nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive, + uint8_t encoding) +{ + u_char c, *p, *src, *start, *end, plus; + uint8_t d0, d1; + uint32_t hash; + nxt_str_t str; + nxt_uint_t i; + + str.length = name->length; + + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } + + p = str.start; + + hash = NXT_HTTP_FIELD_HASH_INIT; + + if (encoding == NXT_HTTP_URI_ENCODING_NONE) { + for (i = 0; i < name->length; i++) { + c = name->start[i]; + *p++ = c; + + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + goto end; + } + + plus = (encoding == NXT_HTTP_URI_ENCODING_PLUS) ? ' ' : '+'; + + start = name->start; + end = start + name->length; + + for (src = start; src < end; src++) { + c = *src; + + switch (c) { + case '%': + if (nxt_slow_path(end - src <= 2)) { + return -1; + } + + d0 = nxt_hex2int[src[1]]; + d1 = nxt_hex2int[src[2]]; + src += 2; + + if (nxt_slow_path((d0 | d1) >= 16)) { + return -1; + } + + c = (d0 << 4) + d1; + *p++ = c; + break; + + case '+': + c = plus; + *p++ = c; + break; + + default: + *p++ = c; + break; + } + + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + str.length = p - str.start; + +end: + + *name = str; + + return nxt_http_field_hash_end(hash) & 0xFFFF; +} diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 9200dc52..f7023997 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -40,13 +40,6 @@ typedef enum { } nxt_http_route_pattern_case_t; -typedef enum { - NXT_HTTP_ROUTE_ENCODING_NONE = 0, - NXT_HTTP_ROUTE_ENCODING_URI, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS -} nxt_http_route_encoding_t; - - typedef struct { nxt_conf_value_t *host; nxt_conf_value_t *uri; @@ -169,29 +162,29 @@ static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static int nxt_http_pattern_compare(const void *one, const void *two); static int nxt_http_addr_pattern_compare(const void *one, const void *two); static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, nxt_str_t *test, nxt_http_route_pattern_type_t type, - nxt_http_route_encoding_t encoding, + nxt_http_uri_encoding_t encoding, nxt_http_route_pattern_case_t pattern_case); static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, @@ -457,7 +450,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.scheme != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -470,7 +463,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.host != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -484,7 +477,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.uri != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_URI); + NXT_HTTP_URI_ENCODING); if (rule == NULL) { return NULL; } @@ -498,7 +491,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.method != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, NXT_HTTP_ROUTE_PATTERN_UPCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -512,7 +505,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.headers != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.headers, NXT_HTTP_ROUTE_HEADER, 0, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (table == NULL) { return NULL; } @@ -524,7 +517,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.arguments != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.arguments, NXT_HTTP_ROUTE_ARGUMENT, 1, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + NXT_HTTP_URI_ENCODING_PLUS); if (table == NULL) { return NULL; } @@ -536,7 +529,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.cookies != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.cookies, NXT_HTTP_ROUTE_COOKIE, 1, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (table == NULL) { return NULL; } @@ -548,7 +541,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.query != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + NXT_HTTP_URI_ENCODING_PLUS); if (rule == NULL) { return NULL; } @@ -690,7 +683,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, static nxt_http_route_table_t * nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n; @@ -729,7 +722,7 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_http_route_ruleset_t * nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, - nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n, next; @@ -777,12 +770,9 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_http_route_rule_t * nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { - u_char c, *p, *src, *start, *end, plus; - uint8_t d0, d1; - uint32_t hash; - nxt_uint_t i; + int64_t hash; nxt_http_route_rule_t *rule; rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, @@ -792,73 +782,14 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, return NULL; } - rule->u.name.length = name->length; - - p = nxt_mp_nget(mp, name->length); - if (nxt_slow_path(p == NULL)) { + hash = nxt_http_field_hash(mp, name, case_sensitive, encoding); + if (nxt_slow_path(hash == -1)) { return NULL; } - hash = NXT_HTTP_FIELD_HASH_INIT; - rule->u.name.start = p; - - if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) { - for (i = 0; i < name->length; i++) { - c = name->start[i]; - *p++ = c; - - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, c); - } - - goto end; - } - - plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+'; - - start = name->start; - end = start + name->length; - - for (src = start; src < end; src++) { - c = *src; - - switch (c) { - case '%': - if (nxt_slow_path(end - src <= 2)) { - return NULL; - } - - d0 = nxt_hex2int[src[1]]; - d1 = nxt_hex2int[src[2]]; - src += 2; - - if (nxt_slow_path((d0 | d1) >= 16)) { - return NULL; - } - - c = (d0 << 4) + d1; - *p++ = c; - break; - - case '+': - c = plus; - *p++ = c; - break; - - default: - *p++ = c; - break; - } - - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, c); - } - - rule->u.name.length = p - rule->u.name.start; - -end: - - rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF; + rule->u.name.hash = hash; + rule->u.name.start = name->start; + rule->u.name.length = name->length; return rule; } @@ -868,7 +799,7 @@ static nxt_http_route_rule_t * nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n; @@ -953,7 +884,7 @@ nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp, { return nxt_http_route_rule_create(task, mp, types, 0, NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); } @@ -992,7 +923,7 @@ static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, nxt_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { u_char c, *p, *end; nxt_str_t test, tmp; @@ -1188,15 +1119,15 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_int_t -nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) +nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding) { u_char *start, *end; switch (encoding) { - case NXT_HTTP_ROUTE_ENCODING_NONE: + case NXT_HTTP_URI_ENCODING_NONE: break; - case NXT_HTTP_ROUTE_ENCODING_URI: + case NXT_HTTP_URI_ENCODING: start = str->start; end = nxt_decode_uri(start, start, str->length); @@ -1207,7 +1138,7 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) str->length = end - start; break; - case NXT_HTTP_ROUTE_ENCODING_URI_PLUS: + case NXT_HTTP_URI_ENCODING_PLUS: start = str->start; end = nxt_decode_uri_plus(start, start, str->length); @@ -1228,9 +1159,8 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, - nxt_str_t *test, - nxt_http_route_pattern_type_t type, - nxt_http_route_encoding_t encoding, + nxt_str_t *test, nxt_http_route_pattern_type_t type, + nxt_http_uri_encoding_t encoding, nxt_http_route_pattern_case_t pattern_case) { u_char *start; -- cgit From 0d2d40e23192a281adaf88ce436723c8b7f5e9d3 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 2 Jun 2022 09:36:35 +0800 Subject: Summary: Var: removing all async stuff. No functional changes. --- src/nxt_http_variables.c | 26 ++++++++++---------------- src/nxt_var.c | 13 ++++--------- src/nxt_var.h | 1 - 3 files changed, 14 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index b765e177..c48f9ca3 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -7,14 +7,12 @@ #include -static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, - nxt_var_query_t *query, nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); +static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, + void *ctx); +static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, + void *ctx); +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx); +static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx); static nxt_var_decl_t nxt_http_vars[] = { @@ -44,8 +42,7 @@ nxt_http_register_variables(void) static nxt_int_t -nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; @@ -58,8 +55,7 @@ nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t -nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx) +nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; @@ -72,8 +68,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, static nxt_int_t -nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; @@ -86,8 +81,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t -nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx) { nxt_http_request_t *r; diff --git a/src/nxt_var.c b/src/nxt_var.c index 0a722d17..458ba678 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -494,17 +494,12 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, continue; /* NXT_DECLINED */ } - ret = nxt_var_index[index](task, query, value, query->ctx); + ret = nxt_var_index[index](task, value, query->ctx); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } value = NULL; - - if (ret != NXT_OK) { - if (nxt_slow_path(ret != NXT_AGAIN)) { - goto fail; - } - - query->waiting++; - } } query->spare = value; diff --git a/src/nxt_var.h b/src/nxt_var.h index 3b7d0c28..7fef0278 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -12,7 +12,6 @@ typedef struct nxt_var_query_s nxt_var_query_t; typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task, - nxt_var_query_t *query, nxt_str_t *str, void *ctx); -- cgit From df421e36b368c9595e8adedc078b69f3f0c2466b Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Tue, 7 Jun 2022 13:43:38 +0800 Subject: Router: removed unused code in nxt_router_conf_error(). No functional changes. --- src/nxt_router.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/nxt_router.c b/src/nxt_router.c index 3a32a363..48547a75 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1229,7 +1229,6 @@ static void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) { nxt_app_t *app; - nxt_queue_t new_socket_confs; nxt_socket_t s; nxt_router_t *router; nxt_queue_link_t *qlk; @@ -1252,11 +1251,6 @@ nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) nxt_free(skcf->listen); } - nxt_queue_init(&new_socket_confs); - nxt_queue_add(&new_socket_confs, &updating_sockets); - nxt_queue_add(&new_socket_confs, &pending_sockets); - nxt_queue_add(&new_socket_confs, &creating_sockets); - rtcf = tmcf->router_conf; nxt_queue_each(app, &tmcf->apps, nxt_app_t, link) { -- cgit From b4540f0960a54908a6bca9c2bd091c239ae76a53 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 7 Jun 2022 13:59:45 +0800 Subject: Removing unused tracking fields and functions. The message tracking is unused since 1d84b9e4b459 commit. This fixes the issue found by Coverity (CID 376263). --- src/nxt_port.h | 4 -- src/nxt_port_memory.c | 131 ---------------------------------------------- src/nxt_port_memory.h | 21 -------- src/nxt_port_memory_int.h | 7 --- src/nxt_port_rpc.c | 1 - src/nxt_router.c | 1 - src/nxt_unit.c | 7 --- 7 files changed, 172 deletions(-) (limited to 'src') diff --git a/src/nxt_port.h b/src/nxt_port.h index 3b66edfd..6b4d3c8f 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -174,9 +174,6 @@ typedef struct { /* More Fragments followed. */ uint8_t mf; /* 1 bit */ - - /* Message delivery tracking enabled, next chunk is tracking msg. */ - uint8_t tracking; /* 1 bit */ } nxt_port_msg_t; @@ -186,7 +183,6 @@ typedef struct { size_t share; nxt_fd_t fd[2]; nxt_port_msg_t port_msg; - uint32_t tracking_msg[2]; uint8_t close_fd; /* 1 bit */ uint8_t allocated; /* 1 bit */ } nxt_port_send_msg_t; diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c index e799f860..0a4a6c53 100644 --- a/src/nxt_port_memory.c +++ b/src/nxt_port_memory.c @@ -539,137 +539,6 @@ nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id) } -nxt_int_t -nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps, - nxt_port_mmap_tracking_t *tracking, uint32_t stream) -{ - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - nxt_debug(task, "request tracking for stream #%uD", stream); - - mmap_handler = nxt_port_mmap_get(task, mmaps, &c, 1, 1); - if (nxt_slow_path(mmap_handler == NULL)) { - return NXT_ERROR; - } - - nxt_port_mmap_handler_use(mmap_handler, 1); - - hdr = mmap_handler->hdr; - - tracking->mmap_handler = mmap_handler; - tracking->tracking = hdr->tracking + c; - - *tracking->tracking = stream; - - nxt_debug(task, "outgoing tracking allocation: %PI->%PI,%d,%d", - hdr->src_pid, hdr->dst_pid, hdr->id, c); - - return NXT_OK; -} - - -nxt_bool_t -nxt_port_mmap_tracking_cancel(nxt_task_t *task, - nxt_port_mmap_tracking_t *tracking, uint32_t stream) -{ - nxt_bool_t res; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - - mmap_handler = tracking->mmap_handler; - - if (nxt_slow_path(mmap_handler == NULL)) { - return 0; - } - - hdr = mmap_handler->hdr; - - res = nxt_atomic_cmp_set(tracking->tracking, stream, 0); - - nxt_debug(task, "%s tracking for stream #%uD", - (res ? "cancelled" : "failed to cancel"), stream); - - if (!res) { - c = tracking->tracking - hdr->tracking; - nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c); - } - - nxt_port_mmap_handler_use(mmap_handler, -1); - - return res; -} - - -nxt_int_t -nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t) -{ - nxt_port_mmap_handler_t *mmap_handler; - - mmap_handler = t->mmap_handler; - -#if (NXT_DEBUG) - { - nxt_atomic_t *tracking; - - tracking = mmap_handler->hdr->tracking; - - nxt_assert(t->tracking >= tracking); - nxt_assert(t->tracking < tracking + PORT_MMAP_CHUNK_COUNT); - } -#endif - - buf[0] = mmap_handler->hdr->id; - buf[1] = t->tracking - mmap_handler->hdr->tracking; - - return NXT_OK; -} - -nxt_bool_t -nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_buf_t *b; - nxt_bool_t res; - nxt_chunk_id_t c; - nxt_port_mmap_header_t *hdr; - nxt_port_mmap_handler_t *mmap_handler; - nxt_port_mmap_tracking_msg_t *tracking_msg; - - b = msg->buf; - - if (nxt_buf_used_size(b) < (int) sizeof(nxt_port_mmap_tracking_msg_t)) { - nxt_debug(task, "too small message %O", nxt_buf_used_size(b)); - return 0; - } - - tracking_msg = (nxt_port_mmap_tracking_msg_t *) b->mem.pos; - - b->mem.pos += sizeof(nxt_port_mmap_tracking_msg_t); - mmap_handler = nxt_port_get_port_incoming_mmap(task, msg->port_msg.pid, - tracking_msg->mmap_id); - - if (nxt_slow_path(mmap_handler == NULL)) { - return 0; - } - - hdr = mmap_handler->hdr; - - c = tracking_msg->tracking_id; - res = nxt_atomic_cmp_set(hdr->tracking + c, msg->port_msg.stream, 0); - - nxt_debug(task, "tracking for stream #%uD %s", msg->port_msg.stream, - (res ? "received" : "already cancelled")); - - if (!res) { - nxt_port_mmap_set_chunk_free(hdr->free_tracking_map, c); - } - - return res; -} - - nxt_buf_t * nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_mmaps_t *mmaps, size_t size) { diff --git a/src/nxt_port_memory.h b/src/nxt_port_memory.h index a2cdf5dd..f1e70964 100644 --- a/src/nxt_port_memory.h +++ b/src/nxt_port_memory.h @@ -15,27 +15,6 @@ typedef struct nxt_port_mmap_handler_s nxt_port_mmap_handler_t; void nxt_port_mmaps_destroy(nxt_port_mmaps_t *port_mmaps, nxt_bool_t free_elts); -typedef struct nxt_port_mmap_tracking_s nxt_port_mmap_tracking_t; - -struct nxt_port_mmap_tracking_s { - void *mmap_handler; - nxt_atomic_t *tracking; -}; - -nxt_int_t -nxt_port_mmap_get_tracking(nxt_task_t *task, nxt_port_mmaps_t *mmaps, - nxt_port_mmap_tracking_t *tracking, uint32_t stream); - -nxt_bool_t -nxt_port_mmap_tracking_cancel(nxt_task_t *task, - nxt_port_mmap_tracking_t *tracking, uint32_t stream); - -nxt_int_t -nxt_port_mmap_tracking_write(uint32_t *buf, nxt_port_mmap_tracking_t *t); - -nxt_bool_t -nxt_port_mmap_tracking_read(nxt_task_t *task, nxt_port_recv_msg_t *msg); - /* * Allocates nxt_but_t structure from task's thread engine mem_pool, assigns * this buf 'mem' pointers to first available shared mem bucket(s). 'size' diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h index d2524ee4..c84615d5 100644 --- a/src/nxt_port_memory_int.h +++ b/src/nxt_port_memory_int.h @@ -84,13 +84,6 @@ struct nxt_port_mmap_msg_s { }; -typedef struct nxt_port_mmap_tracking_msg_s nxt_port_mmap_tracking_msg_t; - -struct nxt_port_mmap_tracking_msg_s { - uint32_t mmap_id; /* Mmap index in nxt_process_t.outgoing. */ - nxt_chunk_id_t tracking_id; /* Tracking index. */ -}; - nxt_inline nxt_bool_t nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c); diff --git a/src/nxt_port_rpc.c b/src/nxt_port_rpc.c index 0cac5cbb..28590933 100644 --- a/src/nxt_port_rpc.c +++ b/src/nxt_port_rpc.c @@ -512,7 +512,6 @@ nxt_port_rpc_close(nxt_task_t *task, nxt_port_t *port) msg.port_msg.mmap = 0; msg.port_msg.nf = 0; msg.port_msg.mf = 0; - msg.port_msg.tracking = 0; msg.size = 0; msg.cancelled = 0; msg.u.data = NULL; diff --git a/src/nxt_router.c b/src/nxt_router.c index 48547a75..6b69b2ce 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -5384,7 +5384,6 @@ nxt_router_app_prepare_request(nxt_task_t *task, msg.pm.mmap = 1; msg.pm.nf = 0; msg.pm.mf = 0; - msg.pm.tracking = 0; nxt_port_mmap_handler_t *mmap_handler = buf->parent; nxt_port_mmap_header_t *hdr = mmap_handler->hdr; diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 32bb07ab..f183ac6e 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -942,7 +942,6 @@ nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream, int queue_fd) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; nxt_socket_msg_oob_init(&oob, fds); @@ -2644,7 +2643,6 @@ nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req, m.msg.mmap = hdr != NULL && m.mmap_msg.size > 0; m.msg.nf = 0; m.msg.mf = 0; - m.msg.tracking = 0; rc = NXT_UNIT_ERROR; @@ -3296,7 +3294,6 @@ skip_response_send: msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; (void) nxt_unit_port_send(req->ctx, req->response_port, &msg, sizeof(msg), NULL); @@ -3619,7 +3616,6 @@ nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); if (nxt_slow_path(res != sizeof(msg))) { @@ -3905,7 +3901,6 @@ nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port, int fd) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; nxt_socket_msg_oob_init(&oob, fds); @@ -4390,7 +4385,6 @@ nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid) msg.mmap = 0; msg.nf = 0; msg.mf = 0; - msg.tracking = 0; res = nxt_unit_port_send(ctx, lib->router_port, &msg, sizeof(msg), NULL); if (nxt_slow_path(res != sizeof(msg))) { @@ -5356,7 +5350,6 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst, m.msg.mmap = 0; m.msg.nf = 0; m.msg.mf = 0; - m.msg.tracking = 0; m.new_port.id = port->id.id; m.new_port.pid = port->id.pid; -- cgit From 6a8081d71e805b12d0f7fd32ce72d60babadfc85 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Wed, 15 Jun 2022 14:27:50 +0800 Subject: Var: relocated nxt_var_is_const() and nxt_var_raw(). No functional changes. --- src/nxt_var.c | 30 +++++++++++++++--------------- src/nxt_var.h | 6 +++--- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nxt_var.c b/src/nxt_var.c index 458ba678..a7cbb898 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -91,21 +91,6 @@ static uint32_t nxt_var_count; static nxt_var_handler_t *nxt_var_index; -void -nxt_var_raw(nxt_var_t *var, nxt_str_t *str) -{ - str->length = var->length; - str->start = nxt_var_raw_start(var); -} - - -nxt_bool_t -nxt_var_is_const(nxt_var_t *var) -{ - return (var->vars == 0); -} - - static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { @@ -420,6 +405,21 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, } +inline void +nxt_var_raw(nxt_var_t *var, nxt_str_t *str) +{ + str->length = var->length; + str->start = nxt_var_raw_start(var); +} + + +inline nxt_bool_t +nxt_var_is_const(nxt_var_t *var) +{ + return (var->vars == 0); +} + + nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) { diff --git a/src/nxt_var.h b/src/nxt_var.h index 7fef0278..1322d507 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -29,14 +29,14 @@ nxt_is_var(nxt_str_t *str) } -void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); -nxt_bool_t nxt_var_is_const(nxt_var_t *var); - nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); nxt_int_t nxt_var_index_init(void); nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz); nxt_int_t nxt_var_test(nxt_str_t *str, u_char *error); +void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); +nxt_bool_t nxt_var_is_const(nxt_var_t *var); + nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp); void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, -- cgit From fd38e69c3db9cda55fb24401c9eedbe18a05e962 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 20 Jun 2022 13:11:34 +0800 Subject: Router: refactored nxt_router_conf_create(). No functional changes. --- src/nxt_router.c | 60 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/nxt_router.c b/src/nxt_router.c index 6b69b2ce..00558d94 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1488,11 +1488,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_tls_init_t *tls_init; nxt_conf_value_t *certificate; #endif - nxt_conf_value_t *conf, *http, *value, *websocket; + nxt_conf_value_t *root, *conf, *http, *value, *websocket; nxt_conf_value_t *applications, *application; nxt_conf_value_t *listeners, *listener; - nxt_conf_value_t *routes_conf, *static_conf, *client_ip_conf; nxt_socket_conf_t *skcf; + nxt_router_conf_t *rtcf; nxt_http_routes_t *routes; nxt_event_engine_t *engine; nxt_app_lang_module_t *lang; @@ -1516,35 +1516,36 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, static nxt_str_t websocket_path = nxt_string("/settings/http/websocket"); static nxt_str_t client_ip_path = nxt_string("/client_ip"); - conf = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); - if (conf == NULL) { + root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); + if (root == NULL) { nxt_alert(task, "configuration parsing error"); return NXT_ERROR; } - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; - ret = nxt_conf_map_object(mp, conf, nxt_router_conf, - nxt_nitems(nxt_router_conf), tmcf->router_conf); + ret = nxt_conf_map_object(mp, root, nxt_router_conf, + nxt_nitems(nxt_router_conf), rtcf); if (ret != NXT_OK) { nxt_alert(task, "root map error"); return NXT_ERROR; } - if (tmcf->router_conf->threads == 0) { - tmcf->router_conf->threads = nxt_ncpu; + if (rtcf->threads == 0) { + rtcf->threads = nxt_ncpu; } - static_conf = nxt_conf_get_path(conf, &static_path); + conf = nxt_conf_get_path(root, &static_path); - ret = nxt_router_conf_process_static(task, tmcf->router_conf, static_conf); + ret = nxt_router_conf_process_static(task, rtcf, conf); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - router = tmcf->router_conf->router; + router = rtcf->router; - applications = nxt_conf_get_path(conf, &applications_path); + applications = nxt_conf_get_path(root, &applications_path); if (applications != NULL) { next = 0; @@ -1593,7 +1594,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_queue_remove(&prev->link); nxt_queue_insert_tail(&tmcf->previous, &prev->link); - ret = nxt_router_apps_hash_add(tmcf->router_conf, prev); + ret = nxt_router_apps_hash_add(rtcf, prev); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } @@ -1728,7 +1729,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_queue_insert_tail(&tmcf->apps, &app->link); - ret = nxt_router_apps_hash_add(tmcf->router_conf, app); + ret = nxt_router_apps_hash_add(rtcf, app); if (nxt_slow_path(ret != NXT_OK)) { goto app_fail; } @@ -1779,21 +1780,21 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } } - routes_conf = nxt_conf_get_path(conf, &routes_path); - if (nxt_fast_path(routes_conf != NULL)) { - routes = nxt_http_routes_create(task, tmcf, routes_conf); + conf = nxt_conf_get_path(root, &routes_path); + if (nxt_fast_path(conf != NULL)) { + routes = nxt_http_routes_create(task, tmcf, conf); if (nxt_slow_path(routes == NULL)) { return NXT_ERROR; } - tmcf->router_conf->routes = routes; + rtcf->routes = routes; } - ret = nxt_upstreams_create(task, tmcf, conf); + ret = nxt_upstreams_create(task, tmcf, root); if (nxt_slow_path(ret != NXT_OK)) { return ret; } - http = nxt_conf_get_path(conf, &http_path); + http = nxt_conf_get_path(root, &http_path); #if 0 if (http == NULL) { nxt_alert(task, "no \"http\" block"); @@ -1801,9 +1802,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } #endif - websocket = nxt_conf_get_path(conf, &websocket_path); + websocket = nxt_conf_get_path(root, &websocket_path); - listeners = nxt_conf_get_path(conf, &listeners_path); + listeners = nxt_conf_get_path(root, &listeners_path); if (listeners != NULL) { next = 0; @@ -1883,9 +1884,9 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, t->length = nxt_strlen(t->start); } - client_ip_conf = nxt_conf_get_path(listener, &client_ip_path); + conf = nxt_conf_get_path(listener, &client_ip_path); ret = nxt_router_conf_process_client_ip(task, tmcf, skcf, - client_ip_conf); + conf); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -1935,7 +1936,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif skcf->listen->handler = nxt_http_conn_init; - skcf->router_conf = tmcf->router_conf; + skcf->router_conf = rtcf; skcf->router_conf->count++; if (lscf.pass.length != 0) { @@ -1943,8 +1944,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, /* COMPATIBILITY: listener application. */ } else if (lscf.application.length > 0) { - skcf->action = nxt_http_pass_application(task, - tmcf->router_conf, + skcf->action = nxt_http_pass_application(task, rtcf, &lscf.application); } @@ -1959,7 +1959,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, goto fail; } - value = nxt_conf_get_path(conf, &access_log_path); + value = nxt_conf_get_path(root, &access_log_path); if (value != NULL) { nxt_conf_get_string(value, &path); @@ -1988,7 +1988,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_memcpy(access_log->path.start, path.start, path.length); } - tmcf->router_conf->access_log = access_log; + rtcf->access_log = access_log; } nxt_queue_add(&deleting_sockets, &router->sockets); -- cgit From 14dfa439eed1983693d7d128cc51c5e738a487d7 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 20 Jun 2022 13:16:25 +0800 Subject: Router: introduced nxt_http_forward_t. This makes the replacement of forwarded request header like client_ip and protocol more generic. It's a prerequirement for protocol replacement. No functional changes. --- src/nxt_http.h | 9 +++++++-- src/nxt_http_request.c | 30 ++++++++++++++++-------------- src/nxt_router.c | 39 +++++++++++++++++---------------------- src/nxt_router.h | 4 ++-- 4 files changed, 42 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/nxt_http.h b/src/nxt_http.h index 37c27325..665ccdbf 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -273,10 +273,15 @@ typedef struct { } nxt_http_proto_table_t; -struct nxt_http_client_ip_s { - nxt_http_route_addr_rule_t *source; +typedef struct { nxt_str_t *header; uint32_t header_hash; +} nxt_http_forward_header_t; + + +struct nxt_http_forward_s { + nxt_http_forward_header_t client_ip; + nxt_http_route_addr_rule_t *source; uint8_t recursive; /* 1 bit */ }; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 0eacf627..3f926796 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -314,25 +314,27 @@ nxt_http_request_start(nxt_task_t *task, void *obj, void *data) static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) { - u_char *start, *p; - nxt_int_t ret, i, len; - nxt_str_t *header; - nxt_array_t *fields_arr; /* of nxt_http_field_t * */ - nxt_sockaddr_t *sa, *prev_sa; - nxt_http_field_t *f, **fields; - nxt_http_client_ip_t *client_ip; - - client_ip = r->conf->socket_conf->client_ip; - - if (client_ip == NULL) { + u_char *start, *p; + nxt_int_t ret, i, len; + nxt_str_t *header; + nxt_array_t *fields_arr; /* of nxt_http_field_t * */ + nxt_sockaddr_t *sa, *prev_sa; + nxt_http_field_t *f, **fields; + nxt_http_forward_t *forward; + nxt_http_forward_header_t *client_ip; + + forward = r->conf->socket_conf->client_ip; + + if (forward == NULL) { return NXT_OK; } - ret = nxt_http_route_addr_rule(r, client_ip->source, r->remote); + ret = nxt_http_route_addr_rule(r, forward->source, r->remote); if (ret <= 0) { return NXT_OK; } + client_ip = &forward->client_ip; header = client_ip->header; fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *)); @@ -388,13 +390,13 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) return NXT_OK; } - if (!client_ip->recursive) { + if (!forward->recursive) { r->remote = sa; return NXT_OK; } - ret = nxt_http_route_addr_rule(r, client_ip->source, sa); + ret = nxt_http_route_addr_rule(r, forward->source, sa); if (ret <= 0 || (i == 0 && p == start)) { r->remote = sa; diff --git a/src/nxt_router.c b/src/nxt_router.c index 00558d94..8487d239 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -109,8 +109,7 @@ static nxt_int_t nxt_router_conf_create(nxt_task_t *task, static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf, - nxt_conf_value_t *conf); + nxt_mp_t *mp, nxt_socket_conf_t *skcf, nxt_conf_value_t *conf); static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); @@ -1885,10 +1884,12 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, } conf = nxt_conf_get_path(listener, &client_ip_path); - ret = nxt_router_conf_process_client_ip(task, tmcf, skcf, - conf); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; + + if (conf != NULL) { + ret = nxt_router_conf_process_client_ip(task, mp, skcf, conf); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } } #if (NXT_TLS) @@ -2124,30 +2125,22 @@ nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, static nxt_int_t -nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, +nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_conf_t *skcf, nxt_conf_value_t *conf) { char c; size_t i; - nxt_mp_t *mp; uint32_t hash; nxt_str_t header; nxt_conf_value_t *source_conf, *header_conf, *recursive_conf; - nxt_http_client_ip_t *client_ip; + nxt_http_forward_t *forward; + nxt_http_forward_header_t *client_ip; nxt_http_route_addr_rule_t *source; static nxt_str_t header_path = nxt_string("/header"); static nxt_str_t source_path = nxt_string("/source"); static nxt_str_t recursive_path = nxt_string("/recursive"); - if (conf == NULL) { - skcf->client_ip = NULL; - - return NXT_OK; - } - - mp = tmcf->router_conf->mem_pool; - source_conf = nxt_conf_get_path(conf, &source_path); header_conf = nxt_conf_get_path(conf, &header_path); recursive_conf = nxt_conf_get_path(conf, &recursive_path); @@ -2156,8 +2149,8 @@ nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf return NXT_ERROR; } - client_ip = nxt_mp_zget(mp, sizeof(nxt_http_client_ip_t)); - if (nxt_slow_path(client_ip == NULL)) { + forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t)); + if (nxt_slow_path(forward == NULL)) { return NXT_ERROR; } @@ -2166,12 +2159,14 @@ nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf return NXT_ERROR; } - client_ip->source = source; + forward->source = source; + + client_ip = &forward->client_ip; nxt_conf_get_string(header_conf, &header); if (recursive_conf != NULL) { - client_ip->recursive = nxt_conf_get_boolean(recursive_conf); + forward->recursive = nxt_conf_get_boolean(recursive_conf); } client_ip->header = nxt_str_dup(mp, NULL, &header); @@ -2190,7 +2185,7 @@ nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_router_temp_conf_t *tmcf client_ip->header_hash = hash; - skcf->client_ip = client_ip; + skcf->client_ip = forward; return NXT_OK; } diff --git a/src/nxt_router.h b/src/nxt_router.h index 7e337d27..b97d5c20 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -18,7 +18,7 @@ typedef struct nxt_http_request_s nxt_http_request_t; typedef struct nxt_http_action_s nxt_http_action_t; typedef struct nxt_http_routes_s nxt_http_routes_t; -typedef struct nxt_http_client_ip_s nxt_http_client_ip_t; +typedef struct nxt_http_forward_s nxt_http_forward_t; typedef struct nxt_upstream_s nxt_upstream_t; typedef struct nxt_upstreams_s nxt_upstreams_t; typedef struct nxt_router_access_log_s nxt_router_access_log_t; @@ -197,7 +197,7 @@ typedef struct { uint8_t discard_unsafe_fields; /* 1 bit */ - nxt_http_client_ip_t *client_ip; + nxt_http_forward_t *client_ip; #if (NXT_TLS) nxt_tls_conf_t *tls; -- cgit From 9d2672a701e3dcaee45bef9251ab55620d42fa42 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 20 Jun 2022 13:22:13 +0800 Subject: Router: forwared header replacement. --- src/nxt_conf_validation.c | 50 +++++++++++++++ src/nxt_h1proto.c | 2 +- src/nxt_http.h | 3 +- src/nxt_http_request.c | 151 ++++++++++++++++++++++++++++++++++------------ src/nxt_http_route.c | 5 +- src/nxt_router.c | 107 +++++++++++++++++++++++--------- src/nxt_router.h | 1 + 7 files changed, 244 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index ee7ebe44..a5958788 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -166,6 +166,8 @@ static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt, @@ -220,6 +222,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[]; +static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[]; #if (NXT_TLS) static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[]; @@ -365,6 +368,10 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { .name = nxt_string("application"), .type = NXT_CONF_VLDT_STRING, .validator = nxt_conf_vldt_app_name, + }, { + .name = nxt_string("forwarded"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_forwarded, }, { .name = nxt_string("client_ip"), .type = NXT_CONF_VLDT_OBJECT, @@ -385,6 +392,27 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = { + { + .name = nxt_string("client_ip"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("protocol"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("source"), + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, + .validator = nxt_conf_vldt_match_addrs, + .flags = NXT_CONF_VLDT_REQUIRED + }, { + .name = nxt_string("recursive"), + .type = NXT_CONF_VLDT_BOOLEAN, + }, + + NXT_CONF_VLDT_END +}; + + static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = { { .name = nxt_string("source"), @@ -2317,6 +2345,28 @@ error: } +static nxt_int_t +nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, + void *data) +{ + nxt_conf_value_t *client_ip, *protocol; + + static nxt_str_t client_ip_str = nxt_string("client_ip"); + static nxt_str_t protocol_str = nxt_string("protocol"); + + client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL); + protocol = nxt_conf_get_object_member(value, &protocol_str, NULL); + + if (client_ip == NULL && protocol == NULL) { + return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have " + "either \"client_ip\" or \"protocol\" " + "option set."); + } + + return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members); +} + + static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index d3340774..1473aaa0 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -490,7 +490,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) r->remote = c->remote; #if (NXT_TLS) - r->tls = c->u.tls; + r->tls = (c->u.tls != NULL); #endif r->task = c->task; diff --git a/src/nxt_http.h b/src/nxt_http.h index 665ccdbf..8fa0caad 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -162,7 +162,6 @@ struct nxt_http_request_s { nxt_sockaddr_t *remote; nxt_sockaddr_t *local; - void *tls; nxt_task_t task; nxt_timer_t timer; @@ -190,6 +189,7 @@ struct nxt_http_request_s { uint8_t pass_count; /* 8 bits */ uint8_t app_target; nxt_http_protocol_t protocol:8; /* 2 bits */ + uint8_t tls; /* 1 bit */ uint8_t logged; /* 1 bit */ uint8_t header_sent; /* 1 bit */ uint8_t inconsistent; /* 1 bit */ @@ -281,6 +281,7 @@ typedef struct { struct nxt_http_forward_s { nxt_http_forward_header_t client_ip; + nxt_http_forward_header_t protocol; nxt_http_route_addr_rule_t *source; uint8_t recursive; /* 1 bit */ }; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 3f926796..7fb86cc4 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -10,10 +10,14 @@ static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp); static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data); -static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task, - nxt_http_request_t *r); +static nxt_int_t nxt_http_request_forward(nxt_task_t *task, + nxt_http_request_t *r, nxt_http_forward_t *forward); +static void nxt_http_request_forward_client_ip(nxt_http_request_t *r, + nxt_http_forward_t *forward, nxt_array_t *fields); static nxt_sockaddr_t *nxt_http_request_client_ip_sockaddr( nxt_http_request_t *r, u_char *start, size_t len); +static void nxt_http_request_forward_protocol(nxt_http_request_t *r, + nxt_http_field_t *field); static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data); static void nxt_http_request_proto_info(nxt_task_t *task, nxt_http_request_t *r); @@ -296,38 +300,46 @@ static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; + nxt_socket_conf_t *skcf; nxt_http_request_t *r; r = obj; r->state = &nxt_http_request_body_state; - ret = nxt_http_request_client_ip(task, r); - if (nxt_slow_path(ret != NXT_OK)) { - nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); + skcf = r->conf->socket_conf; + + if (skcf->forwarded != NULL) { + ret = nxt_http_request_forward(task, r, skcf->forwarded); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + } + + if (skcf->client_ip != NULL) { + ret = nxt_http_request_forward(task, r, skcf->client_ip); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } } nxt_http_request_read_body(task, r); + + return; + +fail: + nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); } static nxt_int_t -nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) +nxt_http_request_forward(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_forward_t *forward) { - u_char *start, *p; - nxt_int_t ret, i, len; - nxt_str_t *header; - nxt_array_t *fields_arr; /* of nxt_http_field_t * */ - nxt_sockaddr_t *sa, *prev_sa; - nxt_http_field_t *f, **fields; - nxt_http_forward_t *forward; - nxt_http_forward_header_t *client_ip; - - forward = r->conf->socket_conf->client_ip; - - if (forward == NULL) { - return NXT_OK; - } + nxt_int_t ret; + nxt_array_t *client_ip_fields; + nxt_http_field_t *f, **fields, *protocol_field; + nxt_http_forward_header_t *client_ip, *protocol; ret = nxt_http_route_addr_rule(r, forward->source, r->remote); if (ret <= 0) { @@ -335,37 +347,78 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) } client_ip = &forward->client_ip; - header = client_ip->header; + protocol = &forward->protocol; - fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *)); - if (nxt_slow_path(fields_arr == NULL)) { - return NXT_ERROR; + if (client_ip->header != NULL) { + client_ip_fields = nxt_array_create(r->mem_pool, 1, + sizeof(nxt_http_field_t *)); + if (nxt_slow_path(client_ip_fields == NULL)) { + return NXT_ERROR; + } + + } else { + client_ip_fields = NULL; } + protocol_field = NULL; + nxt_list_each(f, r->fields) { - if (f->hash == client_ip->header_hash - && f->name_length == client_ip->header->length + if (client_ip_fields != NULL + && f->hash == client_ip->header_hash && f->value_length > 0 - && nxt_memcasecmp(f->name, header->start, header->length) == 0) + && f->name_length == client_ip->header->length + && nxt_memcasecmp(f->name, client_ip->header->start, + client_ip->header->length) == 0) { - fields = nxt_array_add(fields_arr); + fields = nxt_array_add(client_ip_fields); if (nxt_slow_path(fields == NULL)) { return NXT_ERROR; } *fields = f; } + + if (protocol->header != NULL + && protocol_field == NULL + && f->hash == protocol->header_hash + && f->value_length > 0 + && f->name_length == protocol->header->length + && nxt_memcasecmp(f->name, protocol->header->start, + protocol->header->length) == 0) + { + protocol_field = f; + } } nxt_list_loop; + if (client_ip_fields != NULL) { + nxt_http_request_forward_client_ip(r, forward, client_ip_fields); + } + + if (protocol_field != NULL) { + nxt_http_request_forward_protocol(r, protocol_field); + } + + return NXT_OK; +} + + +static void +nxt_http_request_forward_client_ip(nxt_http_request_t *r, + nxt_http_forward_t *forward, nxt_array_t *fields) +{ + u_char *start, *p; + nxt_int_t ret, i, len; + nxt_sockaddr_t *sa, *prev_sa; + nxt_http_field_t **f; + prev_sa = r->remote; - fields = (nxt_http_field_t **) fields_arr->elts; + f = (nxt_http_field_t **) fields->elts; - i = fields_arr->nelts; + i = fields->nelts; while (i-- > 0) { - f = fields[i]; - start = f->value; - len = f->value_length; + start = f[i]->value; + len = f[i]->value_length; do { for (p = start + len - 1; p > start; p--, len--) { @@ -387,20 +440,18 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) r->remote = prev_sa; } - return NXT_OK; + return; } if (!forward->recursive) { r->remote = sa; - - return NXT_OK; + return; } ret = nxt_http_route_addr_rule(r, forward->source, sa); if (ret <= 0 || (i == 0 && p == start)) { r->remote = sa; - - return NXT_OK; + return; } prev_sa = sa; @@ -408,8 +459,6 @@ nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r) } while (len > 0); } - - return NXT_OK; } @@ -453,6 +502,28 @@ nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start, } +static void +nxt_http_request_forward_protocol(nxt_http_request_t *r, + nxt_http_field_t *field) +{ + if (field->value_length == 4) { + if (nxt_memcasecmp(field->value, "http", 4) == 0) { + r->tls = 0; + } + + } else if (field->value_length == 5) { + if (nxt_memcasecmp(field->value, "https", 5) == 0) { + r->tls = 1; + } + + } else if (field->value_length == 2) { + if (nxt_memcasecmp(field->value, "on", 2) == 0) { + r->tls = 1; + } + } +} + + static const nxt_http_request_state_t nxt_http_request_body_state nxt_aligned(64) = { diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index f7023997..5a4f349e 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1949,14 +1949,13 @@ nxt_http_route_test_argument(nxt_http_request_t *r, static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { - nxt_bool_t tls, https; + nxt_bool_t https; nxt_http_route_pattern_slice_t *pattern_slice; pattern_slice = rule->pattern[0].u.pattern_slices->elts; https = (pattern_slice->length == nxt_length("https")); - tls = (r->tls != NULL); - return (tls == https); + return (r->tls == https); } diff --git a/src/nxt_router.c b/src/nxt_router.c index 8487d239..a3cc0a8d 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -108,8 +108,10 @@ static nxt_int_t nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end); static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *conf); -static nxt_int_t nxt_router_conf_process_client_ip(nxt_task_t *task, - nxt_mp_t *mp, nxt_socket_conf_t *skcf, nxt_conf_value_t *conf); +static nxt_http_forward_t *nxt_router_conf_forward(nxt_task_t *task, + nxt_mp_t *mp, nxt_conf_value_t *conf); +static nxt_int_t nxt_router_conf_forward_header(nxt_mp_t *mp, + nxt_conf_value_t *conf, nxt_http_forward_header_t *fh); static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name); static nxt_int_t nxt_router_apps_hash_test(nxt_lvlhsh_query_t *lhq, void *data); @@ -1513,6 +1515,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif static nxt_str_t static_path = nxt_string("/settings/http/static"); static nxt_str_t websocket_path = nxt_string("/settings/http/websocket"); + static nxt_str_t forwarded_path = nxt_string("/forwarded"); static nxt_str_t client_ip_path = nxt_string("/client_ip"); root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); @@ -1883,11 +1886,20 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, t->length = nxt_strlen(t->start); } + conf = nxt_conf_get_path(listener, &forwarded_path); + + if (conf != NULL) { + skcf->forwarded = nxt_router_conf_forward(task, mp, conf); + if (nxt_slow_path(skcf->forwarded == NULL)) { + return NXT_ERROR; + } + } + conf = nxt_conf_get_path(listener, &client_ip_path); if (conf != NULL) { - ret = nxt_router_conf_process_client_ip(task, mp, skcf, conf); - if (nxt_slow_path(ret != NXT_OK)) { + skcf->client_ip = nxt_router_conf_forward(task, mp, conf); + if (nxt_slow_path(skcf->client_ip == NULL)) { return NXT_ERROR; } } @@ -2124,68 +2136,103 @@ nxt_router_conf_process_static(nxt_task_t *task, nxt_router_conf_t *rtcf, } -static nxt_int_t -nxt_router_conf_process_client_ip(nxt_task_t *task, nxt_mp_t *mp, - nxt_socket_conf_t *skcf, nxt_conf_value_t *conf) +static nxt_http_forward_t * +nxt_router_conf_forward(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *conf) { - char c; - size_t i; - uint32_t hash; - nxt_str_t header; - nxt_conf_value_t *source_conf, *header_conf, *recursive_conf; + nxt_int_t ret; + nxt_conf_value_t *header_conf, *client_ip_conf, *protocol_conf; + nxt_conf_value_t *source_conf, *recursive_conf; nxt_http_forward_t *forward; - nxt_http_forward_header_t *client_ip; nxt_http_route_addr_rule_t *source; static nxt_str_t header_path = nxt_string("/header"); + static nxt_str_t client_ip_path = nxt_string("/client_ip"); + static nxt_str_t protocol_path = nxt_string("/protocol"); static nxt_str_t source_path = nxt_string("/source"); static nxt_str_t recursive_path = nxt_string("/recursive"); - source_conf = nxt_conf_get_path(conf, &source_path); header_conf = nxt_conf_get_path(conf, &header_path); + + if (header_conf != NULL) { + client_ip_conf = nxt_conf_get_path(conf, &header_path); + protocol_conf = NULL; + + } else { + client_ip_conf = nxt_conf_get_path(conf, &client_ip_path); + protocol_conf = nxt_conf_get_path(conf, &protocol_path); + } + + source_conf = nxt_conf_get_path(conf, &source_path); recursive_conf = nxt_conf_get_path(conf, &recursive_path); - if (source_conf == NULL || header_conf == NULL) { - return NXT_ERROR; + if (source_conf == NULL + || (protocol_conf == NULL && client_ip_conf == NULL)) + { + return NULL; } forward = nxt_mp_zget(mp, sizeof(nxt_http_forward_t)); if (nxt_slow_path(forward == NULL)) { - return NXT_ERROR; + return NULL; } source = nxt_http_route_addr_rule_create(task, mp, source_conf); if (nxt_slow_path(source == NULL)) { - return NXT_ERROR; + return NULL; } forward->source = source; - client_ip = &forward->client_ip; - - nxt_conf_get_string(header_conf, &header); - if (recursive_conf != NULL) { forward->recursive = nxt_conf_get_boolean(recursive_conf); } - client_ip->header = nxt_str_dup(mp, NULL, &header); - if (nxt_slow_path(client_ip->header == NULL)) { + if (client_ip_conf != NULL) { + ret = nxt_router_conf_forward_header(mp, client_ip_conf, + &forward->client_ip); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + } + + if (protocol_conf != NULL) { + ret = nxt_router_conf_forward_header(mp, protocol_conf, + &forward->protocol); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + } + + return forward; +} + + +static nxt_int_t +nxt_router_conf_forward_header(nxt_mp_t *mp, nxt_conf_value_t *conf, + nxt_http_forward_header_t *fh) +{ + char c; + size_t i; + uint32_t hash; + nxt_str_t header; + + nxt_conf_get_string(conf, &header); + + fh->header = nxt_str_dup(mp, NULL, &header); + if (nxt_slow_path(fh->header == NULL)) { return NXT_ERROR; } hash = NXT_HTTP_FIELD_HASH_INIT; - for (i = 0; i < client_ip->header->length; i++) { - c = client_ip->header->start[i]; + for (i = 0; i < fh->header->length; i++) { + c = fh->header->start[i]; hash = nxt_http_field_hash_char(hash, nxt_lowcase(c)); } hash = nxt_http_field_hash_end(hash) & 0xFFFF; - client_ip->header_hash = hash; - - skcf->client_ip = forward; + fh->header_hash = hash; return NXT_OK; } @@ -5547,7 +5594,7 @@ nxt_router_prepare_msg(nxt_task_t *task, nxt_http_request_t *r, p = nxt_cpymem(p, nxt_sockaddr_address(r->local), r->local->address_length); *p++ = '\0'; - req->tls = (r->tls != NULL); + req->tls = r->tls; req->websocket_handshake = r->websocket_handshake; req->server_name_length = r->server_name.length; diff --git a/src/nxt_router.h b/src/nxt_router.h index b97d5c20..37008f9d 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -197,6 +197,7 @@ typedef struct { uint8_t discard_unsafe_fields; /* 1 bit */ + nxt_http_forward_t *forwarded; nxt_http_forward_t *client_ip; #if (NXT_TLS) -- cgit From c3e40ae932f0cf9ae33166479049d2d3c9fa1615 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 6 Jun 2022 14:18:01 +0200 Subject: Static: Fixed finding the file extension. The code for finding the extension made a few assumptions that are no longer true. It didn't account for pathnames that didn't contain '/', including the empty string, or the NULL string. That code was used with "share", which always had a '/', but now it's also used with "index", which should not have a '/' in it. This fix works by limiting the search to the beginning of the string, so that if no '/' is found in it, it doesn't continue searching before the beginning of the string. This also happens to work for NULL. It is technically Undefined Behavior, as we rely on `NULL + 0 == NULL` and `NULL - NULL == 0`. But that is the only sane behavior for an implementation, and all existing POSIX implementations will Just Work for this code. Relying on this UB is useful, because we don't need to add an explicit check for NULL, and therefore we have faster code. Although the current code can't have a NULL, I expect that when we add support for variables in the index, it will be NULL in some cases. Link: The same code seems to be defined behavior in C++, which normally will share implementation in the compiler for these cases, and therefore it is really unlikely to be in trouble. Link: --- src/nxt_http_static.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 61dd0cb3..eef96c16 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -756,9 +756,7 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) end = path->start + path->length; p = end; - for ( ;; ) { - /* There's always '/' in the beginning of the request path. */ - + while (p > path->start) { p--; ch = *p; @@ -767,11 +765,14 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) p++; /* Fall through. */ case '.': - exten->length = end - p; - exten->start = p; - return; + goto extension; } } + +extension: + + exten->length = end - p; + exten->start = p; } -- cgit From 4418f99cd46b17be893b6bd0df56434078e5aad3 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:52 +0100 Subject: Constified numerous function parameters. As was pointed out by the cppcheck[0] static code analysis utility we can mark numerous function parameters as 'const'. This acts as a hint to the compiler about our intentions and the compiler will tell us when we deviate from them. [0]: https://cppcheck.sourceforge.io/ --- src/nxt_conf.c | 10 +++++----- src/nxt_conf.h | 6 +++--- src/nxt_http.h | 5 +++-- src/nxt_http_parse.c | 26 +++++++++++++------------- src/nxt_http_parse.h | 2 +- src/nxt_http_request.c | 12 ++++++------ src/nxt_http_static.c | 4 ++-- src/nxt_mp.c | 4 ++-- src/nxt_port_memory_int.h | 2 +- src/nxt_port_socket.c | 4 ++-- src/nxt_string.c | 2 +- src/nxt_string.h | 2 +- src/nxt_unit.c | 5 +++-- 13 files changed, 43 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/nxt_conf.c b/src/nxt_conf.c index 79e776a0..a44b8c75 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -102,7 +102,7 @@ typedef struct { static nxt_int_t nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token); -static u_char *nxt_conf_json_skip_space(u_char *start, u_char *end); +static u_char *nxt_conf_json_skip_space(u_char *start, const u_char *end); static u_char *nxt_conf_json_parse_value(nxt_mp_t *mp, nxt_conf_value_t *value, u_char *start, u_char *end, nxt_conf_json_error_t *error); static u_char *nxt_conf_json_parse_object(nxt_mp_t *mp, nxt_conf_value_t *value, @@ -266,7 +266,7 @@ nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count) void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, - nxt_conf_value_t *value, uint32_t index) + const nxt_conf_value_t *value, uint32_t index) { nxt_conf_object_member_t *member; @@ -367,7 +367,7 @@ nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count) void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, - nxt_conf_value_t *value) + const nxt_conf_value_t *value) { array->u.array->elements[index] = *value; } @@ -1271,7 +1271,7 @@ nxt_conf_json_parse(nxt_mp_t *mp, u_char *start, u_char *end, static u_char * -nxt_conf_json_skip_space(u_char *start, u_char *end) +nxt_conf_json_skip_space(u_char *start, const u_char *end) { u_char *p, ch; @@ -2605,7 +2605,7 @@ nxt_conf_json_escape(u_char *dst, u_char *src, size_t size) void -nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line, +nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, nxt_uint_t *column) { u_char *p; diff --git a/src/nxt_conf.h b/src/nxt_conf.h index cfbc5991..46effac4 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -109,7 +109,7 @@ size_t nxt_conf_json_length(nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty); u_char *nxt_conf_json_print(u_char *p, nxt_conf_value_t *value, nxt_conf_json_pretty_t *pretty); -void nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line, +void nxt_conf_json_position(u_char *start, const u_char *pos, nxt_uint_t *line, nxt_uint_t *column); nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt); @@ -125,7 +125,7 @@ NXT_EXPORT uint8_t nxt_conf_get_boolean(nxt_conf_value_t *value); NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, - nxt_conf_value_t *value, uint32_t index); + const nxt_conf_value_t *value, uint32_t index); void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index); nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, @@ -137,7 +137,7 @@ void nxt_conf_set_member_null(nxt_conf_value_t *object, nxt_str_t *name, nxt_conf_value_t *nxt_conf_create_array(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index, - nxt_conf_value_t *value); + const nxt_conf_value_t *value); nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp, nxt_uint_t index, nxt_str_t *value); NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value); diff --git a/src/nxt_http.h b/src/nxt_http.h index 8fa0caad..4064a8a5 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -376,8 +376,9 @@ nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf); nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash); nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, - nxt_str_t *exten, nxt_str_t *type); -nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten); + const nxt_str_t *exten, nxt_str_t *type); +nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, + const nxt_str_t *exten); nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 1ab6cc90..1bb4291f 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -8,16 +8,16 @@ static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); -static u_char *nxt_http_lookup_field_end(u_char *p, u_char *end); + u_char **pos, const u_char *end); +static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end); static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp); @@ -62,7 +62,7 @@ static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = { nxt_inline nxt_http_target_traps_e -nxt_http_parse_target(u_char **pos, u_char *end) +nxt_http_parse_target(u_char **pos, const u_char *end) { u_char *p; nxt_uint_t trap; @@ -158,7 +158,7 @@ nxt_http_parse_fields(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b) static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, ch, *after_slash, *args; nxt_int_t rc; @@ -479,7 +479,7 @@ space_after_target: static nxt_int_t nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, ch; @@ -517,7 +517,7 @@ nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos, static nxt_int_t nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, c; size_t len; @@ -624,7 +624,7 @@ name_end: static nxt_int_t nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p, *start, ch; size_t len; @@ -704,7 +704,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos, static u_char * -nxt_http_lookup_field_end(u_char *p, u_char *end) +nxt_http_lookup_field_end(u_char *p, const u_char *end) { while (nxt_fast_path(end - p >= 16)) { @@ -771,7 +771,7 @@ nxt_http_lookup_field_end(u_char *p, u_char *end) static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos, - u_char *end) + const u_char *end) { u_char *p; nxt_http_field_t *field; diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 3cd9bd15..2b714464 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -35,7 +35,7 @@ typedef union { struct nxt_http_request_parse_s { nxt_int_t (*handler)(nxt_http_request_parse_t *rp, - u_char **pos, u_char *end); + u_char **pos, const u_char *end); nxt_str_t method; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 7fb86cc4..8aa20e59 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -30,11 +30,11 @@ static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, static nxt_http_name_value_t *nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, uint32_t hash, u_char *start, - u_char *end); + const u_char *end); static nxt_int_t nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, - u_char *end); + const u_char *end); static nxt_http_name_value_t *nxt_http_cookie(nxt_array_t *array, u_char *name, - size_t name_length, u_char *start, u_char *end); + size_t name_length, u_char *start, const u_char *end); #define NXT_HTTP_COOKIE_HASH \ @@ -949,7 +949,7 @@ nxt_http_arguments_parse(nxt_http_request_t *r) static nxt_http_name_value_t * nxt_http_argument(nxt_array_t *array, u_char *name, size_t name_length, - uint32_t hash, u_char *start, u_char *end) + uint32_t hash, u_char *start, const u_char *end) { size_t length; nxt_http_name_value_t *nv; @@ -1018,7 +1018,7 @@ nxt_http_cookies_parse(nxt_http_request_t *r) static nxt_int_t -nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) +nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, const u_char *end) { size_t name_length; u_char c, *p, *name; @@ -1067,7 +1067,7 @@ nxt_http_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) static nxt_http_name_value_t * nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, - u_char *start, u_char *end) + u_char *start, const u_char *end) { u_char c, *p; uint32_t hash; diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index eef96c16..387cdec0 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -1024,7 +1024,7 @@ typedef struct { nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, - nxt_str_t *exten, nxt_str_t *type) + const nxt_str_t *exten, nxt_str_t *type) { nxt_lvlhsh_query_t lhq; nxt_http_static_mtype_t *mtype; @@ -1049,7 +1049,7 @@ nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, nxt_str_t * -nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten) +nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, const nxt_str_t *exten) { nxt_lvlhsh_query_t lhq; nxt_http_static_mtype_t *mtype; diff --git a/src/nxt_mp.c b/src/nxt_mp.c index d0de2c0e..2bd8cdee 100644 --- a/src/nxt_mp.c +++ b/src/nxt_mp.c @@ -155,7 +155,7 @@ static void *nxt_mp_alloc_large(nxt_mp_t *mp, size_t alignment, size_t size, nxt_bool_t freeable); static intptr_t nxt_mp_rbtree_compare(nxt_rbtree_node_t *node1, nxt_rbtree_node_t *node2); -static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p); +static nxt_mp_block_t *nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p); static const char *nxt_mp_chunk_free(nxt_mp_t *mp, nxt_mp_block_t *cluster, u_char *p); @@ -830,7 +830,7 @@ nxt_mp_free(nxt_mp_t *mp, void *p) static nxt_mp_block_t * -nxt_mp_find_block(nxt_rbtree_t *tree, u_char *p) +nxt_mp_find_block(nxt_rbtree_t *tree, const u_char *p) { nxt_mp_block_t *block; nxt_rbtree_node_t *node, *sentinel; diff --git a/src/nxt_port_memory_int.h b/src/nxt_port_memory_int.h index c84615d5..21a05b10 100644 --- a/src/nxt_port_memory_int.h +++ b/src/nxt_port_memory_int.h @@ -100,7 +100,7 @@ nxt_inline void nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c); nxt_inline nxt_chunk_id_t -nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, u_char *p) +nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, const u_char *p) { u_char *mm_start; diff --git a/src/nxt_port_socket.c b/src/nxt_port_socket.c index 2a51dfb6..5752d5ab 100644 --- a/src/nxt_port_socket.c +++ b/src/nxt_port_socket.c @@ -19,7 +19,7 @@ static uint8_t nxt_port_enqueue_buf(nxt_task_t *task, nxt_port_msg_t *pm, void *qbuf, nxt_buf_t *b); static nxt_int_t nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, nxt_port_send_msg_t *msg); -static nxt_port_send_msg_t *nxt_port_msg_alloc(nxt_port_send_msg_t *m); +static nxt_port_send_msg_t *nxt_port_msg_alloc(const nxt_port_send_msg_t *m); static void nxt_port_write_handler(nxt_task_t *task, void *obj, void *data); static nxt_port_send_msg_t *nxt_port_msg_first(nxt_port_t *port); nxt_inline void nxt_port_msg_close_fd(nxt_port_send_msg_t *msg); @@ -332,7 +332,7 @@ nxt_port_msg_chk_insert(nxt_task_t *task, nxt_port_t *port, static nxt_port_send_msg_t * -nxt_port_msg_alloc(nxt_port_send_msg_t *m) +nxt_port_msg_alloc(const nxt_port_send_msg_t *m) { nxt_port_send_msg_t *msg; diff --git a/src/nxt_string.c b/src/nxt_string.c index b7aef79e..4d89c23c 100644 --- a/src/nxt_string.c +++ b/src/nxt_string.c @@ -338,7 +338,7 @@ nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length) size_t -nxt_str_strip(u_char *start, u_char *end) +nxt_str_strip(const u_char *start, u_char *end) { u_char *p; diff --git a/src/nxt_string.h b/src/nxt_string.h index 80cdbb59..a8673c61 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -96,7 +96,7 @@ NXT_EXPORT u_char *nxt_memcasestrn(const u_char *s, const u_char *end, const char *ss, size_t length); NXT_EXPORT u_char *nxt_rmemstrn(const u_char *s, const u_char *end, const char *ss, size_t length); -NXT_EXPORT size_t nxt_str_strip(u_char *start, u_char *end); +NXT_EXPORT size_t nxt_str_strip(const u_char *start, u_char *end); typedef struct { diff --git a/src/nxt_unit.c b/src/nxt_unit.c index f183ac6e..4be09061 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -196,7 +196,8 @@ static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx, static nxt_unit_request_info_t *nxt_unit_request_hash_find( nxt_unit_ctx_t *ctx, uint32_t stream, int remove); -static char * nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level); +static char * nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, + int level); static void *nxt_unit_lvlhsh_alloc(void *data, size_t size); static void nxt_unit_lvlhsh_free(void *data, void *p); static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length); @@ -6666,7 +6667,7 @@ static const char * nxt_unit_log_levels[] = { static char * -nxt_unit_snprint_prefix(char *p, char *end, pid_t pid, int level) +nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid, int level) { struct tm tm; struct timespec ts; -- cgit From 29c72085262073dc5dec1ecbde1d520da9763746 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:53 +0100 Subject: Marked a couple of variables 'const'. As was pointed out by the cppcheck[0] static code analysis utility we can mark a couple of variables as 'const'. This acts as a hint to the compiler about our intentions and the compiler will tell us when we deviate from them. [0]: https://cppcheck.sourceforge.io/ --- src/nxt_time_parse.c | 2 +- src/nxt_websocket_accept.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_time_parse.c b/src/nxt_time_parse.c index 94c43289..63620b09 100644 --- a/src/nxt_time_parse.c +++ b/src/nxt_time_parse.c @@ -22,7 +22,7 @@ nxt_time_parse(const u_char *p, size_t len) nxt_uint_t year, days; const u_char *end; - static nxt_int_t mday[12] = { + static const nxt_int_t mday[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; diff --git a/src/nxt_websocket_accept.c b/src/nxt_websocket_accept.c index 05cbcb56..0e2cef58 100644 --- a/src/nxt_websocket_accept.c +++ b/src/nxt_websocket_accept.c @@ -11,8 +11,8 @@ static void nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len) { - u_char c0, c1, c2; - static u_char basis[] = + u_char c0, c1, c2; + static const u_char basis[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; while (len > 2) { -- cgit From 7a286ec0797df4530eeee6f463ae00b86463084b Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:55 +0100 Subject: Socket: removed useless port < 1 check. In src/nxt_sockaddr.c::nxt_job_sockaddr_inet_parse() there is a check that port > 0 then there is a check that port < 1 || port > 65535, well we _know_ it can't be less than 1. --- src/nxt_sockaddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 730428e4..71e50e3c 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -1090,7 +1090,7 @@ nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs) port = nxt_int_parse(host, length); if (port > 0) { - if (port < 1 || port > 65535) { + if (port > 65535) { goto invalid_port; } -- cgit From 39819143ea891b752e5f1f6c6101d0861fb18850 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:00:58 +0100 Subject: Unit: avoided needlessly setting lib in nxt_unit_shm_open(). As was pointed out by the cppcheck[0] static code analysis utility, lib was being set in nxt_unit_shm_open() regardless of platform when in fact it's only used when (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN). Move the variable declaration & definition to be within the #if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN) block. [0]: https://cppcheck.sourceforge.io/ --- src/nxt_unit.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 4be09061..9baa680f 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -3813,13 +3813,12 @@ static int nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size) { int fd; - nxt_unit_impl_t *lib; - - lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); #if (NXT_HAVE_MEMFD_CREATE || NXT_HAVE_SHM_OPEN) char name[64]; + nxt_unit_impl_t *lib; + lib = nxt_container_of(ctx->unit, nxt_unit_impl_t, unit); snprintf(name, sizeof(name), NXT_SHM_PREFIX "unit.%d.%p", lib->pid, (void *) (uintptr_t) pthread_self()); #endif -- cgit From 63667e2f9c571ad4357a30e42b321bec6a97ee89 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 16 Jun 2022 02:01:01 +0100 Subject: Unit: removed a useless assignment. As was pointed out by the cppcheck[0] static code analysis utility there was a useless assignment in nxt_unit_request_read(). The size parameter is passed in by value and was being modified without being used again. [0]: https://cppcheck.sourceforge.io/ --- src/nxt_unit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/nxt_unit.c b/src/nxt_unit.c index 9baa680f..fd086b2c 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -3076,7 +3076,6 @@ nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, size_t size) } req->content_length -= res; - size -= res; dst = nxt_pointer_to(dst, res); -- cgit From f83aef1aab992f97e0f3bc663662055a28b85ee3 Mon Sep 17 00:00:00 2001 From: Timo Stark Date: Mon, 25 Apr 2022 12:57:07 +0200 Subject: Increased readtimeout for configuration endpoint. Closes: --- src/nxt_controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 7510d6f0..e1e9fade 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -725,7 +725,7 @@ static const nxt_event_conn_state_t nxt_controller_conn_read_state .timer_handler = nxt_controller_conn_read_timeout, .timer_value = nxt_controller_conn_timeout_value, - .timer_data = 60 * 1000, + .timer_data = 300 * 1000, }; -- cgit From 7b80186f097fda3d1c0758a30efa889ec89c5a9d Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 04:31:36 +0800 Subject: Var: optimization to get rid of nxt_var_cache_find(). No functional changes. --- src/nxt_var.c | 245 ++++++++++++++++++++-------------------------------------- 1 file changed, 84 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/src/nxt_var.c b/src/nxt_var.c index a7cbb898..05cd6fd2 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -26,19 +26,12 @@ typedef struct { } nxt_var_sub_t; -typedef struct { - nxt_var_t *var; - nxt_str_t *value; -} nxt_var_value_t; - - struct nxt_var_query_s { - nxt_array_t values; /* of nxt_var_value_t */ - nxt_array_t parts; /* of nxt_str_t * */ + nxt_mp_t *pool; nxt_lvlhsh_t cache; - nxt_str_t *spare; + nxt_uint_t waiting; nxt_uint_t failed; /* 1 bit */ @@ -60,15 +53,12 @@ static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); -static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index); -static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, - nxt_str_t *value, nxt_mp_t *mp); +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, + uint32_t index); static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, nxt_bool_t *is_var); -static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query); - static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, @@ -127,28 +117,22 @@ nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) static nxt_str_t * -nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index) +nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) { + nxt_int_t ret; + nxt_str_t *value; nxt_lvlhsh_query_t lhq; - lhq.key_hash = nxt_murmur_hash2_uint32(&index); - lhq.key.length = sizeof(uint32_t); - lhq.key.start = (u_char *) &index; - lhq.proto = &nxt_var_cache_proto; - - if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) { - return NULL; - } - - return lhq.value; -} + value = query->spare; + if (value == NULL) { + value = nxt_mp_zget(query->pool, sizeof(nxt_str_t)); + if (nxt_slow_path(value == NULL)) { + return NULL; + } -static nxt_int_t -nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, - nxt_mp_t *mp) -{ - nxt_lvlhsh_query_t lhq; + query->spare = value; + } lhq.key_hash = nxt_murmur_hash2_uint32(&index); lhq.replace = 0; @@ -156,9 +140,23 @@ nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, lhq.key.start = (u_char *) &index; lhq.value = value; lhq.proto = &nxt_var_cache_proto; - lhq.pool = mp; + lhq.pool = query->pool; - return nxt_lvlhsh_insert(lh, &lhq); + ret = nxt_lvlhsh_insert(&query->cache, &lhq); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NULL; + } + + if (ret == NXT_OK) { + ret = nxt_var_index[index](task, value, query->ctx); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + query->spare = NULL; + } + + return lhq.value; } @@ -432,14 +430,9 @@ nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) if (nxt_slow_path(query == NULL)) { return NXT_ERROR; } - - nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t)); - nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *)); - - } else { - nxt_array_reset(&query->values); } + query->pool = mp; query->ctx = ctx; *query_p = query; @@ -452,13 +445,12 @@ void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, nxt_str_t *str) { - uint32_t index; - nxt_mp_t *mp; - nxt_str_t *value; - nxt_int_t ret; - nxt_uint_t i; - nxt_var_sub_t *subs; - nxt_var_value_t *val; + u_char *p, *src; + size_t length, last, next; + nxt_str_t *value, **part; + nxt_uint_t i; + nxt_array_t parts; + nxt_var_sub_t *subs; if (nxt_var_is_const(var)) { nxt_var_raw(var, str); @@ -469,48 +461,63 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, return; } - mp = query->values.mem_pool; + nxt_memzero(&parts, sizeof(nxt_array_t)); + nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *)); + subs = nxt_var_subs(var); - value = query->spare; + + length = var->length; for (i = 0; i < var->vars; i++) { + value = nxt_var_cache_value(task, query, subs[i].index); + if (nxt_slow_path(value == NULL)) { + goto fail; + } - if (value == NULL) { - value = nxt_mp_zget(mp, sizeof(nxt_str_t)); - if (nxt_slow_path(value == NULL)) { - goto fail; - } + part = nxt_array_add(&parts); + if (nxt_slow_path(part == NULL)) { + goto fail; } - index = subs[i].index; + *part = value; - ret = nxt_var_cache_add(&query->cache, index, value, mp); + length += value->length - subs[i].length; + } - if (ret != NXT_OK) { - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } + p = nxt_mp_nget(query->pool, length + var->strz); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - continue; /* NXT_DECLINED */ - } + str->length = length; + str->start = p; - ret = nxt_var_index[index](task, value, query->ctx); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; + part = parts.elts; + src = nxt_var_raw_start(var); + + last = 0; + + for (i = 0; i < var->vars; i++) { + next = subs[i].position; + + if (next != last) { + p = nxt_cpymem(p, &src[last], next - last); } - value = NULL; + p = nxt_cpymem(p, part[i]->start, part[i]->length); + + last = next + subs[i].length; } - query->spare = value; + if (last != var->length) { + p = nxt_cpymem(p, &src[last], var->length - last); + } - val = nxt_array_add(&query->values); - if (nxt_slow_path(val == NULL)) { - goto fail; + if (var->strz) { + *p = '\0'; } - val->var = var; - val->value = str; + nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str); return; @@ -529,7 +536,9 @@ nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, query->error = error; if (query->waiting == 0) { - nxt_var_query_finish(task, query); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); } } @@ -541,94 +550,8 @@ nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, query->failed |= failed; if (--query->waiting == 0) { - nxt_var_query_finish(task, query); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); } } - - -static void -nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query) -{ - u_char *p, *src; - size_t length, last, next; - nxt_str_t *str, **part; - nxt_var_t *var; - nxt_uint_t i, j; - nxt_var_sub_t *subs; - nxt_var_value_t *val; - - if (query->failed) { - goto done; - } - - val = query->values.elts; - - for (i = 0; i < query->values.nelts; i++) { - var = val[i].var; - - subs = nxt_var_subs(var); - length = var->length; - - for (j = 0; j < var->vars; j++) { - str = nxt_var_cache_find(&query->cache, subs[j].index); - - nxt_assert(str != NULL); - - part = nxt_array_add(&query->parts); - - if (nxt_slow_path(part == NULL)) { - query->failed = 1; - goto done; - } - - *part = str; - - length += str->length - subs[j].length; - } - - p = nxt_mp_nget(query->values.mem_pool, length + var->strz); - if (nxt_slow_path(p == NULL)) { - query->failed = 1; - goto done; - } - - val[i].value->length = length; - val[i].value->start = p; - - part = query->parts.elts; - src = nxt_var_raw_start(var); - - last = 0; - - for (j = 0; j < var->vars; j++) { - next = subs[j].position; - - if (next != last) { - p = nxt_cpymem(p, &src[last], next - last); - } - - p = nxt_cpymem(p, part[j]->start, part[j]->length); - - last = next + subs[j].length; - } - - if (last != var->length) { - p = nxt_cpymem(p, &src[last], var->length - last); - } - - if (var->strz) { - *p = '\0'; - } - - nxt_array_reset(&query->parts); - - nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src, - val[i].value); - } - -done: - - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); -} -- cgit From 45b89e32577eef18e473d0c7ae24562e7efedcc0 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 04:32:49 +0800 Subject: Var: dynamic variables support. This commit adds the variables $arg_NAME, $header_NAME, and $cookie_NAME. --- src/nxt_conf.h | 1 + src/nxt_conf_validation.c | 7 +- src/nxt_http.h | 7 +- src/nxt_http_request.c | 54 +++++++++++++ src/nxt_http_return.c | 7 +- src/nxt_http_route.c | 14 ++-- src/nxt_http_static.c | 8 +- src/nxt_http_variables.c | 187 ++++++++++++++++++++++++++++++++++++++++------ src/nxt_router.c | 5 ++ src/nxt_router.h | 1 + src/nxt_var.c | 131 ++++++++++++++++++++++++++++++-- src/nxt_var.h | 28 +++++-- 12 files changed, 401 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/nxt_conf.h b/src/nxt_conf.h index 46effac4..f95b61c1 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -72,6 +72,7 @@ typedef struct { nxt_mp_t *pool; nxt_str_t error; void *ctx; + nxt_array_t *var_fields; /* of nxt_var_field_t */ nxt_mp_t *conf_pool; nxt_uint_t ver; } nxt_conf_validation_t; diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index a5958788..47164e92 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1210,6 +1210,11 @@ nxt_conf_validate(nxt_conf_validation_t *vldt) { nxt_int_t ret; + vldt->var_fields = nxt_array_create(vldt->pool, 4, sizeof(nxt_var_field_t)); + if (nxt_slow_path(vldt->var_fields == NULL)) { + return NXT_ERROR; + } + ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT); if (ret != NXT_OK) { return ret; @@ -1342,7 +1347,7 @@ nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name, { u_char error[NXT_MAX_ERROR_STR]; - if (nxt_var_test(value, error) != NXT_OK) { + if (nxt_var_test(value, vldt->var_fields, error) != NXT_OK) { return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.", error, name); } diff --git a/src/nxt_http.h b/src/nxt_http.h index 4064a8a5..c2e85840 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -339,6 +339,9 @@ nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive, uint8_t encoding); +int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name); +int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name); +int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name); nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); @@ -369,8 +372,8 @@ nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf, nxt_upstream_t ***upstream_joint); -nxt_int_t nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, - nxt_http_action_conf_t *acf); +nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf, + nxt_http_action_t *action, nxt_http_action_conf_t *acf); nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf); diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 8aa20e59..5f8fd8f7 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -1180,3 +1180,57 @@ end: return nxt_http_field_hash_end(hash) & 0xFFFF; } + + +int64_t +nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name) +{ + return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_PLUS); +} + + +int64_t +nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name) +{ + u_char c, *p; + uint32_t i, hash; + nxt_str_t str; + + str.length = name->length; + + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } + + p = str.start; + hash = NXT_HTTP_FIELD_HASH_INIT; + + for (i = 0; i < name->length; i++) { + c = name->start[i]; + + if (c >= 'A' && c <= 'Z') { + *p = c | 0x20; + + } else if (c == '_') { + *p = '-'; + + } else { + *p = c; + } + + hash = nxt_http_field_hash_char(hash, *p); + p++; + } + + *name = str; + + return nxt_http_field_hash_end(hash) & 0xFFFF; +} + + +int64_t +nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name) +{ + return nxt_http_field_hash(mp, name, 1, NXT_HTTP_URI_ENCODING_NONE); +} diff --git a/src/nxt_http_return.c b/src/nxt_http_return.c index 82c91568..9f3c4fc5 100644 --- a/src/nxt_http_return.c +++ b/src/nxt_http_return.c @@ -32,12 +32,15 @@ static const nxt_http_request_state_t nxt_http_return_send_state; nxt_int_t -nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, +nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf) { + nxt_mp_t *mp; nxt_str_t str; nxt_http_return_conf_t *conf; + mp = rtcf->mem_pool; + conf = nxt_mp_zget(mp, sizeof(nxt_http_return_conf_t)); if (nxt_slow_path(conf == NULL)) { return NXT_ERROR; @@ -54,7 +57,7 @@ nxt_http_return_init(nxt_mp_t *mp, nxt_http_action_t *action, nxt_conf_get_string(acf->location, &str); - conf->location = nxt_var_compile(&str, mp, 0); + conf->location = nxt_var_compile(&str, mp, rtcf->var_fields, 0); if (nxt_slow_path(conf->location == NULL)) { return NXT_ERROR; } diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 5a4f349e..e00c37fe 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -643,6 +643,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_mp_t *mp; nxt_int_t ret; nxt_str_t pass; + nxt_router_conf_t *rtcf; nxt_http_action_conf_t acf; nxt_memzero(&acf, sizeof(acf)); @@ -655,10 +656,11 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_memzero(action, sizeof(nxt_http_action_t)); - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; if (acf.ret != NULL) { - return nxt_http_return_init(mp, action, &acf); + return nxt_http_return_init(rtcf, action, &acf); } if (acf.share != NULL) { @@ -671,7 +673,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_get_string(acf.pass, &pass); - action->u.var = nxt_var_compile(&pass, mp, 0); + action->u.var = nxt_var_compile(&pass, mp, rtcf->var_fields, 0); if (nxt_slow_path(action->u.var == NULL)) { return NXT_ERROR; } @@ -1484,16 +1486,18 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, { nxt_mp_t *mp; nxt_int_t ret; + nxt_router_conf_t *rtcf; nxt_http_action_t *action; - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); if (nxt_slow_path(action == NULL)) { return NULL; } - action->u.var = nxt_var_compile(pass, mp, 0); + action->u.var = nxt_var_compile(pass, mp, rtcf->var_fields, 0); if (nxt_slow_path(action->u.var == NULL)) { return NULL; } diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 387cdec0..19393f2c 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -79,9 +79,11 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_str_t str, *ret; nxt_var_t *var; nxt_conf_value_t *cv; + nxt_router_conf_t *rtcf; nxt_http_static_conf_t *conf; - mp = tmcf->router_conf->mem_pool; + rtcf = tmcf->router_conf; + mp = rtcf->mem_pool; conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t)); if (nxt_slow_path(conf == NULL)) { @@ -102,7 +104,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, cv = nxt_conf_get_array_element_or_itself(acf->share, i); nxt_conf_get_string(cv, &str); - var = nxt_var_compile(&str, mp, 1); + var = nxt_var_compile(&str, mp, rtcf->var_fields, 1); if (nxt_slow_path(var == NULL)) { return NXT_ERROR; } @@ -128,7 +130,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_str_t chr, shr; nxt_bool_t is_const; - conf->chroot = nxt_var_compile(&acf->chroot, mp, 1); + conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields, 1); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index c48f9ca3..79e66668 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -8,29 +8,47 @@ static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, - void *ctx); + void *ctx, uint16_t field); static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, - void *ctx); -static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx); + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_var_decl_t nxt_http_vars[] = { - { nxt_string("method"), - &nxt_http_var_method, - 0 }, - - { nxt_string("request_uri"), - &nxt_http_var_request_uri, - 0 }, - - { nxt_string("uri"), - &nxt_http_var_uri, - 0 }, - - { nxt_string("host"), - &nxt_http_var_host, - 0 }, + { + .name = nxt_string("method"), + .handler = nxt_http_var_method, + }, { + .name = nxt_string("request_uri"), + .handler = nxt_http_var_request_uri, + }, { + .name = nxt_string("uri"), + .handler = nxt_http_var_uri, + }, { + .name = nxt_string("host"), + .handler = nxt_http_var_host, + }, { + .name = nxt_string("arg"), + .handler = nxt_http_var_arg, + .field_hash = nxt_http_argument_hash, + }, { + .name = nxt_string("header"), + .handler = nxt_http_var_header, + .field_hash = nxt_http_header_hash, + }, { + .name = nxt_string("cookie"), + .handler = nxt_http_var_cookie, + .field_hash = nxt_http_cookie_hash, + }, }; @@ -42,7 +60,7 @@ nxt_http_register_variables(void) static nxt_int_t -nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -55,7 +73,8 @@ nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx) static nxt_int_t -nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) { nxt_http_request_t *r; @@ -68,7 +87,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) static nxt_int_t -nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -81,7 +100,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx) static nxt_int_t -nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx) +nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -91,3 +110,125 @@ nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx) return NXT_OK; } + + +static nxt_int_t +nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_array_t *args; + nxt_var_field_t *vf; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + args = nxt_http_arguments_parse(r); + if (nxt_slow_path(args == NULL)) { + return NXT_ERROR; + } + + start = args->elts; + nv = start + args->nelts - 1; + + while (nv >= start) { + + if (vf->hash == nv->hash + && vf->name.length == nv->name_length + && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + { + str->start = nv->value; + str->length = nv->value_length; + + return NXT_OK; + } + + nv--; + } + + nxt_str_null(str); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_var_field_t *vf; + nxt_http_field_t *f; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + nxt_list_each(f, r->fields) { + + if (vf->hash == f->hash + && vf->name.length == f->name_length + && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0) + { + str->start = f->value; + str->length = f->value_length; + + return NXT_OK; + } + + } nxt_list_loop; + + nxt_str_null(str); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_array_t *cookies; + nxt_var_field_t *vf; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *end; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NXT_ERROR; + } + + nv = cookies->elts; + end = nv + cookies->nelts; + + while (nv < end) { + + if (vf->hash == nv->hash + && vf->name.length == nv->name_length + && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + { + str->start = nv->value; + str->length = nv->value_length; + + return NXT_OK; + } + + nv++; + } + + nxt_str_null(str); + + return NXT_OK; +} diff --git a/src/nxt_router.c b/src/nxt_router.c index a3cc0a8d..e84b3d9a 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1004,6 +1004,11 @@ nxt_router_temp_conf(nxt_task_t *task) rtcf->mem_pool = mp; + rtcf->var_fields = nxt_array_create(mp, 4, sizeof(nxt_var_field_t)); + if (nxt_slow_path(rtcf->var_fields == NULL)) { + goto fail; + } + tmp = nxt_mp_create(1024, 128, 256, 32); if (nxt_slow_path(tmp == NULL)) { goto fail; diff --git a/src/nxt_router.h b/src/nxt_router.h index 37008f9d..8c21a70a 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -43,6 +43,7 @@ typedef struct { uint32_t threads; nxt_mp_t *mem_pool; + nxt_array_t *var_fields; /* of nxt_var_field_t */ nxt_router_t *router; nxt_http_routes_t *routes; diff --git a/src/nxt_var.c b/src/nxt_var.c index 05cd6fd2..d3057764 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -52,6 +52,11 @@ struct nxt_var_query_s { static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); +static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, + uint32_t *index); +static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, + uint32_t hash); + static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index); @@ -109,6 +114,117 @@ nxt_var_hash_find(nxt_str_t *name) } +static nxt_var_decl_t * +nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index) +{ + u_char *p, *end; + int64_t hash; + uint16_t field; + nxt_str_t str; + nxt_var_decl_t *decl; + nxt_var_field_t *f; + + f = NULL; + field = 0; + decl = nxt_var_hash_find(name); + + if (decl == NULL) { + p = name->start; + end = p + name->length; + + while (p < end) { + if (*p++ == '_') { + break; + } + } + + if (p == end) { + return NULL; + } + + str.start = name->start; + str.length = p - 1 - name->start; + + decl = nxt_var_hash_find(&str); + + if (decl != NULL) { + str.start = p; + str.length = end - p; + + hash = decl->field_hash(fields->mem_pool, &str); + if (nxt_slow_path(hash == -1)) { + return NULL; + } + + f = nxt_var_field_add(fields, &str, (uint32_t) hash); + if (nxt_slow_path(f == NULL)) { + return NULL; + } + + field = f->index; + } + } + + if (decl != NULL) { + if (decl->field_hash != NULL && f == NULL) { + return NULL; + } + + if (index != NULL) { + *index = (decl->index << 16) | field; + } + } + + return decl; +} + + +static nxt_var_field_t * +nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash) +{ + nxt_uint_t i; + nxt_var_field_t *field; + + field = fields->elts; + + for (i = 0; i < fields->nelts; i++) { + if (field[i].hash == hash + && nxt_strstr_eq(&field[i].name, name)) + { + return field; + } + } + + field = nxt_array_add(fields); + if (nxt_slow_path(field == NULL)) { + return NULL; + } + + field->name = *name; + field->hash = hash; + field->index = fields->nelts - 1; + + return field; +} + + +nxt_var_field_t * +nxt_var_field_get(nxt_array_t *fields, uint16_t index) +{ + nxt_uint_t nfields; + nxt_var_field_t *field; + + field = fields->elts; + nfields = fields->nelts; + + if (nfields > 0 && index <= nfields) { + return &field[index]; + } + + return NULL; +} + + static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) { @@ -148,7 +264,8 @@ nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) } if (ret == NXT_OK) { - ret = nxt_var_index[index](task, value, query->ctx); + ret = nxt_var_index[index >> 16](task, value, query->ctx, + index & 0xffff); if (nxt_slow_path(ret != NXT_OK)) { return NULL; } @@ -213,10 +330,12 @@ nxt_var_index_init(void) nxt_var_t * -nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) +nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, + nxt_bool_t strz) { u_char *p, *end, *next, *src; size_t size; + uint32_t index; nxt_var_t *var; nxt_str_t part; nxt_uint_t n; @@ -267,12 +386,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) next = nxt_var_next_part(p, end - p, &part, &is_var); if (is_var) { - decl = nxt_var_hash_find(&part); + decl = nxt_var_decl_get(&part, fields, &index); if (nxt_slow_path(decl == NULL)) { return NULL; } - subs[n].index = decl->index; + subs[n].index = index; subs[n].length = next - p; subs[n].position = p - str->start; @@ -287,7 +406,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) nxt_int_t -nxt_var_test(nxt_str_t *str, u_char *error) +nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) { u_char *p, *end, *next; nxt_str_t part; @@ -308,7 +427,7 @@ nxt_var_test(nxt_str_t *str, u_char *error) } if (is_var) { - decl = nxt_var_hash_find(&part); + decl = nxt_var_decl_get(&part, fields, NULL); if (decl == NULL) { nxt_sprintf(error, error + NXT_MAX_ERROR_STR, diff --git a/src/nxt_var.h b/src/nxt_var.h index 1322d507..3c38be36 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -13,15 +13,25 @@ typedef struct nxt_var_query_s nxt_var_query_t; typedef nxt_int_t (*nxt_var_handler_t)(nxt_task_t *task, nxt_str_t *str, - void *ctx); + void *ctx, uint16_t field); + +typedef int64_t (*nxt_var_field_hash_t)(nxt_mp_t *mp, nxt_str_t *str); typedef struct { - nxt_str_t name; - nxt_var_handler_t handler; - uint32_t index; + nxt_str_t name; + nxt_var_handler_t handler; + nxt_var_field_hash_t field_hash; + uint32_t index; } nxt_var_decl_t; +typedef struct { + nxt_str_t name; + uint16_t hash; + uint32_t index; +} nxt_var_field_t; + + nxt_inline nxt_bool_t nxt_is_var(nxt_str_t *str) { @@ -31,11 +41,15 @@ nxt_is_var(nxt_str_t *str) nxt_int_t nxt_var_register(nxt_var_decl_t *decl, size_t n); nxt_int_t nxt_var_index_init(void); -nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz); -nxt_int_t nxt_var_test(nxt_str_t *str, u_char *error); -void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); +nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index); + +nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, + nxt_bool_t strz); +nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error); + nxt_bool_t nxt_var_is_const(nxt_var_t *var); +void nxt_var_raw(nxt_var_t *var, nxt_str_t *str); nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp); -- cgit From 8c5e2d5ce5cc31649f8900621d1b92d66100a687 Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 04:34:05 +0800 Subject: HTTP: added more variables. This commit adds the following variables: $remote_addr, $time_local, $request_line, $status, $body_bytes_sent, $header_referer, $header_user_agent. --- src/nxt_http_variables.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) (limited to 'src') diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 79e66668..837ef7b0 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -15,6 +15,22 @@ static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, @@ -36,6 +52,27 @@ static nxt_var_decl_t nxt_http_vars[] = { }, { .name = nxt_string("host"), .handler = nxt_http_var_host, + }, { + .name = nxt_string("remote_addr"), + .handler = nxt_http_var_remote_addr, + }, { + .name = nxt_string("time_local"), + .handler = nxt_http_var_time_local, + }, { + .name = nxt_string("request_line"), + .handler = nxt_http_var_request_line, + }, { + .name = nxt_string("status"), + .handler = nxt_http_var_status, + }, { + .name = nxt_string("body_bytes_sent"), + .handler = nxt_http_var_body_bytes_sent, + }, { + .name = nxt_string("header_referer"), + .handler = nxt_http_var_referer, + }, { + .name = nxt_string("header_user_agent"), + .handler = nxt_http_var_user_agent, }, { .name = nxt_string("arg"), .handler = nxt_http_var_arg, @@ -112,6 +149,204 @@ nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) } +static nxt_int_t +nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + str->length = r->remote->address_length; + str->start = nxt_sockaddr_address(r->remote); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_http_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + r = ctx; + + str->length = date_cache.size; + + str->start = nxt_mp_nget(r->mem_pool, str->length); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + str->length = nxt_thread_time_string(task->thread, &date_cache, str->start) + - str->start; + + return NXT_OK; +} + + +static u_char * +nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +static nxt_int_t +nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + size_t length; + u_char *p, *start; + nxt_http_request_t *r; + + r = ctx; + + length = r->method->length + 1 + r->target.length + 1 + r->version.length; + + start = nxt_mp_nget(r->mem_pool, length); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + p = start; + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + str->start = start; + str->length = p - start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_off_t bytes; + nxt_http_request_t *r; + + r = ctx; + + str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + + str->length = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", + bytes) - str->start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + str->start = nxt_mp_nget(r->mem_pool, 3); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + str->length = nxt_sprintf(str->start, str->start + 3, "%03d", r->status) + - str->start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + if (r->referer != NULL) { + str->start = r->referer->value; + str->length = r->referer->value_length; + + } else { + nxt_str_null(str); + } + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + if (r->user_agent != NULL) { + str->start = r->user_agent->value; + str->length = r->user_agent->value_length; + + } else { + nxt_str_null(str); + } + + return NXT_OK; +} + + static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { -- cgit From c8d9106a0d3217c385f6afe572d904d9d77b8c8b Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 19 Jun 2022 14:20:05 +0200 Subject: Removed code used when NXT_HAVE_POSIX_SPAWN is false. posix_spawn(3POSIX) was introduced by POSIX.1d (IEEE Std 1003.1d-1999), and was later consolidated in POSIX.1-2001, requiring it in all POSIX-compliant systems. It's safe to assume it's always available, more than 20 years after its standardization. Link: --- src/nxt_process.c | 48 ------------------------------------------------ src/nxt_unix.h | 2 -- 2 files changed, 50 deletions(-) (limited to 'src') diff --git a/src/nxt_process.c b/src/nxt_process.c index 82e66a99..98636bbe 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -798,8 +798,6 @@ nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process) } -#if (NXT_HAVE_POSIX_SPAWN) - /* * Linux glibc 2.2 posix_spawn() is implemented via fork()/execve(). * Linux glibc 2.4 posix_spawn() without file actions and spawn @@ -834,52 +832,6 @@ nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp) return pid; } -#else - -nxt_pid_t -nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp) -{ - nxt_pid_t pid; - - /* - * vfork() is better than fork() because: - * it is faster several times; - * its execution time does not depend on private memory mapping size; - * it has lesser chances to fail due to the ENOMEM error. - */ - - pid = vfork(); - - switch (pid) { - - case -1: - nxt_alert(task, "vfork() failed while executing \"%s\" %E", - name, nxt_errno); - break; - - case 0: - /* A child. */ - nxt_debug(task, "execve(\"%s\")", name); - - (void) execve(name, argv, envp); - - nxt_alert(task, "execve(\"%s\") failed %E", name, nxt_errno); - - exit(1); - nxt_unreachable(); - break; - - default: - /* A parent. */ - nxt_debug(task, "vfork(): %PI", pid); - break; - } - - return pid; -} - -#endif - nxt_int_t nxt_process_daemon(nxt_task_t *task) diff --git a/src/nxt_unix.h b/src/nxt_unix.h index d8eaabc3..6bc6be5e 100644 --- a/src/nxt_unix.h +++ b/src/nxt_unix.h @@ -156,9 +156,7 @@ #include #include #include -#if (NXT_HAVE_POSIX_SPAWN) #include -#endif #include #include /* offsetof() */ #include -- cgit From 5015b05fc495bf3e87f8decfd1617a4a399939d4 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 18 Jun 2022 15:59:12 +0200 Subject: Replaced Linux syscall macros by libc macros. User-space programs should use the SYS_*form, as documented in syscall(2). That also adds compatibility to non-Linux systems. --- src/nxt_clone.c | 4 ++-- src/nxt_isolation.c | 2 +- src/nxt_process.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nxt_clone.c b/src/nxt_clone.c index aa952a54..a9b39ac1 100644 --- a/src/nxt_clone.c +++ b/src/nxt_clone.c @@ -14,9 +14,9 @@ pid_t nxt_clone(nxt_int_t flags) { #if defined(__s390x__) || defined(__s390__) || defined(__CRIS__) - return syscall(__NR_clone, NULL, flags); + return syscall(SYS_clone, NULL, flags); #else - return syscall(__NR_clone, flags, NULL); + return syscall(SYS_clone, flags, NULL); #endif } diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index e3cb1f22..7bb8dbfd 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -1003,7 +1003,7 @@ fail: nxt_inline int nxt_pivot_root(const char *new_root, const char *old_root) { - return syscall(__NR_pivot_root, new_root, old_root); + return syscall(SYS_pivot_root, new_root, old_root); } diff --git a/src/nxt_process.h b/src/nxt_process.h index 694f457e..642c3419 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -19,7 +19,7 @@ * fork(2) calls. As we use clone(2) for container, it returns the wrong pid. */ #define nxt_getpid() \ - syscall(__NR_getpid) + syscall(SYS_getpid) #else #define nxt_getpid() \ getpid() -- cgit From 6ba39ccf9b862f56155aa4b391063bf548ce6574 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 23 Jun 2022 13:25:04 +0200 Subject: Fixed incorrect code. The #endif was misplaced by accident during a refactor: . clang(1)'s -Wunreachable-code-break (implied by -Weverything) catches that, but it is only produced for code compiled without support for Unix sockets, which is probably the reason it was undetected: no-one seems to be compiling Unit without Unix sockets support (at least with clang(1)). --- src/nxt_sockaddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 71e50e3c..e8dee83a 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -208,8 +208,8 @@ nxt_getsockname(nxt_task_t *task, nxt_mp_t *mp, nxt_socket_t s) #if (NXT_HAVE_UNIX_DOMAIN) case AF_UNIX: length = nxt_length("unix:") + socklen; -#endif break; +#endif case AF_INET: length = NXT_INET_ADDR_STR_LEN; -- cgit From 14857442c638d39dc0ece60087991916884cd113 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 1 Jul 2022 14:42:35 +0200 Subject: Added missing inline keyword. --- src/nxt_nncq.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_nncq.h b/src/nxt_nncq.h index 20e7ecff..6c9ab326 100644 --- a/src/nxt_nncq.h +++ b/src/nxt_nncq.h @@ -85,7 +85,7 @@ nxt_nncq_empty(nxt_nncq_t const volatile *q) } -static void +static inline void nxt_nncq_init(nxt_nncq_t volatile *q) { q->head = NXT_NNCQ_SIZE; @@ -94,7 +94,7 @@ nxt_nncq_init(nxt_nncq_t volatile *q) } -static void +static inline void nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val) { nxt_nncq_cycle_t e_cycle, t_cycle; @@ -128,7 +128,7 @@ nxt_nncq_enqueue(nxt_nncq_t volatile *q, nxt_nncq_atomic_t val) } -static nxt_nncq_atomic_t +static inline nxt_nncq_atomic_t nxt_nncq_dequeue(nxt_nncq_t volatile *q) { nxt_nncq_cycle_t e_cycle, h_cycle; -- cgit From 3422e81ab6794b6f2a4a1fb237923bab11ae2b18 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 1 Jul 2022 14:42:35 +0200 Subject: Added missing inline keyword. --- src/nxt_nvbcq.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_nvbcq.h b/src/nxt_nvbcq.h index 2b019dcc..e164615b 100644 --- a/src/nxt_nvbcq.h +++ b/src/nxt_nvbcq.h @@ -64,7 +64,7 @@ nxt_nvbcq_empty(nxt_nvbcq_t const volatile *q) } -static void +static inline void nxt_nvbcq_init(nxt_nvbcq_t volatile *q) { nxt_nvbcq_atomic_t i; @@ -79,7 +79,7 @@ nxt_nvbcq_init(nxt_nvbcq_t volatile *q) } -static void +static inline void nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val) { nxt_nvbcq_atomic_t t, h, i; @@ -110,7 +110,7 @@ nxt_nvbcq_enqueue(nxt_nvbcq_t volatile *q, nxt_nvbcq_atomic_t val) } -static nxt_nvbcq_atomic_t +static inline nxt_nvbcq_atomic_t nxt_nvbcq_dequeue(nxt_nvbcq_t volatile *q) { nxt_nvbcq_atomic_t h, t, i, e; -- cgit From eebaff42eaef94f67f2232fc551f6d43c90c2e5c Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Fri, 6 May 2022 19:41:02 +0100 Subject: Var: added a $dollar variable that translates to a '$'. Allow $dollar (or ${dollar}) to translate to a literal $ to allow support for sub-delimiters in URIs. It is possible to have URLs like https://example.com/path/15$1588/9925$2976.html and thus it would be useful to be able to specify them in various bits of the unit config such as the location setting. However this hadn't been possible due to $ being used to denote variables for substitution. E.g $host. As was noted in the below GitHub issue it was suggested by @VBart to use $sign to represent a literal $, however I feel $dollar is more appropriate so we have a variable named after the thing it represents, also @tippexs found[0] that &dollar is used in HTML to represent a $, so there is some somewhat related precedent. (The other idea to use $$ was rejected in my original pull-request[1] for this issue.) This means the above URL could be specified as https://example.com/path/15${dollar}1588/9925${dollar}2976.html in the unit config. This is done by adding a variable called 'dollar' which is loaded into the variables hash table which translates into a literal $. This is then handled in nxt_var_next_part() where variables are parsed for lookup and $dollar is set for substitution by a literal '$'. Actual variable substitution happens in nxt_var_query_finish(). [0]: https://github.com/nginx/unit/pull/693#issuecomment-1130412323 [1]: https://github.com/nginx/unit/pull/693 Closes: https://github.com/nginx/unit/issues/675 --- src/nxt_http_variables.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index 837ef7b0..5a632b24 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -7,6 +7,8 @@ #include +static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field); static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, @@ -41,6 +43,9 @@ static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, static nxt_var_decl_t nxt_http_vars[] = { { + .name = nxt_string("dollar"), + .handler = nxt_http_var_dollar, + }, { .name = nxt_string("method"), .handler = nxt_http_var_method, }, { @@ -96,6 +101,15 @@ nxt_http_register_variables(void) } +static nxt_int_t +nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_str_set(str, "$"); + + return NXT_OK; +} + + static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { -- cgit From c1cea3c97d5dfc260a54cab67b7dc1637a3deb59 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 15 Jun 2022 16:20:01 +0100 Subject: Router: avoided undefined behaviour. In src/nxt_http_route_addr.c::nxt_http_route_addr_pattern_parse() there was potentially undefined behaviour when shifting a 32 bit value by 32 bits, this could happen if cidr_prefix was 0. Promote the shiftee to unsigned long long to avoid this issue. --- src/nxt_http_route_addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 2907a902..985fb737 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -233,7 +233,7 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, } addr.length = delim - addr.start; - inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - cidr_prefix))); + inet->end = htonl(0xFFFFFFFF & (0xFFFFFFFFULL << (32 - cidr_prefix))); inet->start = nxt_inet_addr(addr.start, addr.length) & inet->end; if (nxt_slow_path(inet->start == INADDR_NONE)) { -- cgit From 6e36584a2e9bad0e7c4f96d68c527992deadc650 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Mon, 28 Feb 2022 12:12:30 +0100 Subject: Supporting UNIX sockets in address matching. This closes #645 issue on GitHub. (Also moved a changelog line that was misplaced in a previous commit.) --- src/nxt_conf_validation.c | 5 +++++ src/nxt_http_route.c | 7 +++++++ src/nxt_http_route_addr.c | 10 ++++++++++ src/nxt_http_route_addr.h | 1 + 4 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 47164e92..8c532914 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -2157,6 +2157,11 @@ nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, return nxt_conf_vldt_error(vldt, "The \"address\" does not support " "IPv6 with your configuration."); + case NXT_ADDR_PATTERN_NO_UNIX_ERROR: + return nxt_conf_vldt_error(vldt, "The \"address\" does not support " + "UNIX domain sockets with your " + "configuration."); + default: return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown " "format."); diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index e00c37fe..cdc9077f 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -1818,6 +1818,13 @@ nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, break; #endif +#if (NXT_HAVE_UNIX_DOMAIN) + case AF_UNIX: + + match = (base->addr_family == AF_UNIX); + break; +#endif + default: match = 0; break; diff --git a/src/nxt_http_route_addr.c b/src/nxt_http_route_addr.c index 985fb737..34455af4 100644 --- a/src/nxt_http_route_addr.c +++ b/src/nxt_http_route_addr.c @@ -41,6 +41,16 @@ nxt_http_route_addr_pattern_parse(nxt_mp_t *mp, base->negative = 0; } + if (nxt_str_eq(&addr, "unix", 4)) { +#if (NXT_HAVE_UNIX_DOMAIN) + base->addr_family = AF_UNIX; + + return NXT_OK; +#else + return NXT_ADDR_PATTERN_NO_UNIX_ERROR; +#endif + } + if (nxt_slow_path(addr.length < 2)) { return NXT_ADDR_PATTERN_LENGTH_ERROR; } diff --git a/src/nxt_http_route_addr.h b/src/nxt_http_route_addr.h index 3b1e1da3..2deda6f8 100644 --- a/src/nxt_http_route_addr.h +++ b/src/nxt_http_route_addr.h @@ -26,6 +26,7 @@ enum { NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR, NXT_ADDR_PATTERN_CIDR_ERROR, NXT_ADDR_PATTERN_NO_IPv6_ERROR, + NXT_ADDR_PATTERN_NO_UNIX_ERROR, }; -- cgit From 9b4b4925b38333b8d7795331d27db9811f43d72a Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 9 Jun 2022 14:39:59 +0200 Subject: Ruby: fixed contents of SCRIPT_NAME. Having the basename of the script pathname was incorrect. While we don't have something more accurate, the best thing to do is to have it empty (which should be the right thing most of the time). This closes #715 issue on GitHub. The bug was introduced in git commit 0032543fa65f454c471c968998190b027c1ff270 'Ruby: added the Rack environment parameter "SCRIPT_NAME".'. --- src/ruby/nxt_ruby.c | 46 +++++----------------------------------------- src/ruby/nxt_ruby.h | 1 - 2 files changed, 5 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 8f4afd35..4df77499 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -29,7 +29,6 @@ typedef struct { static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data); static VALUE nxt_ruby_init_basic(VALUE arg); -static VALUE nxt_ruby_script_basename(nxt_str_t *script); static VALUE nxt_ruby_hook_procs_load(VALUE path); static VALUE nxt_ruby_hook_register(VALUE arg); @@ -50,7 +49,7 @@ static void *nxt_ruby_thread_create_gvl(void *rctx); static VALUE nxt_ruby_thread_func(VALUE arg); static void *nxt_ruby_unit_run(void *ctx); static void nxt_ruby_ubf(void *ctx); -static int nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c); +static int nxt_ruby_init_threads(nxt_ruby_app_conf_t *c); static void nxt_ruby_join_threads(nxt_unit_ctx_t *ctx, nxt_ruby_app_conf_t *c); @@ -261,7 +260,7 @@ static nxt_int_t nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) { int state, rc; - VALUE res, path, script; + VALUE res, path; nxt_ruby_ctx_t ruby_ctx; nxt_unit_ctx_t *unit_ctx; nxt_unit_init_t ruby_unit_init; @@ -283,10 +282,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) ruby_options(2, argv); ruby_script("NGINX_Unit"); - script = nxt_ruby_script_basename(&c->script); - ruby_ctx.env = Qnil; - ruby_ctx.script = script; ruby_ctx.io_input = Qnil; ruby_ctx.io_error = Qnil; ruby_ctx.thread = Qnil; @@ -356,7 +352,7 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) goto fail; } - rc = nxt_ruby_init_threads(script, c); + rc = nxt_ruby_init_threads(c); if (nxt_slow_path(rc == NXT_UNIT_ERROR)) { goto fail; } @@ -424,37 +420,6 @@ fail: } -static VALUE -nxt_ruby_script_basename(nxt_str_t *script) -{ - size_t len; - u_char *p, *last; - - last = NULL; - p = script->start + script->length; - - while (p > script->start) { - - if (p[-1] == '/') { - last = p; - break; - } - - p--; - } - - if (last != NULL) { - len = script->length - (last - script->start); - - } else { - last = script->start; - len = script->length; - } - - return rb_str_new((const char *) last, len); -} - - static VALUE nxt_ruby_init_basic(VALUE arg) { @@ -598,7 +563,7 @@ nxt_ruby_rack_env_create(VALUE arg) rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MAJOR)); rb_ary_push(version, UINT2NUM(NXT_RUBY_RACK_API_VERSION_MINOR)); - rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rctx->script); + rb_hash_aset(hash_env, rb_str_new2("SCRIPT_NAME"), rb_str_new("", 0)); rb_hash_aset(hash_env, rb_str_new2("rack.version"), version); rb_hash_aset(hash_env, rb_str_new2("rack.input"), rctx->io_input); rb_hash_aset(hash_env, rb_str_new2("rack.errors"), rctx->io_error); @@ -1393,7 +1358,7 @@ nxt_ruby_ubf(void *ctx) static int -nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c) +nxt_ruby_init_threads(nxt_ruby_app_conf_t *c) { int state; uint32_t i; @@ -1415,7 +1380,6 @@ nxt_ruby_init_threads(VALUE script, nxt_ruby_app_conf_t *c) rctx = &nxt_ruby_ctxs[i]; rctx->env = Qnil; - rctx->script = script; rctx->io_input = Qnil; rctx->io_error = Qnil; rctx->thread = Qnil; diff --git a/src/ruby/nxt_ruby.h b/src/ruby/nxt_ruby.h index 3bdd567a..26430021 100644 --- a/src/ruby/nxt_ruby.h +++ b/src/ruby/nxt_ruby.h @@ -22,7 +22,6 @@ typedef struct { VALUE env; - VALUE script; VALUE io_input; VALUE io_error; VALUE thread; -- cgit From 2bd4a455278dbce756c1dc8be07515f73d611e3b Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 28 Jul 2022 11:00:15 +0800 Subject: Ruby: fixed segfault on SIGTERM signal. This closes #562 issue on GitHub. --- src/ruby/nxt_ruby.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 4df77499..07d02dce 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -377,8 +377,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) } } - rc = (intptr_t) rb_thread_call_without_gvl(nxt_ruby_unit_run, unit_ctx, - nxt_ruby_ubf, unit_ctx); + rc = (intptr_t) rb_thread_call_without_gvl2(nxt_ruby_unit_run, unit_ctx, + nxt_ruby_ubf, unit_ctx); if (nxt_ruby_hook_procs != Qnil) { rb_protect(nxt_ruby_hook_call, nxt_rb_on_thread_shutdown, &state); -- cgit From 8761501b4845656a0f2e5c0e7bf98f948c45fb5f Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 14 Jul 2022 11:14:20 +0800 Subject: Log: split access log from nxt_router.c. No functional changes. --- src/nxt_router.c | 443 +------------------------------------------ src/nxt_router.h | 16 ++ src/nxt_router_access_log.c | 446 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 470 insertions(+), 435 deletions(-) create mode 100644 src/nxt_router_access_log.c (limited to 'src') diff --git a/src/nxt_router.c b/src/nxt_router.c index e84b3d9a..e1f4f6da 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -92,15 +92,10 @@ static void nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); -static void nxt_router_access_log_reopen_handler(nxt_task_t *task, - nxt_port_recv_msg_t *msg); static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task); -static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); static void nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); -static void nxt_router_conf_error(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf); static void nxt_router_conf_send(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type); @@ -201,27 +196,6 @@ static void nxt_router_req_headers_ack_handler(nxt_task_t *task, static void nxt_router_listen_socket_release(nxt_task_t *task, nxt_socket_conf_t *skcf); -static void nxt_router_access_log_writer(nxt_task_t *task, - nxt_http_request_t *r, nxt_router_access_log_t *access_log); -static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); -static void nxt_router_access_log_open(nxt_task_t *task, - nxt_router_temp_conf_t *tmcf); -static void nxt_router_access_log_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_router_access_log_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log); -static void nxt_router_access_log_release(nxt_task_t *task, - nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); -static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, - void *data); -static void nxt_router_access_log_reopen_ready(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); -static void nxt_router_access_log_reopen_error(nxt_task_t *task, - nxt_port_recv_msg_t *msg, void *data); - static void nxt_router_app_port_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); static void nxt_router_app_port_error(nxt_task_t *task, @@ -271,7 +245,7 @@ static void nxt_router_get_mmap_handler(nxt_task_t *task, extern const nxt_http_request_state_t nxt_http_websocket; -static nxt_router_t *nxt_router; +nxt_router_t *nxt_router; static const nxt_str_t http_prefix = nxt_string("HTTP_"); static const nxt_str_t empty_prefix = nxt_string(""); @@ -1075,7 +1049,7 @@ nxt_router_app_need_start(nxt_app_t *app) } -static void +void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; @@ -1231,7 +1205,7 @@ nxt_router_conf_ready(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) } -static void +void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) { nxt_app_t *app; @@ -1483,7 +1457,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_mp_t *mp, *app_mp; uint32_t next, next_target; nxt_int_t ret; - nxt_str_t name, path, target; + nxt_str_t name, target; nxt_app_t *app, *prev; nxt_str_t *t, *s, *targets; nxt_uint_t n, i; @@ -1503,7 +1477,6 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_event_engine_t *engine; nxt_app_lang_module_t *lang; nxt_router_app_conf_t apcf; - nxt_router_access_log_t *access_log; nxt_router_listener_conf_t lscf; static nxt_str_t http_path = nxt_string("/settings/http"); @@ -1793,6 +1766,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (nxt_slow_path(routes == NULL)) { return NXT_ERROR; } + rtcf->routes = routes; } @@ -1980,33 +1954,10 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, value = nxt_conf_get_path(root, &access_log_path); if (value != NULL) { - nxt_conf_get_string(value, &path); - - access_log = router->access_log; - - if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { - nxt_router_access_log_use(&router->lock, access_log); - - } else { - access_log = nxt_malloc(sizeof(nxt_router_access_log_t) - + path.length); - if (access_log == NULL) { - nxt_alert(task, "failed to allocate access log structure"); - goto fail; - } - - access_log->fd = -1; - access_log->handler = &nxt_router_access_log_writer; - access_log->count = 1; - - access_log->path.length = path.length; - access_log->path.start = (u_char *) access_log - + sizeof(nxt_router_access_log_t); - - nxt_memcpy(access_log->path.start, path.start, path.length); + ret = nxt_router_access_log_create(task, rtcf, value); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; } - - rtcf->access_log = access_log; } nxt_queue_add(&deleting_sockets, &router->sockets); @@ -3759,384 +3710,6 @@ nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint) } -static void -nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log) -{ - size_t size; - u_char *buf, *p; - nxt_off_t bytes; - - static nxt_time_string_t date_cache = { - (nxt_atomic_uint_t) -1, - nxt_router_access_log_date, - "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", - nxt_length("31/Dec/1986:19:40:00 +0300"), - NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_SEC, - }; - - size = r->remote->address_length - + 6 /* ' - - [' */ - + date_cache.size - + 3 /* '] "' */ - + r->method->length - + 1 /* space */ - + r->target.length - + 1 /* space */ - + r->version.length - + 2 /* '" ' */ - + 3 /* status */ - + 1 /* space */ - + NXT_OFF_T_LEN - + 2 /* ' "' */ - + (r->referer != NULL ? r->referer->value_length : 1) - + 3 /* '" "' */ - + (r->user_agent != NULL ? r->user_agent->value_length : 1) - + 2 /* '"\n' */ - ; - - buf = nxt_mp_nget(r->mem_pool, size); - if (nxt_slow_path(buf == NULL)) { - return; - } - - p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), - r->remote->address_length); - - p = nxt_cpymem(p, " - - [", 6); - - p = nxt_thread_time_string(task->thread, &date_cache, p); - - p = nxt_cpymem(p, "] \"", 3); - - if (r->method->length != 0) { - p = nxt_cpymem(p, r->method->start, r->method->length); - - if (r->target.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->target.start, r->target.length); - - if (r->version.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->version.start, r->version.length); - } - } - - } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\" ", 2); - - p = nxt_sprintf(p, p + 3, "%03d", r->status); - - *p++ = ' '; - - bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); - - p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); - - p = nxt_cpymem(p, " \"", 2); - - if (r->referer != NULL) { - p = nxt_cpymem(p, r->referer->value, r->referer->value_length); - - } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\" \"", 3); - - if (r->user_agent != NULL) { - p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); - - } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\"\n", 2); - - nxt_fd_write(access_log->fd, buf, p - buf); -} - - -static u_char * -nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) -{ - u_char sign; - time_t gmtoff; - - static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - gmtoff = nxt_timezone(tm) / 60; - - if (gmtoff < 0) { - gmtoff = -gmtoff; - sign = '-'; - - } else { - sign = '+'; - } - - return nxt_sprintf(buf, buf + size, format, - tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec, - sign, gmtoff / 60, gmtoff % 60); -} - - -static void -nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) -{ - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_router_access_log_t *access_log; - - access_log = tmcf->router_conf->access_log; - - b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } - - b->completion_handler = nxt_buf_dummy_completion; - - nxt_buf_cpystr(b, &access_log->path); - *b->mem.free++ = '\0'; - - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_access_log_ready, - nxt_router_access_log_error, - -1, tmcf); - if (nxt_slow_path(stream == 0)) { - goto fail; - } - - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, - stream, router_port->id, b); - - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } - - return; - -fail: - - nxt_router_conf_error(task, tmcf); -} - - -static void -nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_temp_conf_t *tmcf; - nxt_router_access_log_t *access_log; - - tmcf = data; - - access_log = tmcf->router_conf->access_log; - - access_log->fd = msg->fd[0]; - - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - nxt_router_conf_apply, task, tmcf, NULL); -} - - -static void -nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_temp_conf_t *tmcf; - - tmcf = data; - - nxt_router_conf_error(task, tmcf); -} - - -static void -nxt_router_access_log_use(nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log) -{ - if (access_log == NULL) { - return; - } - - nxt_thread_spin_lock(lock); - - access_log->count++; - - nxt_thread_spin_unlock(lock); -} - - -static void -nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, - nxt_router_access_log_t *access_log) -{ - if (access_log == NULL) { - return; - } - - nxt_thread_spin_lock(lock); - - if (--access_log->count != 0) { - access_log = NULL; - } - - nxt_thread_spin_unlock(lock); - - if (access_log != NULL) { - - if (access_log->fd != -1) { - nxt_fd_close(access_log->fd); - } - - nxt_free(access_log); - } -} - - -typedef struct { - nxt_mp_t *mem_pool; - nxt_router_access_log_t *access_log; -} nxt_router_access_log_reopen_t; - - -static void -nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) -{ - nxt_mp_t *mp; - uint32_t stream; - nxt_int_t ret; - nxt_buf_t *b; - nxt_port_t *main_port, *router_port; - nxt_runtime_t *rt; - nxt_router_access_log_t *access_log; - nxt_router_access_log_reopen_t *reopen; - - access_log = nxt_router->access_log; - - if (access_log == NULL) { - return; - } - - mp = nxt_mp_create(1024, 128, 256, 32); - if (nxt_slow_path(mp == NULL)) { - return; - } - - reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); - if (nxt_slow_path(reopen == NULL)) { - goto fail; - } - - reopen->mem_pool = mp; - reopen->access_log = access_log; - - b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); - if (nxt_slow_path(b == NULL)) { - goto fail; - } - - b->completion_handler = nxt_router_access_log_reopen_completion; - - nxt_buf_cpystr(b, &access_log->path); - *b->mem.free++ = '\0'; - - rt = task->thread->runtime; - main_port = rt->port_by_type[NXT_PROCESS_MAIN]; - router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; - - stream = nxt_port_rpc_register_handler(task, router_port, - nxt_router_access_log_reopen_ready, - nxt_router_access_log_reopen_error, - -1, reopen); - if (nxt_slow_path(stream == 0)) { - goto fail; - } - - ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, - stream, router_port->id, b); - - if (nxt_slow_path(ret != NXT_OK)) { - nxt_port_rpc_cancel(task, router_port, stream); - goto fail; - } - - nxt_mp_retain(mp); - - return; - -fail: - - nxt_mp_destroy(mp); -} - - -static void -nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) -{ - nxt_mp_t *mp; - nxt_buf_t *b; - - b = obj; - mp = b->data; - - nxt_mp_release(mp); -} - - -static void -nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_access_log_t *access_log; - nxt_router_access_log_reopen_t *reopen; - - reopen = data; - - access_log = reopen->access_log; - - if (access_log == nxt_router->access_log) { - - if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { - nxt_alert(task, "dup2(%FD, %FD) failed %E", - msg->fd[0], access_log->fd, nxt_errno); - } - } - - nxt_fd_close(msg->fd[0]); - nxt_mp_release(reopen->mem_pool); -} - - -static void -nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, - void *data) -{ - nxt_router_access_log_reopen_t *reopen; - - reopen = data; - - nxt_mp_release(reopen->mem_pool); -} - - static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj, void *data) { diff --git a/src/nxt_router.h b/src/nxt_router.h index 8c21a70a..18fb60b0 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -237,7 +237,23 @@ nxt_int_t nxt_router_application_init(nxt_router_conf_t *rtcf, nxt_str_t *name, nxt_str_t *target, nxt_http_action_t *action); void nxt_router_listen_event_release(nxt_task_t *task, nxt_listen_event_t *lev, nxt_socket_conf_joint_t *joint); + +void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data); +void nxt_router_conf_error(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); void nxt_router_conf_release(nxt_task_t *task, nxt_socket_conf_joint_t *joint); +nxt_int_t nxt_router_access_log_create(nxt_task_t *task, + nxt_router_conf_t *rtcf, nxt_conf_value_t *value); +void nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf); +void nxt_router_access_log_use(nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log); +void nxt_router_access_log_release(nxt_task_t *task, + nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log); +void nxt_router_access_log_reopen_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg); + + +extern nxt_router_t *nxt_router; + #endif /* _NXT_ROUTER_H_INCLUDED_ */ diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c new file mode 100644 index 00000000..d92e80c3 --- /dev/null +++ b/src/nxt_router_access_log.c @@ -0,0 +1,446 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Valentin V. Bartenev + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include + + +static void nxt_router_access_log_writer(nxt_task_t *task, + nxt_http_request_t *r, nxt_router_access_log_t *access_log); +static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static void nxt_router_access_log_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, + void *data); +static void nxt_router_access_log_reopen_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_reopen_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); + + +nxt_int_t +nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, + nxt_conf_value_t *value) +{ + nxt_str_t path; + nxt_router_t *router; + nxt_router_access_log_t *access_log; + + router = nxt_router; + + nxt_conf_get_string(value, &path); + + access_log = router->access_log; + + if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { + nxt_router_access_log_use(&router->lock, access_log); + + } else { + access_log = nxt_malloc(sizeof(nxt_router_access_log_t) + + path.length); + if (access_log == NULL) { + nxt_alert(task, "failed to allocate access log structure"); + return NXT_ERROR; + } + + access_log->fd = -1; + access_log->handler = &nxt_router_access_log_writer; + access_log->count = 1; + + access_log->path.length = path.length; + access_log->path.start = (u_char *) access_log + + sizeof(nxt_router_access_log_t); + + nxt_memcpy(access_log->path.start, path.start, path.length); + } + + rtcf->access_log = access_log; + + return NXT_OK; +} + + +static void +nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_t *access_log) +{ + size_t size; + u_char *buf, *p; + nxt_off_t bytes; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_router_access_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + size = r->remote->address_length + + 6 /* ' - - [' */ + + date_cache.size + + 3 /* '] "' */ + + r->method->length + + 1 /* space */ + + r->target.length + + 1 /* space */ + + r->version.length + + 2 /* '" ' */ + + 3 /* status */ + + 1 /* space */ + + NXT_OFF_T_LEN + + 2 /* ' "' */ + + (r->referer != NULL ? r->referer->value_length : 1) + + 3 /* '" "' */ + + (r->user_agent != NULL ? r->user_agent->value_length : 1) + + 2 /* '"\n' */ + ; + + buf = nxt_mp_nget(r->mem_pool, size); + if (nxt_slow_path(buf == NULL)) { + return; + } + + p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), + r->remote->address_length); + + p = nxt_cpymem(p, " - - [", 6); + + p = nxt_thread_time_string(task->thread, &date_cache, p); + + p = nxt_cpymem(p, "] \"", 3); + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" ", 2); + + p = nxt_sprintf(p, p + 3, "%03d", r->status); + + *p++ = ' '; + + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + + p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); + + p = nxt_cpymem(p, " \"", 2); + + if (r->referer != NULL) { + p = nxt_cpymem(p, r->referer->value, r->referer->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" \"", 3); + + if (r->user_agent != NULL) { + p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\"\n", 2); + + nxt_fd_write(access_log->fd, buf, p - buf); +} + + +static u_char * +nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +void +nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) +{ + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + + access_log = tmcf->router_conf->access_log; + + b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + b->completion_handler = nxt_buf_dummy_completion; + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_ready, + nxt_router_access_log_error, + -1, tmcf); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } + + return; + +fail: + + nxt_router_conf_error(task, tmcf); +} + + +static void +nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + nxt_router_access_log_t *access_log; + + tmcf = data; + + access_log = tmcf->router_conf->access_log; + + access_log->fd = msg->fd[0]; + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); +} + + +static void +nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + + tmcf = data; + + nxt_router_conf_error(task, tmcf); +} + + +void +nxt_router_access_log_use(nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + access_log->count++; + + nxt_thread_spin_unlock(lock); +} + + +void +nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + if (--access_log->count != 0) { + access_log = NULL; + } + + nxt_thread_spin_unlock(lock); + + if (access_log != NULL) { + + if (access_log->fd != -1) { + nxt_fd_close(access_log->fd); + } + + nxt_free(access_log); + } +} + + +typedef struct { + nxt_mp_t *mem_pool; + nxt_router_access_log_t *access_log; +} nxt_router_access_log_reopen_t; + + +void +nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + nxt_mp_t *mp; + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; + + access_log = nxt_router->access_log; + + if (access_log == NULL) { + return; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return; + } + + reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); + if (nxt_slow_path(reopen == NULL)) { + goto fail; + } + + reopen->mem_pool = mp; + reopen->access_log = access_log; + + b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + b->completion_handler = nxt_router_access_log_reopen_completion; + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_reopen_ready, + nxt_router_access_log_reopen_error, + -1, reopen); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } + + nxt_mp_retain(mp); + + return; + +fail: + + nxt_mp_destroy(mp); +} + + +static void +nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) +{ + nxt_mp_t *mp; + nxt_buf_t *b; + + b = obj; + mp = b->data; + + nxt_mp_release(mp); +} + + +static void +nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; + + reopen = data; + + access_log = reopen->access_log; + + if (access_log == nxt_router->access_log) { + + if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { + nxt_alert(task, "dup2(%FD, %FD) failed %E", + msg->fd[0], access_log->fd, nxt_errno); + } + } + + nxt_fd_close(msg->fd[0]); + nxt_mp_release(reopen->mem_pool); +} + + +static void +nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_access_log_reopen_t *reopen; + + reopen = data; + + nxt_mp_release(reopen->mem_pool); +} -- cgit From 3f8cf62c03a55b9767f0c75b3df6a1a40252b19a Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Thu, 28 Jul 2022 11:05:04 +0800 Subject: Log: customizable access log format. --- src/nxt_conf_validation.c | 81 +++++++++++++++- src/nxt_http_request.c | 9 +- src/nxt_http_static.c | 5 +- src/nxt_router.h | 4 +- src/nxt_router_access_log.c | 230 ++++++++++++++++++++++---------------------- src/nxt_var.c | 25 ++++- src/nxt_var.h | 8 +- 7 files changed, 232 insertions(+), 130 deletions(-) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 8c532914..3e89d775 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -202,6 +202,8 @@ static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); +static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, void *data); static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); @@ -241,6 +243,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[]; #if (NXT_HAVE_ISOLATION_ROOTFS) static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[]; #endif +static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { @@ -270,7 +273,8 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { .u.object = nxt_conf_vldt_upstream, }, { .name = nxt_string("access_log"), - .type = NXT_CONF_VLDT_STRING, + .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_access_log, }, NXT_CONF_VLDT_END @@ -1205,6 +1209,19 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = { + { + .name = nxt_string("path"), + .type = NXT_CONF_VLDT_STRING, + }, { + .name = nxt_string("format"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_END +}; + + nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt) { @@ -3090,3 +3107,65 @@ nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, return NXT_OK; } + + +typedef struct { + nxt_str_t path; + nxt_str_t format; +} nxt_conf_vldt_access_log_conf_t; + + +static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = { + { + nxt_string("path"), + NXT_CONF_MAP_STR, + offsetof(nxt_conf_vldt_access_log_conf_t, path), + }, + + { + nxt_string("format"), + NXT_CONF_MAP_STR, + offsetof(nxt_conf_vldt_access_log_conf_t, format), + }, +}; + + +static nxt_int_t +nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, + void *data) +{ + nxt_int_t ret; + nxt_conf_vldt_access_log_conf_t conf; + + static nxt_str_t format_str = nxt_string("format"); + + if (nxt_conf_type(value) == NXT_CONF_STRING) { + return NXT_OK; + } + + ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members); + if (ret != NXT_OK) { + return ret; + } + + nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t)); + + ret = nxt_conf_map_object(vldt->pool, value, + nxt_conf_vldt_access_log_map, + nxt_nitems(nxt_conf_vldt_access_log_map), + &conf); + if (ret != NXT_OK) { + return ret; + } + + if (conf.path.length == 0) { + return nxt_conf_vldt_error(vldt, + "The \"path\" string must not be empty."); + } + + if (nxt_is_var(&conf.format)) { + return nxt_conf_vldt_var(vldt, &format_str, &conf.format); + } + + return NXT_OK; +} diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 5f8fd8f7..a16340de 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -791,6 +791,7 @@ nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data) void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) { + nxt_var_t *log_format; nxt_http_proto_t proto; nxt_http_request_t *r; nxt_http_protocol_t protocol; @@ -800,20 +801,22 @@ nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data) r = obj; proto.any = data; - nxt_debug(task, "http request close handler"); - conf = r->conf; if (!r->logged) { r->logged = 1; access_log = conf->socket_conf->router_conf->access_log; + log_format = conf->socket_conf->router_conf->log_format; if (access_log != NULL) { - access_log->handler(task, r, access_log); + access_log->handler(task, r, access_log, log_format); + return; } } + nxt_debug(task, "http request close handler"); + r->proto.any = NULL; if (r->body != NULL && nxt_buf_is_file(r->body) diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c index 19393f2c..0507e038 100644 --- a/src/nxt_http_static.c +++ b/src/nxt_http_static.c @@ -104,7 +104,7 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, cv = nxt_conf_get_array_element_or_itself(acf->share, i); nxt_conf_get_string(cv, &str); - var = nxt_var_compile(&str, mp, rtcf->var_fields, 1); + var = nxt_var_compile(&str, mp, rtcf->var_fields, NXT_VAR_STRZ); if (nxt_slow_path(var == NULL)) { return NXT_ERROR; } @@ -130,7 +130,8 @@ nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_str_t chr, shr; nxt_bool_t is_const; - conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields, 1); + conf->chroot = nxt_var_compile(&acf->chroot, mp, rtcf->var_fields, + NXT_VAR_STRZ); if (nxt_slow_path(conf->chroot == NULL)) { return NXT_ERROR; } diff --git a/src/nxt_router.h b/src/nxt_router.h index 18fb60b0..a6add219 100644 --- a/src/nxt_router.h +++ b/src/nxt_router.h @@ -53,6 +53,7 @@ typedef struct { nxt_lvlhsh_t apps_hash; nxt_router_access_log_t *access_log; + nxt_var_t *log_format; } nxt_router_conf_t; @@ -223,7 +224,8 @@ typedef struct { struct nxt_router_access_log_s { void (*handler)(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log); + nxt_router_access_log_t *access_log, + nxt_var_t *format); nxt_fd_t fd; nxt_str_t path; uint32_t count; diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c index d92e80c3..dc2a6687 100644 --- a/src/nxt_router_access_log.c +++ b/src/nxt_router_access_log.c @@ -10,10 +10,25 @@ #include +typedef struct { + nxt_str_t path; + nxt_str_t format; +} nxt_router_access_log_conf_t; + + +typedef struct { + nxt_str_t text; + nxt_router_access_log_t *access_log; +} nxt_router_access_log_ctx_t; + + static void nxt_router_access_log_writer(nxt_task_t *task, - nxt_http_request_t *r, nxt_router_access_log_t *access_log); -static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, - struct tm *tm, size_t size, const char *format); + nxt_http_request_t *r, nxt_router_access_log_t *access_log, + nxt_var_t *format); +static void nxt_router_access_log_write_ready(nxt_task_t *task, void *obj, + void *data); +static void nxt_router_access_log_write_error(nxt_task_t *task, void *obj, + void *data); static void nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); static void nxt_router_access_log_error(nxt_task_t *task, @@ -26,26 +41,63 @@ static void nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data); +static nxt_conf_map_t nxt_router_access_log_conf[] = { + { + nxt_string("path"), + NXT_CONF_MAP_STR, + offsetof(nxt_router_access_log_conf_t, path), + }, + + { + nxt_string("format"), + NXT_CONF_MAP_STR, + offsetof(nxt_router_access_log_conf_t, format), + }, +}; + + nxt_int_t nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, nxt_conf_value_t *value) { - nxt_str_t path; - nxt_router_t *router; - nxt_router_access_log_t *access_log; + u_char *p; + nxt_int_t ret; + nxt_str_t str; + nxt_var_t *format; + nxt_router_t *router; + nxt_router_access_log_t *access_log; + nxt_router_access_log_conf_t alcf; - router = nxt_router; + static nxt_str_t log_format_str = nxt_string("$remote_addr - - " + "[$time_local] \"$request_line\" $status $body_bytes_sent " + "\"$header_referer\" \"$header_user_agent\""); + + alcf.format = log_format_str; - nxt_conf_get_string(value, &path); + if (nxt_conf_type(value) == NXT_CONF_STRING) { + nxt_conf_get_string(value, &alcf.path); + + } else { + ret = nxt_conf_map_object(rtcf->mem_pool, value, + nxt_router_access_log_conf, + nxt_nitems(nxt_router_access_log_conf), + &alcf); + if (ret != NXT_OK) { + nxt_alert(task, "access log map error"); + return NXT_ERROR; + } + } + + router = nxt_router; access_log = router->access_log; - if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { + if (access_log != NULL && nxt_strstr_eq(&alcf.path, &access_log->path)) { nxt_router_access_log_use(&router->lock, access_log); } else { access_log = nxt_malloc(sizeof(nxt_router_access_log_t) - + path.length); + + alcf.path.length); if (access_log == NULL) { nxt_alert(task, "failed to allocate access log structure"); return NXT_ERROR; @@ -55,14 +107,32 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, access_log->handler = &nxt_router_access_log_writer; access_log->count = 1; - access_log->path.length = path.length; + access_log->path.length = alcf.path.length; access_log->path.start = (u_char *) access_log + sizeof(nxt_router_access_log_t); - nxt_memcpy(access_log->path.start, path.start, path.length); + nxt_memcpy(access_log->path.start, alcf.path.start, alcf.path.length); + } + + str.length = alcf.format.length + 1; + + str.start = nxt_malloc(str.length); + if (str.start == NULL) { + nxt_alert(task, "failed to allocate log format structure"); + return NXT_ERROR; + } + + p = nxt_cpymem(str.start, alcf.format.start, alcf.format.length); + *p = '\n'; + + format = nxt_var_compile(&str, rtcf->mem_pool, rtcf->var_fields, + NXT_VAR_LOGGING); + if (nxt_slow_path(format == NULL)) { + return NXT_ERROR; } rtcf->access_log = access_log; + rtcf->log_format = format; return NXT_OK; } @@ -70,130 +140,56 @@ nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, static void nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, - nxt_router_access_log_t *access_log) + nxt_router_access_log_t *access_log, nxt_var_t *format) { - size_t size; - u_char *buf, *p; - nxt_off_t bytes; - - static nxt_time_string_t date_cache = { - (nxt_atomic_uint_t) -1, - nxt_router_access_log_date, - "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", - nxt_length("31/Dec/1986:19:40:00 +0300"), - NXT_THREAD_TIME_LOCAL, - NXT_THREAD_TIME_SEC, - }; - - size = r->remote->address_length - + 6 /* ' - - [' */ - + date_cache.size - + 3 /* '] "' */ - + r->method->length - + 1 /* space */ - + r->target.length - + 1 /* space */ - + r->version.length - + 2 /* '" ' */ - + 3 /* status */ - + 1 /* space */ - + NXT_OFF_T_LEN - + 2 /* ' "' */ - + (r->referer != NULL ? r->referer->value_length : 1) - + 3 /* '" "' */ - + (r->user_agent != NULL ? r->user_agent->value_length : 1) - + 2 /* '"\n' */ - ; - - buf = nxt_mp_nget(r->mem_pool, size); - if (nxt_slow_path(buf == NULL)) { + nxt_int_t ret; + nxt_router_access_log_ctx_t *ctx; + + ctx = nxt_mp_get(r->mem_pool, sizeof(nxt_router_access_log_ctx_t)); + if (nxt_slow_path(ctx == NULL)) { return; } - p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), - r->remote->address_length); + ctx->access_log = access_log; - p = nxt_cpymem(p, " - - [", 6); + if (nxt_var_is_const(format)) { + nxt_var_raw(format, &ctx->text); - p = nxt_thread_time_string(task->thread, &date_cache, p); - - p = nxt_cpymem(p, "] \"", 3); - - if (r->method->length != 0) { - p = nxt_cpymem(p, r->method->start, r->method->length); - - if (r->target.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->target.start, r->target.length); - - if (r->version.length != 0) { - *p++ = ' '; - p = nxt_cpymem(p, r->version.start, r->version.length); - } - } + nxt_router_access_log_write_ready(task, r, ctx); } else { - *p++ = '-'; - } - - p = nxt_cpymem(p, "\" ", 2); - - p = nxt_sprintf(p, p + 3, "%03d", r->status); - - *p++ = ' '; - - bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); - - p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); - - p = nxt_cpymem(p, " \"", 2); - - if (r->referer != NULL) { - p = nxt_cpymem(p, r->referer->value, r->referer->value_length); + ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return; + } - } else { - *p++ = '-'; - } + nxt_var_query(task, r->var_query, format, &ctx->text); + nxt_var_query_resolve(task, r->var_query, ctx, + nxt_router_access_log_write_ready, + nxt_router_access_log_write_error); + } +} - p = nxt_cpymem(p, "\" \"", 3); - if (r->user_agent != NULL) { - p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); +static void +nxt_router_access_log_write_ready(nxt_task_t *task, void *obj, void *data) +{ + nxt_http_request_t *r; + nxt_router_access_log_ctx_t *ctx; - } else { - *p++ = '-'; - } + r = obj; + ctx = data; - p = nxt_cpymem(p, "\"\n", 2); + nxt_fd_write(ctx->access_log->fd, ctx->text.start, ctx->text.length); - nxt_fd_write(access_log->fd, buf, p - buf); + nxt_http_request_close_handler(task, r, r->proto.any); } -static u_char * -nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, - size_t size, const char *format) +static void +nxt_router_access_log_write_error(nxt_task_t *task, void *obj, void *data) { - u_char sign; - time_t gmtoff; - - static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - gmtoff = nxt_timezone(tm) / 60; - - if (gmtoff < 0) { - gmtoff = -gmtoff; - sign = '-'; - - } else { - sign = '+'; - } - return nxt_sprintf(buf, buf + size, format, - tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, - tm->tm_hour, tm->tm_min, tm->tm_sec, - sign, gmtoff / 60, gmtoff % 60); } diff --git a/src/nxt_var.c b/src/nxt_var.c index d3057764..f55a2d30 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -9,7 +9,7 @@ struct nxt_var_s { size_t length; nxt_uint_t vars; - uint8_t strz; /* 1 bit */ + nxt_var_flags_t flags; u_char data[]; /* @@ -331,11 +331,12 @@ nxt_var_index_init(void) nxt_var_t * nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, - nxt_bool_t strz) + nxt_var_flags_t flags) { u_char *p, *end, *next, *src; size_t size; uint32_t index; + nxt_bool_t strz; nxt_var_t *var; nxt_str_t part; nxt_uint_t n; @@ -343,6 +344,8 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, nxt_var_sub_t *subs; nxt_var_decl_t *decl; + strz = (flags & NXT_VAR_STRZ) != 0; + n = 0; p = str->start; @@ -368,7 +371,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, var->length = str->length; var->vars = n; - var->strz = strz; + var->flags = flags; subs = nxt_var_subs(var); src = nxt_var_raw_start(var); @@ -568,6 +571,7 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, size_t length, last, next; nxt_str_t *value, **part; nxt_uint_t i; + nxt_bool_t strz, logging; nxt_array_t parts; nxt_var_sub_t *subs; @@ -583,6 +587,9 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, nxt_memzero(&parts, sizeof(nxt_array_t)); nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *)); + strz = (var->flags & NXT_VAR_STRZ) != 0; + logging = (var->flags & NXT_VAR_LOGGING) != 0; + subs = nxt_var_subs(var); length = var->length; @@ -601,9 +608,13 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, *part = value; length += value->length - subs[i].length; + + if (logging && value->start == NULL) { + length += 1; + } } - p = nxt_mp_nget(query->pool, length + var->strz); + p = nxt_mp_nget(query->pool, length + strz); if (nxt_slow_path(p == NULL)) { goto fail; } @@ -625,6 +636,10 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, p = nxt_cpymem(p, part[i]->start, part[i]->length); + if (logging && part[i]->start == NULL) { + *p++ = '-'; + } + last = next + subs[i].length; } @@ -632,7 +647,7 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, p = nxt_cpymem(p, &src[last], var->length - last); } - if (var->strz) { + if (strz) { *p = '\0'; } diff --git a/src/nxt_var.h b/src/nxt_var.h index 3c38be36..cc7ff502 100644 --- a/src/nxt_var.h +++ b/src/nxt_var.h @@ -32,6 +32,12 @@ typedef struct { } nxt_var_field_t; +typedef enum { + NXT_VAR_STRZ = 1 << 0, + NXT_VAR_LOGGING = 1 << 1, +} nxt_var_flags_t; + + nxt_inline nxt_bool_t nxt_is_var(nxt_str_t *str) { @@ -45,7 +51,7 @@ nxt_int_t nxt_var_index_init(void); nxt_var_field_t *nxt_var_field_get(nxt_array_t *fields, uint16_t index); nxt_var_t *nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, - nxt_bool_t strz); + nxt_var_flags_t flags); nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error); nxt_bool_t nxt_var_is_const(nxt_var_t *var); -- cgit From 2c0888f69c247c82fc02ba207aa19fa00acf4b5e Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 19 Jun 2022 12:48:01 +0200 Subject: Including iff it exists. With NXT_HAVE_PIVOT_ROOT, we had issues in MacOS. Headers should normally be included unconditionally, except of course if they don't exist. This fixes part of the #737 issue on GitHub. --- src/nxt_isolation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 7bb8dbfd..5a0714ff 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -7,7 +7,7 @@ #include #include -#if (NXT_HAVE_PIVOT_ROOT) +#if (NXT_HAVE_MNTENT_H) #include #endif -- cgit From 418bc208d08dbc4a0a3511e503c946ab6ac71c39 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 2 Aug 2022 19:39:55 +0200 Subject: Rejecting non-Linux pivot_root(2). Some non-Linux systems implement pivot_root(2), even if they don't document that. An example is MacOS: $ grepc pivot_root / 2>/dev/null .../sys/sysproto.h:3012: int pivot_root(struct proc *, struct pivot_root_args *, int *); Since the prototype of the syscall differs from that of Linux, we can't use that syscall. Let's make sure the test only detects pivot_root(2) under Linux. Also, rename the feature macro to make clear that it's only about Linux's pivot_root(2). This closes #737 issue on GitHub. --- src/nxt_isolation.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 5a0714ff..796da4c6 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -45,7 +45,7 @@ static int nxt_cdecl nxt_isolation_mount_compare(const void *v1, const void *v2); static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process); -#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) +#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *rootfs); static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task, const char *rootfs); @@ -752,7 +752,7 @@ undo: } -#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) +#if (NXT_HAVE_LINUX_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) @@ -1007,7 +1007,7 @@ nxt_pivot_root(const char *new_root, const char *old_root) } -#else /* !(NXT_HAVE_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */ +#else /* !(NXT_HAVE_LINUX_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */ nxt_int_t -- cgit From c7543311ca70c0855721a67ac8b0408ba35f5378 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 31 Mar 2022 23:12:21 +0200 Subject: Python: supporting UNIX sockets. This closes #635 issue on GitHub. --- src/python/nxt_python_asgi.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 91af8f4b..172fd60b 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -30,6 +30,8 @@ static void nxt_py_asgi_close_handler(nxt_unit_request_info_t *req); static PyObject *nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req); static PyObject *nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port); +static PyObject *nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, + uint8_t len, uint16_t port); static PyObject *nxt_py_asgi_create_header(nxt_unit_field_t *f); static PyObject *nxt_py_asgi_create_subprotocols(nxt_unit_field_t *f); @@ -663,7 +665,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, query_string, v) Py_DECREF(v); - v = nxt_py_asgi_create_address(&r->remote, r->remote_length, 0); + v = nxt_py_asgi_create_ip_address(&r->remote, r->remote_length, 0); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'client' pair"); goto fail; @@ -735,6 +737,48 @@ fail: static PyObject * nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) +{ + size_t prefix_len; + nxt_str_t addr; + PyObject *pair, *v; + + addr.length = len; + addr.start = nxt_unit_sptr_get(sptr); + + prefix_len = nxt_length("unix:"); + if (!nxt_str_start(&addr, "unix:", prefix_len)) { + return nxt_py_asgi_create_ip_address(sptr, len, port); + } + +#if NXT_HAVE_UNIX_DOMAIN + pair = PyTuple_New(2); + if (nxt_slow_path(pair == NULL)) { + return NULL; + } + + addr.start += prefix_len; + addr.length -= prefix_len; + + v = PyString_FromStringAndSize((const char *) addr.start, addr.length); + if (nxt_slow_path(v == NULL)) { + Py_DECREF(pair); + + return NULL; + } + + PyTuple_SET_ITEM(pair, 0, v); + PyTuple_SET_ITEM(pair, 1, Py_None); + + return pair; + +#else + return NULL; +#endif +} + + +static PyObject * +nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port) { char *p, *s; PyObject *pair, *v; -- cgit From 900828cc4b92e95b4810c00df9759ab9a07429c7 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Thu, 17 Feb 2022 12:33:46 +0000 Subject: Fixing isolated process PID manipulation. Registering an isolated PID in the global PID hash is wrong because it can be duplicated. Isolated processes are stored only in the children list until the response for the WHOAMI message is processed and the global PID is discovered. To remove isolated siblings, a pointer to the children list is introduced in the nxt_process_init_t struct. This closes #633 issue on GitHub. --- src/nxt_application.c | 75 ++++++++++++++++++++++++++++++++++++++++----------- src/nxt_process.c | 34 ++++++++++++++++++++--- src/nxt_process.h | 2 ++ src/nxt_runtime.c | 13 +++++---- 4 files changed, 100 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/nxt_application.c b/src/nxt_application.c index 594574b1..556f1ffb 100644 --- a/src/nxt_application.c +++ b/src/nxt_application.c @@ -23,6 +23,13 @@ #endif +#ifdef WCOREDUMP +#define NXT_WCOREDUMP(s) WCOREDUMP(s) +#else +#define NXT_WCOREDUMP(s) 0 +#endif + + typedef struct { nxt_app_type_t type; nxt_str_t version; @@ -636,6 +643,8 @@ nxt_proto_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) process->data.app = nxt_app_conf; process->stream = msg->port_msg.stream; + init->siblings = &nxt_proto_children; + ret = nxt_process_start(task, process); if (nxt_slow_path(ret == NXT_ERROR)) { nxt_process_use(task, process, -1); @@ -711,15 +720,19 @@ nxt_proto_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid, pid); - nxt_runtime_process_remove(task->thread->runtime, process); - process->pid = pid; - nxt_runtime_process_add(task, process); - } else { nxt_debug(task, "app process %PI is created", isolated_pid); } + + if (!process->registered) { + nxt_assert(!nxt_queue_is_empty(&process->ports)); + + nxt_runtime_process_add(task, process); + + nxt_port_use(task, nxt_process_port_first(process), -1); + } } @@ -753,7 +766,11 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data) int status; nxt_err_t err; nxt_pid_t pid; + nxt_port_t *port; nxt_process_t *process; + nxt_runtime_t *rt; + + rt = task->thread->runtime; nxt_debug(task, "proto sigchld handler signo:%d (%s)", (int) (uintptr_t) obj, data); @@ -783,32 +800,58 @@ nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data) return; } + process = nxt_proto_process_remove(task, pid); + if (WTERMSIG(status)) { -#ifdef WCOREDUMP - nxt_alert(task, "app process (isolated %PI) exited on signal %d%s", - pid, WTERMSIG(status), - WCOREDUMP(status) ? " (core dumped)" : ""); -#else - nxt_alert(task, "app process (isolated %PI) exited on signal %d", - pid, WTERMSIG(status)); -#endif + if (rt->is_pid_isolated) { + nxt_alert(task, "app process %PI (isolated %PI) " + "exited on signal %d%s", + process != NULL ? process->pid : 0, + pid, WTERMSIG(status), + NXT_WCOREDUMP(status) ? " (core dumped)" : ""); + + } else { + nxt_alert(task, "app process %PI exited on signal %d%s", + pid, WTERMSIG(status), + NXT_WCOREDUMP(status) ? " (core dumped)" : ""); + } } else { - nxt_trace(task, "app process (isolated %PI) exited with code %d", - pid, WEXITSTATUS(status)); + if (rt->is_pid_isolated) { + nxt_trace(task, "app process %PI (isolated %PI) " + "exited with code %d", + process != NULL ? process->pid : 0, + pid, WEXITSTATUS(status)); + + } else { + nxt_trace(task, "app process %PI exited with code %d", + pid, WEXITSTATUS(status)); + } } - process = nxt_proto_process_remove(task, pid); if (process == NULL) { continue; } + if (process->registered) { + port = NULL; + + } else { + nxt_assert(!nxt_queue_is_empty(&process->ports)); + + port = nxt_process_port_first(process); + } + if (process->state != NXT_PROCESS_STATE_CREATING) { nxt_port_remove_notify_others(task, process); } nxt_process_close_ports(task, process); + if (port != NULL) { + nxt_port_use(task, port, -1); + } + if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) { nxt_process_quit(task, 0); return; @@ -1122,7 +1165,7 @@ nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process) break; default: - nxt_debug(task, "process (isolated %PI) failed to add", + nxt_alert(task, "process (isolated %PI) failed to add", process->isolated_pid); break; } diff --git a/src/nxt_process.c b/src/nxt_process.c index 98636bbe..738a03bf 100644 --- a/src/nxt_process.c +++ b/src/nxt_process.c @@ -296,6 +296,16 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process) } nxt_runtime_process_loop; + if (init->siblings != NULL) { + nxt_queue_each(p, init->siblings, nxt_process_t, link) { + + nxt_debug(task, "remove sibling process %PI", p->pid); + + nxt_process_close_ports(task, p); + + } nxt_queue_loop; + } + return NXT_OK; } @@ -303,8 +313,9 @@ nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process) static nxt_pid_t nxt_process_create(nxt_task_t *task, nxt_process_t *process) { - nxt_int_t ret; - nxt_pid_t pid; + nxt_int_t ret; + nxt_pid_t pid; + nxt_runtime_t *rt; #if (NXT_HAVE_CLONE) pid = nxt_clone(SIGCHLD | process->isolation.clone.flags); @@ -352,7 +363,20 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process) process->pid = pid; process->isolated_pid = pid; - nxt_runtime_process_add(task, process); + rt = task->thread->runtime; + + if (rt->is_pid_isolated) { + /* + * Do not register process in runtime with isolated pid. + * Only global pid can be the key to avoid clash. + */ + nxt_assert(!nxt_queue_is_empty(&process->ports)); + + nxt_port_use(task, nxt_process_port_first(process), 1); + + } else { + nxt_runtime_process_add(task, process); + } return pid; } @@ -960,6 +984,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) { nxt_port_t *port; + nxt_process_use(task, process, 1); + nxt_process_port_each(process, port) { nxt_port_close(task, port); @@ -967,6 +993,8 @@ nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) nxt_runtime_port_remove(task, port); } nxt_process_port_loop; + + nxt_process_use(task, process, -1); } diff --git a/src/nxt_process.h b/src/nxt_process.h index 642c3419..15fd4e7f 100644 --- a/src/nxt_process.h +++ b/src/nxt_process.h @@ -148,6 +148,8 @@ typedef struct { const nxt_port_handlers_t *port_handlers; const nxt_sig_event_t *signals; + + nxt_queue_t *siblings; } nxt_process_init_t; diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c index 46955f1c..d9c9f2ef 100644 --- a/src/nxt_runtime.c +++ b/src/nxt_runtime.c @@ -1408,6 +1408,7 @@ nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process) nxt_assert(process->use_count == 0); nxt_assert(process->registered == 0); + nxt_assert(nxt_queue_is_empty(&process->ports)); nxt_port_mmaps_destroy(&process->incoming, 1); @@ -1579,11 +1580,11 @@ nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process) process->registered = 1; - nxt_thread_log_debug("process %PI added", process->pid); + nxt_debug(task, "process %PI added", process->pid); break; default: - nxt_thread_log_debug("process %PI failed to add", process->pid); + nxt_alert(task, "process %PI failed to add", process->pid); break; } @@ -1597,6 +1598,8 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) nxt_pid_t pid; nxt_lvlhsh_query_t lhq; + nxt_assert(process->registered != 0); + pid = process->pid; nxt_runtime_process_lhq_pid(&lhq, &pid); @@ -1608,9 +1611,9 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) { case NXT_OK: - rt->nprocesses--; + nxt_assert(lhq.value == process); - process = lhq.value; + rt->nprocesses--; process->registered = 0; @@ -1618,7 +1621,7 @@ nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) break; default: - nxt_thread_log_debug("process %PI remove failed", pid); + nxt_thread_log_alert("process %PI remove failed", pid); break; } -- cgit From 22c510066686d4f5c8cecfeb54c0b958b5f5bb3f Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 3 Aug 2022 14:42:49 +0200 Subject: Removed dead code. nxt_sockaddr_ntop() stopped being used in commit (git) 029942f4eb71. It has been replaced mostly by nxt_sockaddr_text(). commit 029942f4eb7196c2cff0d0e26bc6ff274138f7d8 Author: Igor Sysoev Date: Wed Feb 22 15:09:59 2017 +0300 I/O operations refactoring. nxt_job_sockaddr_parse() stopped being used in commit (git) 794248090a74. commit 794248090a74f31cbfcf24ea8c835df2d4d21073 Author: Igor Sysoev Date: Wed Mar 4 14:04:08 2020 +0300 Legacy upstream code removed. Also, remove functions and types used only by those two functions: nxt_job_sockaddr_unix_parse() nxt_job_sockaddr_inet6_parse() nxt_job_sockaddr_inet_parse() nxt_job_sockaddr_parse_t nxt_job_resolve() nxt_job_resolve_t --- src/nxt_job_resolve.c | 132 ---------------- src/nxt_job_resolve.h | 29 ---- src/nxt_main.h | 1 - src/nxt_sockaddr.c | 412 -------------------------------------------------- src/nxt_sockaddr.h | 12 -- 5 files changed, 586 deletions(-) delete mode 100644 src/nxt_job_resolve.c delete mode 100644 src/nxt_job_resolve.h (limited to 'src') diff --git a/src/nxt_job_resolve.c b/src/nxt_job_resolve.c deleted file mode 100644 index 0f1fb9aa..00000000 --- a/src/nxt_job_resolve.c +++ /dev/null @@ -1,132 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#include - - -void -nxt_job_resolve(nxt_job_resolve_t *jbr) -{ - int err; - u_char *host; - size_t length; - nxt_mp_t *mp; - nxt_uint_t n; - nxt_sockaddr_t *sa; - struct addrinfo hint, *res, *r; - nxt_work_handler_t handler; - - #define NXT_BUFSIZE 64 - u_char buf[NXT_BUFSIZE]; - - handler = jbr->error_handler; - res = NULL; - - length = jbr->name.length + 1; - - if (nxt_fast_path(length <= NXT_BUFSIZE)) { - host = buf; - - } else { - host = nxt_mp_alloc(jbr->job.mem_pool, length); - if (nxt_slow_path(host == NULL)) { - goto fail; - } - } - - nxt_cpystrn(host, jbr->name.start, length); - - nxt_memzero(&hint, sizeof(struct addrinfo)); - hint.ai_socktype = SOCK_STREAM; - - err = getaddrinfo((char *) host, NULL, &hint, &res); - - if (err != 0) { - nxt_thread_log_error(jbr->log_level, - "getaddrinfo(\"%s\") failed (%d: %s)", - host, err, gai_strerror(err)); - goto fail; - } - - n = 0; - for (r = res; r != NULL; r = r->ai_next) { - - switch (r->ai_addr->sa_family) { -#if (NXT_INET6) - case AF_INET6: -#endif - case AF_INET: - n++; - break; - - default: - break; - } - } - - jbr->count = n; - mp = jbr->job.mem_pool; - - jbr->sockaddrs = nxt_mp_alloc(mp, n * sizeof(nxt_sockaddr_t *)); - if (nxt_slow_path(jbr->sockaddrs == NULL)) { - goto fail; - } - - n = 0; - for (r = res; r != NULL; r = r->ai_next) { - - switch (r->ai_addr->sa_family) { -#if (NXT_INET6) - case AF_INET6: - length = NXT_INET6_ADDR_STR_LEN; - break; -#endif - case AF_INET: - length = NXT_INET_ADDR_STR_LEN; - break; - - default: - continue; - } - - sa = nxt_sockaddr_create(mp, r->ai_addr, r->ai_addrlen, length); - if (nxt_slow_path(sa == NULL)) { - goto fail; - } - - jbr->sockaddrs[n++] = sa; - - if (jbr->port != 0) { - - switch (sa->u.sockaddr.sa_family) { - case AF_INET: - sa->u.sockaddr_in.sin_port = jbr->port; - break; -#if (NXT_INET6) - case AF_INET6: - sa->u.sockaddr_in6.sin6_port = jbr->port; - break; -#endif - default: - break; - } - } - } - - handler = jbr->ready_handler; - -fail: - - if (nxt_fast_path(res != NULL)) { - freeaddrinfo(res); - } - - if (host != buf) { - nxt_mp_free(jbr->job.mem_pool, host); - } - - nxt_job_return(jbr->job.task, &jbr->job, handler); -} diff --git a/src/nxt_job_resolve.h b/src/nxt_job_resolve.h deleted file mode 100644 index fef55b99..00000000 --- a/src/nxt_job_resolve.h +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#ifndef _NXT_JOB_RESOLVE_H_INCLUDED_ -#define _NXT_JOB_RESOLVE_H_INCLUDED_ - - -typedef struct { - nxt_job_t job; - nxt_str_t name; - - uint32_t log_level; /* 4 bits */ - in_port_t port; - uint16_t count; - - nxt_sockaddr_t **sockaddrs; - - nxt_work_handler_t ready_handler; - nxt_work_handler_t error_handler; -} nxt_job_resolve_t; - - -void nxt_job_resolve(nxt_job_resolve_t *jbr); - - -#endif /* _NXT_JOB_RESOLVE_H_INCLUDED_ */ diff --git a/src/nxt_main.h b/src/nxt_main.h index 7f812568..dca4b6dc 100644 --- a/src/nxt_main.h +++ b/src/nxt_main.h @@ -146,7 +146,6 @@ typedef void (*nxt_event_conn_handler_t)(nxt_thread_t *thr, nxt_conn_t *c); #include #include -#include #include #include diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index e8dee83a..8220590e 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -15,10 +15,6 @@ static nxt_sockaddr_t *nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr); static nxt_sockaddr_t *nxt_sockaddr_inet6_parse(nxt_mp_t *mp, nxt_str_t *addr); static nxt_sockaddr_t *nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr); -static nxt_int_t nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs); -static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs); -static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs); - nxt_sockaddr_t * nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls) @@ -433,82 +429,6 @@ nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2) } -size_t -nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, u_char *end, nxt_bool_t port) -{ - u_char *p; - - switch (sa->u.sockaddr.sa_family) { - - case AF_INET: - p = (u_char *) &sa->u.sockaddr_in.sin_addr; - - if (port) { - p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud:%d", - p[0], p[1], p[2], p[3], - ntohs(sa->u.sockaddr_in.sin_port)); - } else { - p = nxt_sprintf(buf, end, "%ud.%ud.%ud.%ud", - p[0], p[1], p[2], p[3]); - } - - return p - buf; - -#if (NXT_INET6) - - case AF_INET6: - p = buf; - - if (port) { - *p++ = '['; - } - - p = nxt_inet6_ntop(sa->u.sockaddr_in6.sin6_addr.s6_addr, p, end); - - if (port) { - p = nxt_sprintf(p, end, "]:%d", - ntohs(sa->u.sockaddr_in6.sin6_port)); - } - - return p - buf; -#endif - -#if (NXT_HAVE_UNIX_DOMAIN) - - case AF_UNIX: - -#if (NXT_LINUX) - - p = (u_char *) sa->u.sockaddr_un.sun_path; - - if (p[0] == '\0') { - size_t length; - - /* Linux abstract socket address has no trailing zero. */ - - length = sa->socklen - offsetof(struct sockaddr_un, sun_path) - 1; - p = nxt_sprintf(buf, end, "unix:\\0%*s", length, p + 1); - - } else { - p = nxt_sprintf(buf, end, "unix:%s", p); - } - -#else /* !(NXT_LINUX) */ - - p = nxt_sprintf(buf, end, "unix:%s", sa->u.sockaddr_un.sun_path); - -#endif - - return p - buf; - -#endif /* NXT_HAVE_UNIX_DOMAIN */ - - default: - return 0; - } -} - - #if (NXT_INET6) static u_char * @@ -849,338 +769,6 @@ nxt_sockaddr_inet_parse(nxt_mp_t *mp, nxt_str_t *addr) } -void -nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs) -{ - u_char *p; - size_t length; - nxt_int_t ret; - nxt_work_handler_t handler; - - nxt_job_set_name(&jbs->resolve.job, "job sockaddr parse"); - - length = jbs->addr.length; - p = jbs->addr.start; - - if (length > 6 && nxt_memcmp(p, "unix:", 5) == 0) { - ret = nxt_job_sockaddr_unix_parse(jbs); - - } else if (length != 0 && *p == '[') { - ret = nxt_job_sockaddr_inet6_parse(jbs); - - } else { - ret = nxt_job_sockaddr_inet_parse(jbs); - } - - switch (ret) { - - case NXT_OK: - handler = jbs->resolve.ready_handler; - break; - - case NXT_ERROR: - handler = jbs->resolve.error_handler; - break; - - default: /* NXT_AGAIN */ - return; - } - - nxt_job_return(jbs->resolve.job.task, &jbs->resolve.job, handler); -} - - -static nxt_int_t -nxt_job_sockaddr_unix_parse(nxt_job_sockaddr_parse_t *jbs) -{ -#if (NXT_HAVE_UNIX_DOMAIN) - size_t length, socklen; - u_char *path; - nxt_mp_t *mp; - nxt_sockaddr_t *sa; - - /* - * Actual sockaddr_un length can be lesser or even larger than defined - * struct sockaddr_un length (see comment in nxt_socket.h). So - * limit maximum Unix domain socket address length by defined sun_path[] - * length because some OSes accept addresses twice larger than defined - * struct sockaddr_un. Also reserve space for a trailing zero to avoid - * ambiguity, since many OSes accept Unix domain socket addresses - * without a trailing zero. - */ - const size_t max_len = sizeof(struct sockaddr_un) - - offsetof(struct sockaddr_un, sun_path) - 1; - - /* cutting "unix:" */ - length = jbs->addr.length - 5; - path = jbs->addr.start + 5; - - if (length > max_len) { - nxt_thread_log_error(jbs->resolve.log_level, - "unix domain socket \"%V\" name is too long", - &jbs->addr); - return NXT_ERROR; - } - - socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; - -#if (NXT_LINUX) - - /* - * Linux unix(7): - * - * abstract: an abstract socket address is distinguished by the fact - * that sun_path[0] is a null byte ('\0'). The socket's address in - * this namespace is given by the additional bytes in sun_path that - * are covered by the specified length of the address structure. - * (Null bytes in the name have no special significance.) - */ - if (path[0] == '\0') { - socklen--; - } - -#endif - - mp = jbs->resolve.job.mem_pool; - - jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); - - if (nxt_fast_path(jbs->resolve.sockaddrs != NULL)) { - sa = nxt_sockaddr_alloc(mp, socklen, jbs->addr.length); - - if (nxt_fast_path(sa != NULL)) { - jbs->resolve.count = 1; - jbs->resolve.sockaddrs[0] = sa; - - sa->u.sockaddr_un.sun_family = AF_UNIX; - nxt_memcpy(sa->u.sockaddr_un.sun_path, path, length); - - return NXT_OK; - } - } - - return NXT_ERROR; - -#else /* !(NXT_HAVE_UNIX_DOMAIN) */ - - nxt_thread_log_error(jbs->resolve.log_level, - "unix domain socket \"%V\" is not supported", - &jbs->addr); - return NXT_ERROR; - -#endif -} - - -static nxt_int_t -nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs) -{ -#if (NXT_INET6) - u_char *p, *addr, *addr_end; - size_t length; - nxt_mp_t *mp; - nxt_int_t port; - nxt_sockaddr_t *sa; - struct in6_addr *in6_addr; - - length = jbs->addr.length - 1; - addr = jbs->addr.start + 1; - - addr_end = nxt_memchr(addr, ']', length); - - if (addr_end == NULL) { - goto invalid_address; - } - - mp = jbs->resolve.job.mem_pool; - - jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); - - if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) { - return NXT_ERROR; - } - - sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), - NXT_INET6_ADDR_STR_LEN); - - if (nxt_slow_path(sa == NULL)) { - return NXT_ERROR; - } - - jbs->resolve.count = 1; - jbs->resolve.sockaddrs[0] = sa; - - in6_addr = &sa->u.sockaddr_in6.sin6_addr; - - if (nxt_inet6_addr(in6_addr, addr, addr_end - addr) != NXT_OK) { - goto invalid_address; - } - - p = addr_end + 1; - length = (addr + length) - p; - - if (length == 0) { - jbs->no_port = 1; - port = jbs->resolve.port; - goto found; - } - - if (*p == ':') { - port = nxt_int_parse(p + 1, length - 1); - - if (port >= 1 && port <= 65535) { - port = htons((in_port_t) port); - goto found; - } - } - - nxt_thread_log_error(jbs->resolve.log_level, - "invalid port in \"%V\"", &jbs->addr); - - return NXT_ERROR; - -found: - - sa->u.sockaddr_in6.sin6_family = AF_INET6; - sa->u.sockaddr_in6.sin6_port = (in_port_t) port; - - if (IN6_IS_ADDR_UNSPECIFIED(in6_addr)) { - jbs->wildcard = 1; - } - - return NXT_OK; - -invalid_address: - - nxt_thread_log_error(jbs->resolve.log_level, - "invalid IPv6 address in \"%V\"", &jbs->addr); - return NXT_ERROR; - -#else - - nxt_thread_log_error(jbs->resolve.log_level, - "IPv6 socket \"%V\" is not supported", &jbs->addr); - return NXT_ERROR; - -#endif -} - - -static nxt_int_t -nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs) -{ - u_char *p, *host; - size_t length; - nxt_mp_t *mp; - nxt_int_t port; - in_addr_t addr; - nxt_sockaddr_t *sa; - - addr = INADDR_ANY; - - length = jbs->addr.length; - host = jbs->addr.start; - - p = nxt_memchr(host, ':', length); - - if (p == NULL) { - - /* single value port, address, or host name */ - - port = nxt_int_parse(host, length); - - if (port > 0) { - if (port > 65535) { - goto invalid_port; - } - - /* "*:XX" */ - port = htons((in_port_t) port); - jbs->resolve.port = (in_port_t) port; - - } else { - jbs->no_port = 1; - - addr = nxt_inet_addr(host, length); - - if (addr == INADDR_NONE) { - jbs->resolve.name.length = length; - jbs->resolve.name.start = host; - - nxt_job_resolve(&jbs->resolve); - return NXT_AGAIN; - } - - /* "x.x.x.x" */ - port = jbs->resolve.port; - } - - } else { - - /* x.x.x.x:XX or host:XX */ - - p++; - length = (host + length) - p; - port = nxt_int_parse(p, length); - - if (port < 1 || port > 65535) { - goto invalid_port; - } - - port = htons((in_port_t) port); - - length = (p - 1) - host; - - if (length != 1 || host[0] != '*') { - addr = nxt_inet_addr(host, length); - - if (addr == INADDR_NONE) { - jbs->resolve.name.length = length; - jbs->resolve.name.start = host; - jbs->resolve.port = (in_port_t) port; - - nxt_job_resolve(&jbs->resolve); - return NXT_AGAIN; - } - - /* "x.x.x.x:XX" */ - } - } - - mp = jbs->resolve.job.mem_pool; - - jbs->resolve.sockaddrs = nxt_mp_alloc(mp, sizeof(void *)); - if (nxt_slow_path(jbs->resolve.sockaddrs == NULL)) { - return NXT_ERROR; - } - - sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), - NXT_INET_ADDR_STR_LEN); - - if (nxt_fast_path(sa != NULL)) { - jbs->resolve.count = 1; - jbs->resolve.sockaddrs[0] = sa; - - jbs->wildcard = (addr == INADDR_ANY); - - sa->u.sockaddr_in.sin_family = AF_INET; - sa->u.sockaddr_in.sin_port = (in_port_t) port; - sa->u.sockaddr_in.sin_addr.s_addr = addr; - - return NXT_OK; - } - - return NXT_ERROR; - -invalid_port: - - nxt_thread_log_error(jbs->resolve.log_level, - "invalid port in \"%V\"", &jbs->addr); - - return NXT_ERROR; -} - - in_addr_t nxt_inet_addr(u_char *buf, size_t length) { diff --git a/src/nxt_sockaddr.h b/src/nxt_sockaddr.h index a8f1b393..0f96f6dd 100644 --- a/src/nxt_sockaddr.h +++ b/src/nxt_sockaddr.h @@ -58,15 +58,6 @@ struct nxt_sockaddr_s { }; -typedef struct { - nxt_job_resolve_t resolve; - nxt_str_t addr; - - uint8_t wildcard; /* 1 bit */ - uint8_t no_port; /* 1 bit */ -} nxt_job_sockaddr_parse_t; - - nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_socket_t *ls); void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c); @@ -88,12 +79,9 @@ NXT_EXPORT void nxt_sockaddr_text(nxt_sockaddr_t *sa); NXT_EXPORT uint32_t nxt_sockaddr_port_number(nxt_sockaddr_t *sa); NXT_EXPORT nxt_bool_t nxt_sockaddr_cmp(nxt_sockaddr_t *sa1, nxt_sockaddr_t *sa2); -NXT_EXPORT size_t nxt_sockaddr_ntop(nxt_sockaddr_t *sa, u_char *buf, - u_char *end, nxt_bool_t port); NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse(nxt_mp_t *mp, nxt_str_t *addr); NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_parse_optport(nxt_mp_t *mp, nxt_str_t *addr); -NXT_EXPORT void nxt_job_sockaddr_parse(nxt_job_sockaddr_parse_t *jbs); NXT_EXPORT in_addr_t nxt_inet_addr(u_char *buf, size_t len); #if (NXT_INET6) NXT_EXPORT nxt_int_t nxt_inet6_addr(struct in6_addr *in6_addr, u_char *buf, -- cgit From c1ae86e9301b2af332baa6d3ce2164f3e52d0f1d Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 16 Aug 2022 03:11:36 +0100 Subject: Fixed UNIX sockets support for ASGI. This change was forgotten in the original implementation 282123ba4f7b. --- src/python/nxt_python_asgi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c index 172fd60b..4ad0857d 100644 --- a/src/python/nxt_python_asgi.c +++ b/src/python/nxt_python_asgi.c @@ -665,7 +665,7 @@ nxt_py_asgi_create_http_scope(nxt_unit_request_info_t *req) SET_ITEM(scope, query_string, v) Py_DECREF(v); - v = nxt_py_asgi_create_ip_address(&r->remote, r->remote_length, 0); + v = nxt_py_asgi_create_address(&r->remote, r->remote_length, 0); if (nxt_slow_path(v == NULL)) { nxt_unit_req_alert(req, "Python failed to create 'client' pair"); goto fail; -- cgit From 1c2f070ee226256a05ced1eaae08196a375a53b6 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 22 Jun 2022 13:33:05 +0200 Subject: Fixed include guard. For consistency, use the same pattern as in the rest of the project. --- src/nxt_isolation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_isolation.h b/src/nxt_isolation.h index 88a5f9e1..b1bfc33c 100644 --- a/src/nxt_isolation.h +++ b/src/nxt_isolation.h @@ -2,8 +2,8 @@ * Copyright (C) NGINX, Inc. */ -#ifndef _NXT_ISOLATION_H_ -#define _NXT_ISOLATION_H_ +#ifndef _NXT_ISOLATION_H_INCLUDED_ +#define _NXT_ISOLATION_H_INCLUDED_ nxt_int_t nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, @@ -15,4 +15,4 @@ nxt_int_t nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_int_t nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process); #endif -#endif /* _NXT_ISOLATION_H_ */ +#endif /* _NXT_ISOLATION_H_INCLUDED_ */ -- cgit From d8e0768a5bae991b96328f469b8e27d8a51da9d6 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 28 Jul 2022 16:10:32 +0200 Subject: Fixed support for abstract Unix sockets. Unix domain sockets are normally backed by files in the filesystem. This has historically been problematic when closing and opening again such sockets, since SO_REUSEADDR is ignored for Unix sockets (POSIX left the behavior of SO_REUSEADDR as implementation-defined, and most --if not all-- implementations decided to just ignore this flag). Many solutions are available for this problem, but all of them have important caveats: - unlink(2) the file when it's not needed anymore. This is not easy, because the process that controls the fd may not be the same process that created the file, and may not have file permissions to remove it. Further solutions can be applied to that caveat: - unlink(2) the file right after creation. This will remove the pathname from the filesystem without closing the socket (it will continue to live until the last fd is closed). This is not useful for us, since we need the pathname of the socket as its interface. - chown(2) or chmod(2) the directory that contains the socket. For removing a file from the filesystem, a process needs write permissions in the containing directory. We could put sockets in dummy directories that can be chown(2)ed to nobody. This could be dangerous, though, as we don't control the socket names. It is our users who configure the socket name in their configuration, and so it's easy that they don't understand the many implications of not chosing an appropriate socket pathname. A user could unknowingly put the socket in a directory that is not supposed to be owned by user nobody, and if we blindly chown(2) or chmod(2) the directory, we could be creating a big security hole. - Ask the main process to remove the socket. This would require a very complex communication mechanism with the main process, which is not impossible, but let's avoid it if there are simpler solutions. - Give the child process the CAP_DAC_OVERRIDE capability. That is one of the most powerful capabilities. A process with that capability can be considered root for most practical aspects. Even if the capability is disabled for most of the lifetime of the process, there's a slight chance that a malicious actor could activate it and then easily do serious damage to the system. - unlink(2) the file right before calling bind(2). This is dangerous because another process (for example, another running instance of unitd(8)), could be using the socket, and removing the pathname from the filesystem would be problematic. To do this correctly, a lot of checks should be added before the actual unlink(2), which is error-prone, and difficult to do correctly, and atomically. - Use abstract-namespace Unix domain sockets. This is the simplest solution, as it only requires accepting a slightly different syntax (basically a @ prefix) for the socket name, to transform it into a string starting with a null byte ('\0') that the kernel can understand. The patch is minimal. Since abstract sockets live in an abstract namespace, they don't create files in the filesystem, so there's no need to remove them later. The kernel removes the name when the last fd to it has been closed. One caveat is that only Linux currently supports this kind of Unix sockets. Of course, a solution to that could be to ask other kernels to implement such a feature. Another caveat is that filesystem permissions can't be used to control access to the socket file (since, of course, there's no file). Anyone knowing the socket name can access to it. The only method to control access to it is by using network_namespaces(7). Since in unitd(8) we're using 0666 file sockets, abstract sockets should be no more insecure than that (anyone can already read/write to the listener sockets). - Ask the kernel to implement a simpler way to unlink(2) socket files when they are not needed anymore. I've suggested that to the mailing list, in: In this commit, I decided to go for the easiest/simplest solution, which is abstract sockets. In fact, we already had partial support. This commit only fixes some small bug in the existing code so that abstract Unix sockets work: - Don't chmod(2) the socket if it's an abstract one. This fixes the creation of abstract sockets, but doesn't make them usable, since we produce them with a trailing '\0' in their name. That will be fixed in the following commit. This closes #669 issue on GitHub. --- src/nxt_main_process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c index 03761a10..39a8e112 100644 --- a/src/nxt_main_process.c +++ b/src/nxt_main_process.c @@ -1187,7 +1187,9 @@ nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls) #if (NXT_HAVE_UNIX_DOMAIN) - if (sa->u.sockaddr.sa_family == AF_UNIX) { + if (sa->u.sockaddr.sa_family == AF_UNIX + && sa->u.sockaddr_un.sun_path[0] != '\0') + { char *filename; mode_t access; -- cgit From e2aec6686a4d2cf1ddc017b50dbb39baefd2d425 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 7 Aug 2022 01:08:52 +0200 Subject: Storing abstract sockets with @ internally. We accept both "\u0000socket-name" and "@socket-name" as abstract unix sockets. The first one is passed to the kernel pristine, while the second is transformed '@'->'\0'. The commit that added support for unix sockets accepts both variants, but we internally stored it in the same way, using "\u0000..." for both. We want to support abstract sockets transparently to the user, so that if the user configures unitd with '@', if we receive a query about the current configuration, the user should see the same exact thing that was configured. So, this commit avoids the transformation in the internal state file, storing user input pristine, and we only transform the '@' for a string that will be used internally (not user-visible). This commit (indirectly) fixes a small bug, where we created abstract sockets with a trailing '\0' in their name due to calling twice nxt_sockaddr_parse() on the same string. By calling that function only once with each copy of the string, we have fixed that bug. --- src/nxt_conf_validation.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 3e89d775..fe6c22e5 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -1480,9 +1480,14 @@ nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value) { nxt_int_t ret; + nxt_str_t str; nxt_sockaddr_t *sa; - sa = nxt_sockaddr_parse(vldt->pool, name); + if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) { + return NXT_ERROR; + } + + sa = nxt_sockaddr_parse(vldt->pool, &str); if (nxt_slow_path(sa == NULL)) { return nxt_conf_vldt_error(vldt, "The listener address \"%V\" is invalid.", -- cgit From 7e4a8a54221adf00cd3eb45a24b633ce61400570 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 28 Jul 2022 16:10:32 +0200 Subject: Disallowed abstract unix socket syntax in non-Linux systems. The previous commit added/fixed support for abstract Unix domain sockets on Linux with a leading '@' or '\0'. To be consistent in all platforms, treat those prefixes as markers for abstract sockets in all platforms, and fail if abstract sockets are not supported by the platform. That will avoid mistakes when copying a config file from a Linux system and using it in non-Linux, which would surprisingly create a normal socket. --- src/nxt_sockaddr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 8220590e..86c3335e 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -601,8 +601,6 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; -#if (NXT_LINUX) - /* * Linux unix(7): * @@ -615,9 +613,12 @@ nxt_sockaddr_unix_parse(nxt_mp_t *mp, nxt_str_t *addr) if (path[0] == '@') { path[0] = '\0'; socklen--; - } - +#if !(NXT_LINUX) + nxt_thread_log_error(NXT_LOG_ERR, + "abstract unix domain sockets are not supported"); + return NULL; #endif + } sa = nxt_sockaddr_alloc(mp, socklen, addr->length); -- cgit From b26624fc10cc1f4eb88c16ac8fb5b6b4b61895fc Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 31 Aug 2022 12:49:15 +0100 Subject: Ruby: prevented a segfault on receiving SIGINT (^C). As was reported[0] by @travisbell on GitHub, if running unit from the terminal in the foreground when hitting ^C to exit it, the ruby application processes would segfault if they were using threads. It's not 100% clear where the actual problem lies, but it _looks_ like it may be in ruby. The simplest way to deal with this for now is to just ignore SIGINT in the ruby application processes. Unit will still receive and handle it, cleanly shutting everything down. For people who want to handle SIGINT in their ruby application running under unit they can still trap SIGINT and it will override the ignore. [0]: https://github.com/nginx/unit/issues/562#issuecomment-1223229585 Closes: https://github.com/nginx/unit/issues/562 --- src/ruby/nxt_ruby.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c index 07d02dce..f316d8a5 100644 --- a/src/ruby/nxt_ruby.c +++ b/src/ruby/nxt_ruby.c @@ -270,6 +270,8 @@ nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data) static char *argv[2] = { (char *) "NGINX_Unit", (char *) "-e0" }; + signal(SIGINT, SIG_IGN); + conf = data->app; c = &conf->u.ruby; -- cgit From ce26dd729e6842c9ec8cc83bf091167e4c50a1ec Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Mon, 29 Aug 2022 14:27:09 +0800 Subject: Implemented basic statistics API. --- src/nxt_conf.c | 14 ++++ src/nxt_conf.h | 2 + src/nxt_conn.h | 23 +++++++ src/nxt_conn_accept.c | 9 ++- src/nxt_conn_close.c | 14 ++-- src/nxt_controller.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++-- src/nxt_event_engine.h | 4 ++ src/nxt_h1proto.c | 13 ++-- src/nxt_port.h | 5 ++ src/nxt_router.c | 81 ++++++++++++++++++++++++ src/nxt_status.c | 102 +++++++++++++++++++++++++++++ src/nxt_status.h | 32 ++++++++++ 12 files changed, 452 insertions(+), 16 deletions(-) create mode 100644 src/nxt_status.c create mode 100644 src/nxt_status.h (limited to 'src') diff --git a/src/nxt_conf.c b/src/nxt_conf.c index a44b8c75..c6312f3d 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -278,6 +278,20 @@ nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, } +nxt_int_t +nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, nxt_str_t *name, + nxt_conf_value_t *value, uint32_t index) +{ + nxt_conf_object_member_t *member; + + member = &object->u.object->members[index]; + + member->value = *value; + + return nxt_conf_set_string_dup(&member->name, mp, name); +} + + void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index) diff --git a/src/nxt_conf.h b/src/nxt_conf.h index f95b61c1..c8a276c0 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -127,6 +127,8 @@ NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, const nxt_conf_value_t *value, uint32_t index); +nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, + nxt_str_t *name, nxt_conf_value_t *value, uint32_t index); void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index); nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, diff --git a/src/nxt_conn.h b/src/nxt_conn.h index a443601f..8a703e9a 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -160,6 +160,7 @@ struct nxt_conn_s { uint8_t block_read; /* 1 bit */ uint8_t block_write; /* 1 bit */ uint8_t delayed; /* 1 bit */ + uint8_t idle; /* 1 bit */ #define NXT_CONN_SENDFILE_OFF 0 #define NXT_CONN_SENDFILE_ON 1 @@ -294,6 +295,28 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, } while (0) +#define nxt_conn_idle(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_insert_head(&e->idle_connections, &c->link); \ + \ + c->idle = 1; \ + e->idle_conns_cnt++; \ + } while (0) + + +#define nxt_conn_active(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_remove(&c->link); \ + \ + c->idle = 0; \ + e->idle_conns_cnt--; \ + } while (0) + + extern nxt_conn_io_t nxt_unix_conn_io; diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c index 77c44c58..720c7b64 100644 --- a/src/nxt_conn_accept.c +++ b/src/nxt_conn_accept.c @@ -187,7 +187,8 @@ nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data) void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) { - nxt_conn_t *next; + nxt_conn_t *next; + nxt_event_engine_t *engine; nxt_sockaddr_text(c->remote); @@ -195,7 +196,11 @@ nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) (size_t) c->remote->address_length, nxt_sockaddr_address(c->remote)); - nxt_queue_insert_head(&task->thread->engine->idle_connections, &c->link); + engine = task->thread->engine; + + engine->accepted_conns_cnt++; + + nxt_conn_idle(engine, c); c->listen = lev; lev->count++; diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c index 7c130309..92bd8d1b 100644 --- a/src/nxt_conn_close.c +++ b/src/nxt_conn_close.c @@ -119,6 +119,8 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) nxt_socket_close(task, c->socket.fd); c->socket.fd = -1; + engine->closed_conns_cnt++; + if (timers_pending == 0) { nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, @@ -137,8 +139,9 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) static void nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) { - nxt_conn_t *c; - nxt_timer_t *timer; + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_event_engine_t *engine; timer = obj; @@ -146,13 +149,16 @@ nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd); + engine = task->thread->engine; + if (c->socket.fd != -1) { nxt_socket_close(task, c->socket.fd); c->socket.fd = -1; + + engine->closed_conns_cnt++; } - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - c->write_state->ready_handler, + nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, task, c, c->socket.data); } diff --git a/src/nxt_controller.c b/src/nxt_controller.c index e1e9fade..09168821 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -85,6 +86,12 @@ static void nxt_controller_process_request(nxt_task_t *task, static void nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, nxt_str_t *path); static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task); +static void nxt_controller_process_status(nxt_task_t *task, + nxt_controller_request_t *req); +static void nxt_controller_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_controller_status_response(nxt_task_t *task, + nxt_controller_request_t *req, nxt_str_t *path); #if (NXT_TLS) static void nxt_controller_process_cert(nxt_task_t *task, nxt_controller_request_t *req, nxt_str_t *path); @@ -120,6 +127,7 @@ static nxt_uint_t nxt_controller_router_ready; static nxt_controller_conf_t nxt_controller_conf; static nxt_queue_t nxt_controller_waiting_requests; static nxt_bool_t nxt_controller_waiting_init_conf; +static nxt_conf_value_t *nxt_controller_status; static const nxt_event_conn_state_t nxt_controller_conn_read_state; @@ -1035,6 +1043,7 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) static nxt_str_t certificates = nxt_string("certificates"); #endif static nxt_str_t config = nxt_string("config"); + static nxt_str_t status = nxt_string("status"); c = req->conn; path = req->parser.path; @@ -1058,6 +1067,32 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) return; } + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (nxt_str_start(&path, "/status", 7) + && (path.length == 7 || path.start[7] == '/')) + { + if (!nxt_str_eq(&req->parser.method, "GET", 3)) { + goto invalid_method; + } + + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } + + if (path.length == 7) { + path.length = 1; + + } else { + path.length -= 7; + path.start += 7; + } + + nxt_controller_status_response(task, req, &path); + return; + } + #if (NXT_TLS) if (nxt_str_start(&path, "/certificates", 13) @@ -1085,15 +1120,18 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) return; } - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (path.length == 1 && path.start[0] == '/') { if (!nxt_str_eq(&req->parser.method, "GET", 3)) { goto invalid_method; } - count = 1; + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } + + count = 2; #if (NXT_TLS) count++; #endif @@ -1114,7 +1152,8 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) nxt_conf_set_member(value, &certificates, certs, i++); #endif - nxt_conf_set_member(value, &config, nxt_controller_conf.root, i); + nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++); + nxt_conf_set_member(value, &status, nxt_controller_status, i); resp.status = 200; resp.conf = value; @@ -1451,6 +1490,128 @@ nxt_controller_check_postpone_request(nxt_task_t *task) } +static void +nxt_controller_process_status(nxt_task_t *task, nxt_controller_request_t *req) +{ + uint32_t stream; + nxt_int_t rc; + nxt_port_t *router_port, *controller_port; + nxt_runtime_t *rt; + nxt_controller_response_t resp; + + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } + + rt = task->thread->runtime; + + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + nxt_assert(router_port != NULL); + nxt_assert(nxt_controller_router_ready); + + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + + stream = nxt_port_rpc_register_handler(task, controller_port, + nxt_controller_status_handler, + nxt_controller_status_handler, + router_port->pid, req); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS, + -1, stream, controller_port->id, NULL); + + if (nxt_slow_path(rc != NXT_OK)) { + nxt_port_rpc_cancel(task, controller_port, stream); + + goto fail; + } + + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); + return; + +fail: + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + resp.status = 500; + resp.title = (u_char *) "Failed to get status."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; +} + + +static void +nxt_controller_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_conf_value_t *status; + nxt_controller_request_t *req; + nxt_controller_response_t resp; + + nxt_debug(task, "controller status handler"); + + req = data; + + if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { + status = nxt_status_get((nxt_status_report_t *) msg->buf->mem.pos, + req->conn->mem_pool); + } else { + status = NULL; + } + + if (status == NULL) { + nxt_queue_remove(&req->link); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + resp.status = 500; + resp.title = (u_char *) "Failed to get status."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + } + + nxt_controller_status = status; + + nxt_controller_flush_requests(task); + + nxt_controller_status = NULL; +} + + +static void +nxt_controller_status_response(nxt_task_t *task, nxt_controller_request_t *req, + nxt_str_t *path) +{ + nxt_conf_value_t *status; + nxt_controller_response_t resp; + + status = nxt_conf_get_path(nxt_controller_status, path); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (status == NULL) { + resp.status = 404; + resp.title = (u_char *) "Invalid path."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; + } + + resp.status = 200; + resp.conf = status; + + nxt_controller_response(task, req, &resp); +} + + #if (NXT_TLS) static void diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 91cfc0aa..4153742d 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -483,6 +483,10 @@ struct nxt_event_engine_s { nxt_queue_t idle_connections; nxt_array_t *mem_cache; + nxt_atomic_uint_t accepted_conns_cnt; + nxt_atomic_uint_t idle_conns_cnt; + nxt_atomic_uint_t closed_conns_cnt; + nxt_queue_link_t link; // STUB: router link nxt_queue_link_t link0; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 1473aaa0..852b4866 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -478,7 +478,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn request init"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); r = nxt_http_request_create(task); @@ -1739,7 +1739,7 @@ nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn close"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_shutdown(task, c); } @@ -1754,7 +1754,7 @@ nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn error"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_shutdown(task, c); } @@ -1801,7 +1801,8 @@ nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) c->sent = 0; engine = task->thread->engine; - nxt_queue_insert_head(&engine->idle_connections, &c->link); + + nxt_conn_idle(engine, c); if (in == NULL) { c->read_state = &nxt_h1p_keepalive_state; @@ -1855,7 +1856,7 @@ nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p idle close"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_idle_response(task, c); } @@ -1874,7 +1875,7 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) c = nxt_read_timer_conn(timer); c->block_read = 1; - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_idle_response(task, c); } diff --git a/src/nxt_port.h b/src/nxt_port.h index 6b4d3c8f..3a8da5ad 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -53,6 +53,9 @@ struct nxt_port_handlers_s { nxt_port_handler_t data; nxt_port_handler_t app_restart; + /* Status report. */ + nxt_port_handler_t status; + nxt_port_handler_t oosm; nxt_port_handler_t shm_ack; nxt_port_handler_t read_queue; @@ -104,6 +107,7 @@ typedef enum { _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data), _NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart), + _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status), _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm), _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack), @@ -145,6 +149,7 @@ typedef enum { NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA, NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA), NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART), + NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS), NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM), NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK), diff --git a/src/nxt_router.c b/src/nxt_router.c index e1f4f6da..e7723a2d 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -7,6 +7,7 @@ #include #include +#include #if (NXT_TLS) #include #endif @@ -90,6 +91,8 @@ static void nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); +static void nxt_router_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg); static void nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); @@ -269,6 +272,7 @@ static const nxt_port_handlers_t nxt_router_process_port_handlers = { .get_mmap = nxt_router_get_mmap_handler, .data = nxt_router_conf_data_handler, .app_restart = nxt_router_app_restart_handler, + .status = nxt_router_status_handler, .remove_pid = nxt_router_remove_pid_handler, .access_log = nxt_router_access_log_reopen_handler, .rpc_ready = nxt_port_rpc_handler, @@ -918,6 +922,83 @@ fail: } +static void +nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + u_char *p; + size_t alloc; + nxt_app_t *app; + nxt_buf_t *b; + nxt_uint_t type; + nxt_port_t *port; + nxt_status_app_t *app_stat; + nxt_event_engine_t *engine; + nxt_status_report_t *report; + + port = nxt_runtime_port_find(task->thread->runtime, + msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "nxt_router_status_handler(): reply port not found"); + return; + } + + alloc = sizeof(nxt_status_report_t); + + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + + alloc += sizeof(nxt_status_app_t) + app->name.length; + + } nxt_queue_loop; + + b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0); + if (nxt_slow_path(b == NULL)) { + type = NXT_PORT_MSG_RPC_ERROR; + goto fail; + } + + report = (nxt_status_report_t *) b->mem.free; + b->mem.free = b->mem.end; + + nxt_memzero(report, sizeof(nxt_status_report_t)); + + nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) { + + report->accepted_conns += engine->accepted_conns_cnt; + report->idle_conns += engine->idle_conns_cnt; + report->closed_conns += engine->closed_conns_cnt; + + } nxt_queue_loop; + + report->apps_count = 0; + app_stat = report->apps; + p = b->mem.end; + + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + p -= app->name.length; + + nxt_memcpy(p, app->name.start, app->name.length); + + app_stat->name.length = app->name.length; + app_stat->name.start = (u_char *) (p - b->mem.pos); + + app_stat->active_requests = app->active_requests; + app_stat->pending_processes = app->pending_processes; + app_stat->processes = app->processes; + app_stat->idle_processes = app->idle_processes; + + report->apps_count++; + app_stat++; + } nxt_queue_loop; + + type = NXT_PORT_MSG_RPC_READY_LAST; + +fail: + + nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b); +} + + static void nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port, void *data) diff --git a/src/nxt_status.c b/src/nxt_status.c new file mode 100644 index 00000000..529f6ebb --- /dev/null +++ b/src/nxt_status.c @@ -0,0 +1,102 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include + + +nxt_conf_value_t * +nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) +{ + size_t i; + nxt_str_t name; + nxt_int_t ret; + nxt_status_app_t *app; + nxt_conf_value_t *status, *obj, *apps, *app_obj; + + static nxt_str_t conns_str = nxt_string("connections"); + static nxt_str_t acc_str = nxt_string("accepted"); + static nxt_str_t active_str = nxt_string("active"); + static nxt_str_t idle_str = nxt_string("idle"); + static nxt_str_t closed_str = nxt_string("closed"); + static nxt_str_t reqs_str = nxt_string("requests"); + static nxt_str_t apps_str = nxt_string("applications"); + static nxt_str_t procs_str = nxt_string("processes"); + static nxt_str_t run_str = nxt_string("running"); + static nxt_str_t start_str = nxt_string("starting"); + + status = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(status == NULL)) { + return NULL; + } + + obj = nxt_conf_create_object(mp, 4); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &conns_str, obj, 0); + + nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0); + nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns + - report->closed_conns + - report->idle_conns, 1); + nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); + nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); + + obj = nxt_conf_create_object(mp, 0); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &reqs_str, obj, 1); + + apps = nxt_conf_create_object(mp, report->apps_count); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &apps_str, apps, 2); + + for (i = 0; i < report->apps_count; i++) { + app = &report->apps[i]; + + app_obj = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + name.length = app->name.length; + name.start = nxt_pointer_to(report, (uintptr_t) app->name.start); + + ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + obj = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(app_obj, &procs_str, obj, 0); + + nxt_conf_set_member_integer(obj, &run_str, app->processes, 0); + nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1); + nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); + + obj = nxt_conf_create_object(mp, 1); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(app_obj, &reqs_str, obj, 1); + + nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0); + } + + return status; +} diff --git a/src/nxt_status.h b/src/nxt_status.h new file mode 100644 index 00000000..b12eabcb --- /dev/null +++ b/src/nxt_status.h @@ -0,0 +1,32 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_STATUS_H_INCLUDED_ +#define _NXT_STATUS_H_INCLUDED_ + + +typedef struct { + nxt_str_t name; + uint32_t active_requests; + uint32_t pending_processes; + uint32_t processes; + uint32_t idle_processes; +} nxt_status_app_t; + + +typedef struct { + uint64_t accepted_conns; + uint64_t idle_conns; + uint64_t closed_conns; + + size_t apps_count; + nxt_status_app_t apps[]; +} nxt_status_report_t; + + +nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp); + + +#endif /* _NXT_STATUS_H_INCLUDED_ */ -- cgit From 3ea113fcb7261a0be3b9dc8d32c402da1bcfadaa Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Mon, 29 Aug 2022 14:32:20 +0800 Subject: Status: added requests count. --- src/nxt_event_engine.h | 1 + src/nxt_http_request.c | 2 ++ src/nxt_router.c | 1 + src/nxt_status.c | 5 ++++- src/nxt_status.h | 1 + 5 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 4153742d..291ea749 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -486,6 +486,7 @@ struct nxt_event_engine_s { nxt_atomic_uint_t accepted_conns_cnt; nxt_atomic_uint_t idle_conns_cnt; nxt_atomic_uint_t closed_conns_cnt; + nxt_atomic_uint_t requests_cnt; nxt_queue_link_t link; // STUB: router link diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index a16340de..943ad82d 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -278,6 +278,8 @@ nxt_http_request_create(nxt_task_t *task) r->resp.content_length_n = -1; r->state = &nxt_http_request_init_state; + task->thread->engine->requests_cnt++; + return r; fail: diff --git a/src/nxt_router.c b/src/nxt_router.c index e7723a2d..f02bf3f2 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -967,6 +967,7 @@ nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) report->accepted_conns += engine->accepted_conns_cnt; report->idle_conns += engine->idle_conns_cnt; report->closed_conns += engine->closed_conns_cnt; + report->requests += engine->requests_cnt; } nxt_queue_loop; diff --git a/src/nxt_status.c b/src/nxt_status.c index 529f6ebb..12280019 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -23,6 +23,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) static nxt_str_t idle_str = nxt_string("idle"); static nxt_str_t closed_str = nxt_string("closed"); static nxt_str_t reqs_str = nxt_string("requests"); + static nxt_str_t total_str = nxt_string("total"); static nxt_str_t apps_str = nxt_string("applications"); static nxt_str_t procs_str = nxt_string("processes"); static nxt_str_t run_str = nxt_string("running"); @@ -47,13 +48,15 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); - obj = nxt_conf_create_object(mp, 0); + obj = nxt_conf_create_object(mp, 1); if (nxt_slow_path(obj == NULL)) { return NULL; } nxt_conf_set_member(status, &reqs_str, obj, 1); + nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); + apps = nxt_conf_create_object(mp, report->apps_count); if (nxt_slow_path(obj == NULL)) { return NULL; diff --git a/src/nxt_status.h b/src/nxt_status.h index b12eabcb..a99ac7d0 100644 --- a/src/nxt_status.h +++ b/src/nxt_status.h @@ -20,6 +20,7 @@ typedef struct { uint64_t accepted_conns; uint64_t idle_conns; uint64_t closed_conns; + uint64_t requests; size_t apps_count; nxt_status_app_t apps[]; -- cgit From 9d3b9dba40924229b0c4909b0a4c60d08214501c Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Tue, 6 Sep 2022 09:40:54 +0800 Subject: Status: fixed incorrect pointer in test operation. Found by Coverity (CID 380755). --- src/nxt_status.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nxt_status.c b/src/nxt_status.c index 12280019..f8002e86 100644 --- a/src/nxt_status.c +++ b/src/nxt_status.c @@ -58,7 +58,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_conf_set_member_integer(obj, &total_str, report->requests, 0); apps = nxt_conf_create_object(mp, report->apps_count); - if (nxt_slow_path(obj == NULL)) { + if (nxt_slow_path(apps == NULL)) { return NULL; } @@ -81,7 +81,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) } obj = nxt_conf_create_object(mp, 3); - if (nxt_slow_path(app_obj == NULL)) { + if (nxt_slow_path(obj == NULL)) { return NULL; } @@ -92,7 +92,7 @@ nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); obj = nxt_conf_create_object(mp, 1); - if (nxt_slow_path(app_obj == NULL)) { + if (nxt_slow_path(obj == NULL)) { return NULL; } -- cgit From 558a5d3e892dab4690c9f980b3e175ac26e4e077 Mon Sep 17 00:00:00 2001 From: Alex Colomar Date: Fri, 9 Sep 2022 13:40:17 +0100 Subject: Fixed a mutex leak in the C API. In nxt_unit_create() we could leak a mutex created in nxt_unit_ctx_init(). This could happen if nxt_unit_ctx_init() succeeded but later on we bailed out of nxt_unit_create(), we would destroy the mutex created in nxt_unit_create() but not the one created in nxt_unit_ctx_init(). Reorder things so that we do the call to nxt_unit_create() after all the other checks so if it fails we don't leak the mutex it created. Co-developed-by: Andrew Clayton Signed-off-by: Andrew Clayton Signed-off-by: Alex Colomar --- src/nxt_unit.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nxt_unit.c b/src/nxt_unit.c index fd086b2c..e5cb0b58 100644 --- a/src/nxt_unit.c +++ b/src/nxt_unit.c @@ -585,9 +585,14 @@ fail: static nxt_unit_impl_t * nxt_unit_create(nxt_unit_init_t *init) { - int rc; - nxt_unit_impl_t *lib; - nxt_unit_callbacks_t *cb; + int rc; + nxt_unit_impl_t *lib; + + if (nxt_slow_path(init->callbacks.request_handler == NULL)) { + nxt_unit_alert(NULL, "request_handler is NULL"); + + return NULL; + } lib = nxt_unit_malloc(NULL, sizeof(nxt_unit_impl_t) + init->request_data_size); @@ -630,15 +635,6 @@ nxt_unit_create(nxt_unit_init_t *init) goto fail; } - cb = &lib->callbacks; - - if (cb->request_handler == NULL) { - nxt_unit_alert(NULL, "request_handler is NULL"); - - pthread_mutex_destroy(&lib->mutex); - goto fail; - } - nxt_unit_mmaps_init(&lib->incoming); nxt_unit_mmaps_init(&lib->outgoing); -- cgit