From f96dc46ea761b4690bda02c992bbe9605be4b7a0 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Thu, 12 Jan 2023 19:50:35 +0100 Subject: [PATCH] Add sock_send_x and remove fastcgi compression --- src/lib/fastcgi.c | 89 +++++++----------------------------- src/lib/fastcgi.h | 14 ++---- src/lib/http.c | 4 +- src/lib/proxy.c | 8 ++-- src/lib/sock.c | 10 ++++ src/lib/sock.h | 2 + src/lib/uri.c | 27 ++++------- src/lib/websocket.c | 2 +- src/worker/fastcgi_handler.c | 30 ++---------- src/worker/request_handler.c | 4 +- 10 files changed, 55 insertions(+), 135 deletions(-) diff --git a/src/lib/fastcgi.c b/src/lib/fastcgi.c index 7adf9f7..309333f 100644 --- a/src/lib/fastcgi.c +++ b/src/lib/fastcgi.c @@ -9,13 +9,13 @@ #include "../defs.h" #include "fastcgi.h" #include "utils.h" -#include "compress.h" #include "../logger.h" #include "list.h" #include #include #include +#include char *fastcgi_add_param(char *buf, const char *key, const char *value) { char *ptr = buf; @@ -66,9 +66,7 @@ int fastcgi_init(fastcgi_cnx_t *conn, int mode, unsigned int req_num, const sock conn->socket = fcgi_sock; struct sockaddr_un sock_addr = {AF_UNIX}; - if (conn->mode == FASTCGI_SESIMOS) { - snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", SESIMOS_BACKEND_SOCKET); - } else if (conn->mode == FASTCGI_PHP) { + if (conn->mode == FASTCGI_BACKEND_PHP) { snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", PHP_FPM_SOCKET); } @@ -219,8 +217,8 @@ int fastcgi_php_error(const fastcgi_cnx_t *conn, const char *msg, int msg_len, c memcpy(msg_str, msg, msg_len); msg_str[msg_len] = 0; char *ptr1 = NULL; - int len; - int err = 0; + int len, err = 0; + // FIXME *msg is part of a stream, handle fragmented lines while (1) { log_lvl_t msg_type = LOG_INFO; @@ -289,12 +287,7 @@ int fastcgi_header(fastcgi_cnx_t *conn, http_res *res, char *err_msg) { while (1) { ret = recv(conn->socket, &header, sizeof(header), 0); - if (ret < 0) { - res->status = http_get_status(500); - sprintf(err_msg, "Unable to communicate with FastCGI socket."); - error("Unable to receive from FastCGI socket"); - return 1; - } else if (ret != sizeof(header)) { + if (ret != sizeof(header)) { res->status = http_get_status(500); sprintf(err_msg, "Unable to communicate with FastCGI socket."); error("Unable to receive from FastCGI socket"); @@ -304,13 +297,7 @@ int fastcgi_header(fastcgi_cnx_t *conn, http_res *res, char *err_msg) { content_len = (header.contentLengthB1 << 8) | header.contentLengthB0; content = malloc(content_len + header.paddingLength); ret = recv(conn->socket, content, content_len + header.paddingLength, 0); - if (ret < 0) { - res->status = http_get_status(500); - sprintf(err_msg, "Unable to communicate with FastCGI socket."); - error("Unable to receive from FastCGI socket"); - free(content); - return 1; - } else if (ret != (content_len + header.paddingLength)) { + if (ret != (content_len + header.paddingLength)) { res->status = http_get_status(500); sprintf(err_msg, "Unable to communicate with FastCGI socket."); error("Unable to receive from FastCGI socket"); @@ -337,8 +324,7 @@ int fastcgi_header(fastcgi_cnx_t *conn, http_res *res, char *err_msg) { free(content); return 1; } else if (header.type == FCGI_STDERR) { - // TODO implement Sesimos backend error handling - if (conn->mode == FASTCGI_PHP) { + if (conn->mode == FASTCGI_BACKEND_PHP) { err = err || fastcgi_php_error(conn, content, content_len, err_msg); } } else if (header.type == FCGI_STDOUT) { @@ -395,27 +381,9 @@ int fastcgi_header(fastcgi_cnx_t *conn, http_res *res, char *err_msg) { int fastcgi_send(fastcgi_cnx_t *conn, sock *client, int flags) { FCGI_Header header; long ret; - char buf0[256]; + char buf0[256], *content, *ptr; int len; - char *content, *ptr; unsigned short req_id, content_len; - char comp_out[4096]; - int finish_comp = 0; - - compress_ctx comp_ctx; - if (flags & FASTCGI_COMPRESS_BR) { - flags &= ~FASTCGI_COMPRESS_GZ; - if (compress_init(&comp_ctx, COMPRESS_BR) != 0) { - error("Unable to init brotli"); - flags &= ~FASTCGI_COMPRESS_BR; - } - } else if (flags & FASTCGI_COMPRESS_GZ) { - flags &= ~FASTCGI_COMPRESS_BR; - if (compress_init(&comp_ctx, COMPRESS_GZ) != 0) { - error("Unable to init gzip"); - flags &= ~FASTCGI_COMPRESS_GZ; - } - } if (conn->out_buf != NULL && conn->out_len > conn->out_off) { content = conn->out_buf; @@ -464,45 +432,23 @@ int fastcgi_send(fastcgi_cnx_t *conn, sock *client, int flags) { conn->socket = 0; free(content); - if (flags & FASTCGI_COMPRESS) { - finish_comp = 1; - content_len = 0; - goto out; - finish: - compress_free(&comp_ctx); - } - if (flags & FASTCGI_CHUNKED) { - sock_send(client, "0\r\n\r\n", 5, 0); + sock_send_x(client, "0\r\n\r\n", 5, 0); } return 0; } else if (header.type == FCGI_STDERR) { - // TODO implement Sesimos backend error handling - if (conn->mode == FASTCGI_PHP) { + if (conn->mode == FASTCGI_BACKEND_PHP) { fastcgi_php_error(conn, content, content_len, buf0); } } else if (header.type == FCGI_STDOUT) { - unsigned long avail_in, avail_out; out: - avail_in = content_len; - char *next_in = ptr; - do { - int buf_len = content_len; - if (flags & FASTCGI_COMPRESS) { - avail_out = sizeof(comp_out); - compress_compress(&comp_ctx, next_in + content_len - avail_in, &avail_in, comp_out, &avail_out, finish_comp); - ptr = comp_out; - buf_len = (int) (sizeof(comp_out) - avail_out); - } - if (buf_len != 0) { - len = sprintf(buf0, "%X\r\n", buf_len); - if (flags & FASTCGI_CHUNKED) sock_send(client, buf0, len, 0); - sock_send(client, ptr, buf_len, 0); - if (flags & FASTCGI_CHUNKED) sock_send(client, "\r\n", 2, 0); - } - } while ((flags & FASTCGI_COMPRESS) && (avail_in != 0 || avail_out != sizeof(comp_out))); - if (finish_comp) goto finish; + if (content_len != 0) { + len = sprintf(buf0, "%X\r\n", content_len); + if (flags & FASTCGI_CHUNKED) sock_send_x(client, buf0, len, 0); + sock_send_x(client, ptr, content_len, 0); + if (flags & FASTCGI_CHUNKED) sock_send_x(client, "\r\n", 2, 0); + } } else { error("Unknown FastCGI type: %i", header.type); } @@ -562,8 +508,7 @@ int fastcgi_dump(fastcgi_cnx_t *conn, char *buf, long len) { return 0; } else if (header.type == FCGI_STDERR) { - // TODO implement Sesimos backend error handling - if (conn->mode == FASTCGI_PHP) { + if (conn->mode == FASTCGI_BACKEND_PHP) { fastcgi_php_error(conn, content, content_len, buf0); } } else if (header.type == FCGI_STDOUT) { diff --git a/src/lib/fastcgi.h b/src/lib/fastcgi.h index eb1dd82..a41ac04 100644 --- a/src/lib/fastcgi.h +++ b/src/lib/fastcgi.h @@ -14,28 +14,20 @@ #include "uri.h" #define FASTCGI_CHUNKED 1 -#define FASTCGI_COMPRESS_GZ 2 -#define FASTCGI_COMPRESS_BR 4 -#define FASTCGI_COMPRESS 6 -#define FASTCGI_COMPRESS_HOLD 8 -#define FASTCGI_PHP 1 -#define FASTCGI_SESIMOS 2 +#define FASTCGI_BACKEND_PHP 1 #ifndef PHP_FPM_SOCKET # define PHP_FPM_SOCKET "/var/run/php-fpm/php-fpm.sock" #endif -#define SESIMOS_BACKEND_SOCKET "/var/run/sesimos/backend.sock" - typedef struct { int mode; int socket; unsigned short req_id; - char *out_buf; const char *webroot; - unsigned short out_len; - unsigned short out_off; + char *out_buf; + unsigned short out_len, out_off; char *r_addr; char *r_host; } fastcgi_cnx_t; diff --git a/src/lib/http.c b/src/lib/http.c index e1774e7..160d7b6 100644 --- a/src/lib/http.c +++ b/src/lib/http.c @@ -358,7 +358,7 @@ int http_send_response(sock *client, http_res *res) { off += sprintf(buf + off, "%s: %s\r\n", http_field_get_name(f), http_field_get_value(f)); } off += sprintf(buf + off, "\r\n"); - if (sock_send(client, buf, off, 0) != off) + if (sock_send_x(client, buf, off, 0) != off) return -1; return 0; @@ -372,7 +372,7 @@ int http_send_request(sock *server, http_req *req) { off += sprintf(buf + off, "%s: %s\r\n", http_field_get_name(f), http_field_get_value(f)); } off += sprintf(buf + off, "\r\n"); - if (sock_send(server, buf, off, 0) != off) + if (sock_send_x(server, buf, off, 0) != off) return -1; return 0; diff --git a/src/lib/proxy.c b/src/lib/proxy.c index 96ea864..4717521 100644 --- a/src/lib/proxy.c +++ b/src/lib/proxy.c @@ -635,14 +635,14 @@ int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int len = sprintf(buf, "%lX\r\n", buf_len); ret = 1; - if (flags & PROXY_CHUNKED) ret = sock_send(client, buf, len, 0); + if (flags & PROXY_CHUNKED) ret = sock_send_x(client, buf, len, 0); if (ret <= 0) goto err; - ret = sock_send(client, ptr, buf_len, 0); + ret = sock_send_x(client, ptr, buf_len, 0); if (ret <= 0) goto err; if (!(flags & PROXY_COMPRESS)) snd_len += ret; - if (flags & PROXY_CHUNKED) ret = sock_send(client, "\r\n", 2, 0); + if (flags & PROXY_CHUNKED) ret = sock_send_x(client, "\r\n", 2, 0); if (ret <= 0) { err: error("Unable to send"); @@ -660,7 +660,7 @@ int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int if (ret <= 0) return -1; if (flags & PROXY_CHUNKED) { - ret = sock_send(client, "0\r\n\r\n", 5, 0); + ret = sock_send_x(client, "0\r\n\r\n", 5, 0); if (ret <= 0) { error("Unable to send"); return -1; diff --git a/src/lib/sock.c b/src/lib/sock.c index 6f2fe38..6d30919 100644 --- a/src/lib/sock.c +++ b/src/lib/sock.c @@ -106,6 +106,16 @@ long sock_send(sock *s, void *buf, unsigned long len, int flags) { } } +long sock_send_x(sock *s, void *buf, unsigned long len, int flags) { + long sent = 0; + for (long ret; sent < len; sent += ret) { + ret = sock_send(s, buf + sent, len - sent, flags); + if (ret <= 0) + return ret; + } + return sent; +} + long sock_recv(sock *s, void *buf, unsigned long len, int flags) { long ret; if (s->enc) { diff --git a/src/lib/sock.h b/src/lib/sock.h index 1eada2f..b554868 100644 --- a/src/lib/sock.h +++ b/src/lib/sock.h @@ -40,6 +40,8 @@ int sock_set_timeout(sock *s, double sec); long sock_send(sock *s, void *buf, unsigned long len, int flags); +long sock_send_x(sock *s, void *buf, unsigned long len, int flags); + long sock_recv(sock *s, void *buf, unsigned long len, int flags); long sock_splice(sock *dst, sock *src, void *buf, unsigned long buf_len, unsigned long len); diff --git a/src/lib/uri.c b/src/lib/uri.c index 03104a0..765bf31 100644 --- a/src/lib/uri.c +++ b/src/lib/uri.c @@ -113,18 +113,16 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo while (1) { sprintf(buf0, "%s%s", uri->webroot, uri->path); - p_len = snprintf(buf1, sizeof(buf1), "%s.ncr", buf0); + p_len = snprintf(buf1, sizeof(buf1), "%s.php", buf0); if (p_len < 0 || p_len >= sizeof(buf1)) return -1; - p_len = snprintf(buf2, sizeof(buf2), "%s.php", buf0); + p_len = snprintf(buf2, sizeof(buf2), "%s.html", buf0); if (p_len < 0 || p_len >= sizeof(buf2)) return -1; - p_len = snprintf(buf3, sizeof(buf3), "%s.html", buf0); - if (p_len < 0 || p_len >= sizeof(buf3)) return -1; if (strlen(uri->path) <= 1 || path_exists(buf0) || path_is_file(buf1) || - path_is_file(buf2) || - path_is_file(buf3)) { + path_is_file(buf2)) + { break; } @@ -145,7 +143,7 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo uri->filename = malloc(strlen(buf0) + 1); strcpy(uri->filename, buf0); long len = (long) strlen(uri->path); - if (strends(uri->path, ".ncr") || strends(uri->path, ".php")) { + if (strends(uri->path, ".php")) { uri->path[len - 4] = 0; uri->is_static = 0; } else if (strends(uri->path, ".html")) { @@ -165,9 +163,8 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo } else { uri->is_dir = 1; strcpy(uri->path + strlen(uri->path), "/"); - sprintf(buf1, "%s%sindex.ncr", uri->webroot, uri->path); - sprintf(buf2, "%s%sindex.php", uri->webroot, uri->path); - sprintf(buf3, "%s%sindex.html", uri->webroot, uri->path); + sprintf(buf1, "%s%sindex.php", uri->webroot, uri->path); + sprintf(buf2, "%s%sindex.html", uri->webroot, uri->path); if (path_is_file(buf1)) { uri->filename = malloc(strlen(buf1) + 1); strcpy(uri->filename, buf1); @@ -175,10 +172,6 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo } else if (path_is_file(buf2)) { uri->filename = malloc(strlen(buf2) + 1); strcpy(uri->filename, buf2); - uri->is_static = 0; - } else if (path_is_file(buf3)) { - uri->filename = malloc(strlen(buf3) + 1); - strcpy(uri->filename, buf3); } else { if (dir_mode == URI_DIR_MODE_FORBIDDEN) { uri->is_static = 1; @@ -198,9 +191,9 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo if (strends(uri->path + strlen(uri->path), "index")) { uri->path[strlen(uri->path) - 5] = 0; } - if (streq(uri->pathinfo, "index.ncr") || - streq(uri->pathinfo, "index.php") || - streq(uri->pathinfo, "index.html")) { + if (streq(uri->pathinfo, "index.php") || + streq(uri->pathinfo, "index.html")) + { uri->pathinfo[0] = 0; } diff --git a/src/lib/websocket.c b/src/lib/websocket.c index 41ef49b..6e63147 100644 --- a/src/lib/websocket.c +++ b/src/lib/websocket.c @@ -125,7 +125,7 @@ int ws_send_frame_header(sock *s, ws_frame *frame) { ptr += 4; } - long ret = sock_send(s, buf, ptr - buf, frame->len != 0 ? MSG_MORE : 0); + long ret = sock_send_x(s, buf, ptr - buf, frame->len != 0 ? MSG_MORE : 0); if (ret < 0) { error("Unable to send to socket"); return -1; diff --git a/src/worker/fastcgi_handler.c b/src/worker/fastcgi_handler.c index 19463fd..16a4975 100644 --- a/src/worker/fastcgi_handler.c +++ b/src/worker/fastcgi_handler.c @@ -46,10 +46,8 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t *fcgi_cnx) { char buf[1024]; int mode, ret; - if (strends(uri->filename, ".ncr")) { - mode = FASTCGI_SESIMOS; - } else if (strends(uri->filename, ".php")) { - mode = FASTCGI_PHP; + if (strends(uri->filename, ".php")) { + mode = FASTCGI_BACKEND_PHP; } else { res->status = http_get_status(500); error("Invalid FastCGI extension: %s", uri->filename); @@ -127,27 +125,8 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t *fcgi_cnx) { } ctx->use_fastcgi = 1; - - if (ctx->content_length != -1 && ctx->content_length < 1024000) { - ctx->use_fastcgi |= FASTCGI_COMPRESS_HOLD; - } - ctx->content_length = -1; - int http_comp = http_get_compression(req, res); - if (http_comp & COMPRESS) { - if (http_comp & COMPRESS_BR) { - ctx->use_fastcgi |= FASTCGI_COMPRESS_BR; - sprintf(buf, "br"); - } else if (http_comp & COMPRESS_GZ) { - ctx->use_fastcgi |= FASTCGI_COMPRESS_GZ; - sprintf(buf, "gzip"); - } - http_add_header_field(&res->hdr, "Vary", "Accept-Encoding"); - http_add_header_field(&res->hdr, "Content-Encoding", buf); - http_remove_header_field(&res->hdr, "Content-Length", HTTP_REMOVE_ALL); - } - if (http_get_header_field(&res->hdr, "Content-Length") == NULL) { http_add_header_field(&res->hdr, "Transfer-Encoding", "chunked"); } @@ -156,10 +135,9 @@ static int fastcgi_handler_1(client_ctx_t *ctx, fastcgi_cnx_t *fcgi_cnx) { } static int fastcgi_handler_2(client_ctx_t *ctx, fastcgi_cnx_t *fcgi_cnx) { - const char *transfer_encoding = http_get_header_field(&ctx->res.hdr, "Transfer-Encoding"); - int chunked = strcontains(transfer_encoding, "chunked"); + int chunked = strcontains(http_get_header_field(&ctx->res.hdr, "Transfer-Encoding"), "chunked"); - int flags = (chunked ? FASTCGI_CHUNKED : 0) | (ctx->use_fastcgi & (FASTCGI_COMPRESS | FASTCGI_COMPRESS_HOLD)); + int flags = (chunked ? FASTCGI_CHUNKED : 0); int ret = fastcgi_send(fcgi_cnx, &ctx->socket, flags); if (ret < 0) { ctx->c_keep_alive = 0; diff --git a/src/worker/request_handler.c b/src/worker/request_handler.c index d6c1481..68e9721 100644 --- a/src/worker/request_handler.c +++ b/src/worker/request_handler.c @@ -341,7 +341,7 @@ int respond(client_ctx_t *ctx) { } else if (!streq(req->method, "HEAD")) { // default response if (ctx->msg_buf != NULL) { - ret = sock_send(client, ctx->msg_buf, ctx->content_length, 0); + ret = sock_send_x(client, ctx->msg_buf, ctx->content_length, 0); if (ret <= 0) { error("Unable to send"); } @@ -352,7 +352,7 @@ int respond(client_ctx_t *ctx) { if (snd_len + len > ctx->content_length) { len = ctx->content_length - snd_len; } - ret = sock_send(client, buffer, len, feof(ctx->file) ? 0 : MSG_MORE); + ret = sock_send_x(client, buffer, len, feof(ctx->file) ? 0 : MSG_MORE); if (ret <= 0) { error("Unable to send"); break;