3 Commits

Author SHA1 Message Date
51d85cc99f Async check if closed 2023-01-02 16:52:18 +01:00
a4c0093fbe Small improvements 2023-01-02 15:43:26 +01:00
6ff6f0c73b Reduce client_ctx_t footprint 2023-01-02 15:20:02 +01:00
8 changed files with 101 additions and 58 deletions

View File

@@ -17,6 +17,7 @@
typedef struct { typedef struct {
int fd; int fd;
sock *socket;
short events; short events;
int flags; int flags;
void (*cb)(void *); void (*cb)(void *);
@@ -30,20 +31,69 @@ typedef struct {
evt_listen_t q[256]; evt_listen_t q[256];
} listen_queue_t; } listen_queue_t;
static listen_queue_t listen1, listen2, *listen = &listen1; static listen_queue_t listen1, listen2, *listen_q = &listen1;
static volatile sig_atomic_t alive = 1; static volatile sig_atomic_t alive = 1;
static pthread_t thread = -1; static pthread_t thread = -1;
static int async_add_to_queue(evt_listen_t *evt) { static int async_add_to_queue(evt_listen_t *evt) {
// TODO locking // TODO locking
memcpy(&listen->q[listen->n++], evt, sizeof(*evt)); memcpy(&listen_q->q[listen_q->n++], evt, sizeof(*evt));
return 0; return 0;
} }
int async(int fd, short events, int flags, void cb(void *), void *arg, void err_cb(void *), void *err_arg) { static int async_exec(evt_listen_t *evt, short r_events) {
struct pollfd fds[1] = {{.fd = fd, .events = events}}; if (r_events & evt->events) {
// specified event(s) occurred
if (evt->socket && !sock_check(evt->socket)) {
evt->err_cb(evt->err_arg);
errno = 0;
} else {
evt->cb(evt->arg);
errno = 0;
if (evt->flags & ASYNC_KEEP)
return 1;
}
return 0;
} else if (r_events & (POLLERR | POLLHUP | POLLNVAL)) {
// error occurred
evt->err_cb(evt->err_arg);
errno = 0;
return 0;
} else {
// no event occurred
return -1;
}
}
static int async_check(evt_listen_t *evt) {
struct pollfd fds[1] = {{.fd = evt->fd, .events = evt->events}};
// check, if fd is already ready
if (poll(fds, 1, 0) == 1) {
// fd already read
if (async_exec(evt, fds[0].revents) == 0)
return 1;
}
return 0;
}
static int async_add(evt_listen_t *evt) {
if (async_check(evt) == 1)
return 0;
int ret = async_add_to_queue(evt);
if (ret == 0 && thread != -1)
pthread_kill(thread, SIGUSR1);
return ret;
}
int async_fd(int fd, short events, int flags, void cb(void *), void *arg, void err_cb(void *), void *err_arg) {
evt_listen_t evt = { evt_listen_t evt = {
.fd = fd, .fd = fd,
.socket = NULL,
.events = events, .events = events,
.flags = flags, .flags = flags,
.cb = cb, .cb = cb,
@@ -51,28 +101,21 @@ int async(int fd, short events, int flags, void cb(void *), void *arg, void err_
.err_cb = err_cb, .err_cb = err_cb,
.err_arg = err_arg, .err_arg = err_arg,
}; };
return async_add(&evt);
}
// check, if fd is already ready int async(sock *s, short events, int flags, void cb(void *), void *arg, void err_cb(void *), void *err_arg) {
if (poll(fds, 1, 0) == 1) { evt_listen_t evt = {
// fd already read .fd = s->socket,
if (fds[0].revents & events) { .socket = s,
// specified event(s) occurred .events = events,
cb(arg); .flags = flags,
.cb = cb,
if (!(flags & ASYNC_KEEP)) .arg = arg,
return 0; .err_cb = err_cb,
} else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { .err_arg = err_arg,
// error occurred };
err_cb(err_arg); return async_add(&evt);
return 0;
}
}
int ret = async_add_to_queue(&evt);
if (ret == 0 && thread != -1)
pthread_kill(thread, SIGUSR1);
return ret;
} }
void async_thread(void) { void async_thread(void) {
@@ -84,8 +127,8 @@ void async_thread(void) {
// main event loop // main event loop
while (alive) { while (alive) {
// swap listen queue // swap listen queue
listen_queue_t *l = listen; listen_queue_t *l = listen_q;
listen = (listen == &listen1) ? &listen2 : &listen1; listen_q = (listen_q == &listen1) ? &listen2 : &listen1;
// fill fds with newly added queue entries // fill fds with newly added queue entries
for (num_fds = 0; num_fds < l->n; num_fds++) { for (num_fds = 0; num_fds < l->n; num_fds++) {
@@ -106,22 +149,8 @@ void async_thread(void) {
for (int i = 0; i < num_fds; i++) { for (int i = 0; i < num_fds; i++) {
evt_listen_t *e = &l->q[i]; evt_listen_t *e = &l->q[i];
if (fds[i].revents & e->events) { if (async_exec(e, fds[i].revents) != 0)
// specified event(s) occurred
e->cb(e->arg);
if (e->flags & ASYNC_KEEP)
async_add_to_queue(e);
} else if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
// error occurred
e->err_cb(e->err_arg);
} else {
// no event occurred
async_add_to_queue(e); async_add_to_queue(e);
}
// reset errno to prevent strange behaviour
errno = 0;
} }
// reset size of queue // reset size of queue

View File

@@ -9,11 +9,15 @@
#ifndef SESIMOS_ASYNC_H #ifndef SESIMOS_ASYNC_H
#define SESIMOS_ASYNC_H #define SESIMOS_ASYNC_H
#include "lib/sock.h"
#include <poll.h> #include <poll.h>
#define ASYNC_KEEP 1 #define ASYNC_KEEP 1
int async(int fd, short events, int flags, void cb(void *), void *arg, void err_cb(void *), void *err_arg); int async(sock *s, short events, int flags, void cb(void *), void *arg, void err_cb(void *), void *err_arg);
int async_fd(int fd, short events, int flags, void cb(void *), void *arg, void err_cb(void *), void *err_arg);
void async_thread(void); void async_thread(void);

View File

@@ -37,7 +37,7 @@
#define HTTP_COLOR_ERROR "#C00000" #define HTTP_COLOR_ERROR "#C00000"
#define CLIENT_MAX_HEADER_SIZE 8192 #define CLIENT_MAX_HEADER_SIZE 8192
#define HTTP_MAX_HEADER_FIELD_NUM 64 #define HTTP_MAX_HEADER_FIELD_NUM 32
#ifndef SERVER_STR #ifndef SERVER_STR
# define SERVER_STR "sesimos" # define SERVER_STR "sesimos"
@@ -69,11 +69,11 @@ typedef struct {
char type; char type;
union { union {
struct { struct {
char name[64]; char name[32];
char value[192]; char value[32];
} normal; } normal;
struct { struct {
char name[192]; char name[64 - sizeof(char *)];
char *value; char *value;
} ex_value; } ex_value;
struct { struct {

View File

@@ -257,7 +257,7 @@ int main(int argc, char *const argv[]) {
workers_init(); workers_init();
for (int i = 0; i < NUM_SOCKETS; i++) { for (int i = 0; i < NUM_SOCKETS; i++) {
async(sockets[i], POLLIN, ASYNC_KEEP, accept_cb, &sockets[i], accept_err_cb, &sockets[i]); async_fd(sockets[i], POLLIN, ASYNC_KEEP, accept_cb, &sockets[i], accept_err_cb, &sockets[i]);
} }
notice("Ready to accept connections"); notice("Ready to accept connections");

View File

@@ -21,7 +21,7 @@ typedef struct {
unsigned char in_use: 1, s_keep_alive:1, c_keep_alive:1; unsigned char in_use: 1, s_keep_alive:1, c_keep_alive:1;
char cc[3], host[256]; char cc[3], host[256];
char req_host[256], err_msg[256]; char req_host[256], err_msg[256];
char log_prefix[512]; char log_prefix[128];
char _c_addr[INET6_ADDRSTRLEN + 1], _s_addr[INET6_ADDRSTRLEN + 1]; char _c_addr[INET6_ADDRSTRLEN + 1], _s_addr[INET6_ADDRSTRLEN + 1];
long cnx_s, cnx_e, req_s, res_ts, req_e; long cnx_s, cnx_e, req_s, res_ts, req_e;
http_req req; http_req req;
@@ -33,7 +33,7 @@ typedef struct {
host_config_t *conf; host_config_t *conf;
FILE *file; FILE *file;
long content_length; long content_length;
char msg_buf[8192], msg_content[1024]; char *msg_buf, *msg_buf_ptr, msg_content[1024];
proxy_ctx_t *proxy; proxy_ctx_t *proxy;
} client_ctx_t; } client_ctx_t;

View File

@@ -13,6 +13,7 @@
#include "../workers.h" #include "../workers.h"
#include <string.h> #include <string.h>
#include <errno.h>
static int local_handler(client_ctx_t *ctx); static int local_handler(client_ctx_t *ctx);
@@ -47,10 +48,12 @@ static int local_handler(client_ctx_t *ctx) {
res->status = http_get_status(200); res->status = http_get_status(200);
http_add_header_field(&res->hdr, "Content-Type", "message/http"); http_add_header_field(&res->hdr, "Content-Type", "message/http");
ctx->content_length = snprintf(ctx->msg_buf, sizeof(ctx->msg_buf) - ctx->content_length, "%s %s HTTP/%s\r\n", req->method, req->uri, req->version); ctx->msg_buf_ptr = malloc(4096);
ctx->msg_buf = ctx->msg_buf_ptr;
ctx->content_length = snprintf(ctx->msg_buf, 4096 - ctx->content_length, "%s %s HTTP/%s\r\n", req->method, req->uri, req->version);
for (int i = 0; i < req->hdr.field_num; i++) { for (int i = 0; i < req->hdr.field_num; i++) {
const http_field *f = &req->hdr.fields[i]; const http_field *f = &req->hdr.fields[i];
ctx->content_length += snprintf(ctx->msg_buf + ctx->content_length, sizeof(ctx->msg_buf) - ctx->content_length, "%s: %s\r\n", http_field_get_name(f), http_field_get_value(f)); ctx->content_length += snprintf(ctx->msg_buf + ctx->content_length, 4096 - ctx->content_length, "%s: %s\r\n", http_field_get_name(f), http_field_get_value(f));
} }
return 0; return 0;
@@ -110,6 +113,7 @@ static int local_handler(client_ctx_t *ctx) {
ctx->file = fopen(uri->meta->filename_comp_br, "rb"); ctx->file = fopen(uri->meta->filename_comp_br, "rb");
if (ctx->file == NULL) { if (ctx->file == NULL) {
cache_mark_dirty(ctx->conf->cache, uri->filename); cache_mark_dirty(ctx->conf->cache, uri->filename);
errno = 0;
} else { } else {
http_add_header_field(&res->hdr, "Content-Encoding", "br"); http_add_header_field(&res->hdr, "Content-Encoding", "br");
enc = COMPRESS_BR; enc = COMPRESS_BR;
@@ -118,6 +122,7 @@ static int local_handler(client_ctx_t *ctx) {
ctx->file = fopen(uri->meta->filename_comp_gz, "rb"); ctx->file = fopen(uri->meta->filename_comp_gz, "rb");
if (ctx->file == NULL) { if (ctx->file == NULL) {
cache_mark_dirty(ctx->conf->cache, uri->filename); cache_mark_dirty(ctx->conf->cache, uri->filename);
errno = 0;
} else { } else {
http_add_header_field(&res->hdr, "Content-Encoding", "gzip"); http_add_header_field(&res->hdr, "Content-Encoding", "gzip");
enc = COMPRESS_GZ; enc = COMPRESS_GZ;

View File

@@ -57,7 +57,8 @@ static int request_handler(client_ctx_t *ctx) {
ctx->use_proxy = 0; ctx->use_proxy = 0;
ctx->proxy = NULL; ctx->proxy = NULL;
ctx->msg_content[0] = 0; ctx->msg_content[0] = 0;
ctx->msg_buf[0] = 0; ctx->msg_buf = NULL;
ctx->msg_buf_ptr = NULL;
ctx->req_host[0] = 0; ctx->req_host[0] = 0;
ctx->err_msg[0] = 0; ctx->err_msg[0] = 0;
@@ -130,7 +131,7 @@ static int request_handler(client_ctx_t *ctx) {
info(BLD_STR "%s %s", req->method, req->uri); info(BLD_STR "%s %s", req->method, req->uri);
if (strcmp(req->uri, "/.sesimos/style.css") == 0 && (strcmp(req->method, "GET") == 0 || strcmp(req->method, "HEAD") == 0)) { if (strcmp(req->uri, "/.sesimos/style.css") == 0 && (strcmp(req->method, "GET") == 0 || strcmp(req->method, "HEAD") == 0)) {
memcpy(ctx->msg_buf, http_style_doc, http_style_doc_size); ctx->msg_buf = (char *) http_style_doc;
ctx->content_length = http_style_doc_size; ctx->content_length = http_style_doc_size;
res->status= http_get_status(200); res->status= http_get_status(200);
http_add_header_field(&res->hdr, "Content-Type", "text/css; charset=UTF-8"); http_add_header_field(&res->hdr, "Content-Type", "text/css; charset=UTF-8");
@@ -226,7 +227,7 @@ int respond(client_ctx_t *ctx) {
if (http_get_header_field(&res->hdr, "Accept-Ranges") == NULL) { if (http_get_header_field(&res->hdr, "Accept-Ranges") == NULL) {
http_add_header_field(&res->hdr, "Accept-Ranges", "none"); http_add_header_field(&res->hdr, "Accept-Ranges", "none");
} }
if (!ctx->use_fastcgi && ctx->file == NULL && ctx->msg_buf[0] == 0) { if (!ctx->use_fastcgi && ctx->file == NULL && ctx->msg_buf == NULL) {
http_remove_header_field(&res->hdr, "Date", HTTP_REMOVE_ALL); http_remove_header_field(&res->hdr, "Date", HTTP_REMOVE_ALL);
http_remove_header_field(&res->hdr, "Server", HTTP_REMOVE_ALL); http_remove_header_field(&res->hdr, "Server", HTTP_REMOVE_ALL);
http_remove_header_field(&res->hdr, "Cache-Control", HTTP_REMOVE_ALL); http_remove_header_field(&res->hdr, "Cache-Control", HTTP_REMOVE_ALL);
@@ -276,9 +277,11 @@ int respond(client_ctx_t *ctx) {
proxy_doc = msg_pre_buf_2; proxy_doc = msg_pre_buf_2;
} }
ctx->msg_buf_ptr = malloc(4096);
ctx->msg_buf = ctx->msg_buf_ptr;
snprintf(msg_pre_buf_1, sizeof(msg_pre_buf_1), http_info->doc, snprintf(msg_pre_buf_1, sizeof(msg_pre_buf_1), http_info->doc,
res->status->code, res->status->msg, http_msg != NULL ? http_msg->msg : "", err_msg[0] != 0 ? err_msg : ""); res->status->code, res->status->msg, http_msg != NULL ? http_msg->msg : "", err_msg[0] != 0 ? err_msg : "");
ctx->content_length = snprintf(ctx->msg_buf, sizeof(ctx->msg_buf), http_default_doc, res->status->code, ctx->content_length = snprintf(ctx->msg_buf, 4096, http_default_doc, res->status->code,
res->status->msg, msg_pre_buf_1, http_info->mode, http_info->icon, http_info->color, ctx->req_host, res->status->msg, msg_pre_buf_1, http_info->mode, http_info->icon, http_info->color, ctx->req_host,
proxy_doc, ctx->msg_content[0] != 0 ? ctx->msg_content : "", SERVER_STR_HTML); proxy_doc, ctx->msg_content[0] != 0 ? ctx->msg_content : "", SERVER_STR_HTML);
} }
@@ -328,7 +331,7 @@ int respond(client_ctx_t *ctx) {
// default response // default response
unsigned long snd_len = 0; unsigned long snd_len = 0;
unsigned long len; unsigned long len;
if (ctx->msg_buf[0] != 0) { if (ctx->msg_buf != NULL) {
ret = sock_send(client, ctx->msg_buf, ctx->content_length, 0); ret = sock_send(client, ctx->msg_buf, ctx->content_length, 0);
if (ret <= 0) { if (ret <= 0) {
error("Unable to send: %s", sock_strerror(client)); error("Unable to send: %s", sock_strerror(client));
@@ -372,6 +375,8 @@ void request_complete(client_ctx_t *ctx) {
ctx->req_e = clock_micros(); ctx->req_e = clock_micros();
info("Transfer complete: %s", format_duration(ctx->req_e - ctx->req_s, buf)); info("Transfer complete: %s", format_duration(ctx->req_e - ctx->req_s, buf));
if (ctx->file) fclose(ctx->file);
free(ctx->msg_buf_ptr);
uri_free(&ctx->uri); uri_free(&ctx->uri);
http_free_req(&ctx->req); http_free_req(&ctx->req);
http_free_res(&ctx->res); http_free_res(&ctx->res);

View File

@@ -50,7 +50,7 @@ static int handle_request_cb(client_ctx_t *ctx) {
int handle_request(client_ctx_t *ctx) { int handle_request(client_ctx_t *ctx) {
if (ctx->c_keep_alive && ctx->s_keep_alive) { if (ctx->c_keep_alive && ctx->s_keep_alive) {
return async(ctx->socket.socket, POLLIN, 0, (void (*)(void *)) handle_request_cb, ctx, (void (*)(void *)) tcp_close, ctx); return async(&ctx->socket, POLLIN, 0, (void (*)(void *)) handle_request_cb, ctx, (void (*)(void *)) tcp_close, ctx);
} else { } else {
tcp_close(ctx); tcp_close(ctx);
return 0; return 0;