From da15222f1ba51a3309b43f1f7aff062d183e7f25 Mon Sep 17 00:00:00 2001 From: Oleg S Date: Mon, 16 Jan 2023 22:52:47 +0300 Subject: [PATCH] Fix bug on send iterable response without keepalive flag (#26) * Added remote client address into log messages * Fix bug on send iterable response without keepalive flag --- fastwsgi/logx.c | 25 +++++++++++++++++++++---- fastwsgi/logx.h | 1 + fastwsgi/server.c | 38 ++++++++++++++++++++++++++++---------- fastwsgi/server.h | 7 ++++++- 4 files changed, 56 insertions(+), 15 deletions(-) diff --git a/fastwsgi/logx.c b/fastwsgi/logx.c index 33f7ab5..5a7bc04 100644 --- a/fastwsgi/logx.c +++ b/fastwsgi/logx.c @@ -33,6 +33,15 @@ void set_log_level(int level) } static const char log_prefix[] = "[FWSGI-X]"; +static const int log_level_pos = 7; +static const char * log_client_addr = NULL; +static int log_client_addr_len = 0; + +void set_log_client_addr(const char * addr) +{ + log_client_addr = addr; + log_client_addr_len = addr ? strlen(addr) : 0; +} void logmsg(int level, const char * fmt, ...) { @@ -40,10 +49,18 @@ void logmsg(int level, const char * fmt, ...) if (level <= g_log_level) { va_list argptr; va_start(argptr, fmt); - const int prefix_len = sizeof(log_prefix); // include space - memcpy(buf, log_prefix, prefix_len); // add prefix - buf[prefix_len - 3] = g_log_level_str[level]; // replace X to error type - buf[prefix_len - 1] = 0x20; // add space delimiter + const int log_prefix_size = sizeof(log_prefix) - 1; + memcpy(buf, log_prefix, log_prefix_size); + buf[log_level_pos] = g_log_level_str[level]; // replace X to error type + buf[log_prefix_size] = 0x20; // add space delimiter + int prefix_len = log_prefix_size + 1; + if (log_client_addr) { + buf[prefix_len++] = '('; + memcpy(buf + prefix_len, log_client_addr, log_client_addr_len); + prefix_len += log_client_addr_len; + buf[prefix_len++] = ')'; + buf[prefix_len++] = 0x20; // add space delimiter + } int maxlen = sizeof(buf) - prefix_len - 8; int len = vsnprintf(buf + prefix_len, maxlen, fmt, argptr); va_end(argptr); diff --git a/fastwsgi/logx.h b/fastwsgi/logx.h index a9a0f60..3c16b46 100644 --- a/fastwsgi/logx.h +++ b/fastwsgi/logx.h @@ -30,6 +30,7 @@ typedef enum { extern int g_log_level; void set_log_level(int level); +void set_log_client_addr(const char * addr); void logmsg(int level, const char * fmt, ...); #define LOGMSG(_level_, ...) if (_level_ <= g_log_level) logmsg(_level_, __VA_ARGS__) diff --git a/fastwsgi/server.c b/fastwsgi/server.c index fd967b4..c96fafd 100644 --- a/fastwsgi/server.c +++ b/fastwsgi/server.c @@ -40,8 +40,9 @@ typedef enum { void close_cb(uv_handle_t * handle) { - LOGn("disconnected ================================="); client_t * client = (client_t *)handle; + update_log_prefix(client); + LOGn("disconnected ================================="); Py_XDECREF(client->request.headers); Py_XDECREF(client->request.wsgi_input_empty); Py_XDECREF(client->request.wsgi_input); @@ -50,6 +51,7 @@ void close_cb(uv_handle_t * handle) reset_response_body(client); free_read_buffer(client, NULL); free(client); + update_log_prefix(NULL); } void close_connection(client_t * client) @@ -61,6 +63,7 @@ void close_connection(client_t * client) void shutdown_cb(uv_shutdown_t * req, int status) { uv_handle_t * client = (uv_handle_t *)req->handle; + update_log_prefix(client); LOGt("%s: status = %d", __func__, status); if (!uv_is_closing(client)) uv_close(client, close_cb); @@ -110,6 +113,7 @@ void write_cb(uv_write_t * req, int status) int close_conn = 0; write_req_t * wreq = (write_req_t*)req; client_t * client = (client_t *)wreq->client; + update_log_prefix(client); if (status != 0) { LOGe("%s: Write error: %s", __func__, uv_strerror(status)); goto fin; @@ -168,7 +172,10 @@ void write_cb(uv_write_t * req, int status) return; fin: - if (status < 0 || !client->srv->allow_keepalive) { + if (status < 0) { + close_conn = 1; + } + if (!client->request.keep_alive || !client->srv->allow_keepalive) { close_conn = 1; } if (!close_conn) { @@ -257,6 +264,7 @@ void read_cb(uv_stream_t * handle, ssize_t nread, const uv_buf_t * buf) int act = CA_OK; client_t * client = (client_t *)handle; llhttp_t * parser = &client->request.parser; + update_log_prefix(client); if (nread == 0) { LOGd("read_cb: nread = 0"); @@ -323,8 +331,6 @@ void read_cb(uv_stream_t * handle, ssize_t nread, const uv_buf_t * buf) } LOGi("Response created! (len = %d+%lld)", client->head.size, client->response.body_preloaded_size); act = stream_write(client); - if (!client->request.keep_alive || !client->srv->allow_keepalive) - act = CA_SHUTDOWN; fin: if (buf->base) @@ -359,9 +365,10 @@ fin: void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { + client_t * client = (client_t *)handle; + update_log_prefix(client); const int read_buffer_size = (int)g_srv.read_buffer_size; LOGt("%s: size = %d (suggested = %d)", __func__, read_buffer_size, (int)suggested_size); - client_t * client = (client_t *)handle; buf->base = NULL; buf->len = 0; @@ -407,11 +414,12 @@ void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) void connection_cb(uv_stream_t * server, int status) { + update_log_prefix(NULL); if (status < 0) { LOGe("Connection error %s\n", uv_strerror(status)); return; } - LOGn("new connection ================================="); + LOGi("new connection ================================="); client_t* client = calloc(1, sizeof(client_t) + g_srv.read_buffer_size + 8); client->srv = &g_srv; @@ -432,12 +440,19 @@ void connection_cb(uv_stream_t * server, int status) rc = uv_tcp_getpeername((uv_tcp_t*)&client->handle, &sock_addr.addr, &sock_len); LOGw_IF(rc, "%s: cannot get remote addr (err = %d)", __func__, rc); if (rc == 0) { - rc = uv_ip_name(&sock_addr.addr, client->remote_addr, sizeof(client->remote_addr)); + char ip[48]; + rc = uv_ip_name(&sock_addr.addr, ip, sizeof(ip)); LOGw_IF(rc, "%s: cannot get remote IP-addr (err = %d)", __func__, rc); if (rc) - client->remote_addr[0] = 0; - LOGn_IF(rc == 0, "remote IP-addr: %s", client->remote_addr); + ip[0] = 0; + if (sock_addr.addr.sa_family == AF_INET6) { + sprintf(client->remote_addr, "[%s]:%d", ip, (int)sock_addr.in6.sin6_port); + } else { + sprintf(client->remote_addr, "%s:%d", ip, (int)sock_addr.in4.sin_port); + } } + update_log_prefix(client); + LOGn("connected ================================="); llhttp_init(&client->request.parser, HTTP_REQUEST, &g_srv.parser_settings); client->request.parser.data = client; uv_read_start((uv_stream_t*)&client->handle, alloc_cb, read_cb); @@ -449,6 +464,7 @@ void signal_handler(uv_signal_t * req, int signum) uv_stop(g_srv.loop); uv_signal_stop(req); if (g_srv.hook_sigint == 2) { + update_log_prefix(NULL); LOGw("%s: halt process", __func__); exit(0); } @@ -528,6 +544,7 @@ PyObject * init_server(PyObject * Py_UNUSED(self), PyObject * server) { int64_t rv; + update_log_prefix(NULL); if (g_srv_inited) { PyErr_Format(PyExc_Exception, "server already inited"); return PyLong_FromLong(-1000); @@ -565,7 +582,7 @@ PyObject * init_server(PyObject * Py_UNUSED(self), PyObject * server) g_srv.port = (int)port; int64_t backlog = get_obj_attr_int(server, "backlog"); - if (port == LLONG_MIN) { + if (backlog == LLONG_MIN) { PyErr_Format(PyExc_ValueError, "Option backlog not defined"); return PyLong_FromLong(-1014); } @@ -696,6 +713,7 @@ PyObject * run_nowait(PyObject * self, PyObject * server) PyObject * close_server(PyObject * Py_UNUSED(self), PyObject * Py_UNUSED(server)) { if (g_srv_inited) { + update_log_prefix(NULL); LOGn("%s", __func__); if (g_srv.signal.signal_cb) { uv_signal_stop(&g_srv.signal); diff --git a/fastwsgi/server.h b/fastwsgi/server.h index 55c15af..f4a67c5 100644 --- a/fastwsgi/server.h +++ b/fastwsgi/server.h @@ -64,7 +64,7 @@ typedef enum { typedef struct { uv_tcp_t handle; // peer connection. Placement strictly at the beginning of the structure! server_t * srv; - char remote_addr[48]; + char remote_addr[64]; xbuf_t rbuf[2]; // buffers for reading from socket struct { int load_state; @@ -128,5 +128,10 @@ typedef enum { int build_response(client_t * client, int flags, int status, const void * headers, const void * body, int body_size); PyObject* wsgi_iterator_get_next_chunk(client_t * client, int outpyerr); +inline void update_log_prefix(void * _client) +{ + client_t * client = (client_t *)_client; + set_log_client_addr(client ? client->remote_addr : NULL); +} #endif