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

View File

@@ -9,11 +9,15 @@
#ifndef SESIMOS_ASYNC_H
#define SESIMOS_ASYNC_H
#include "lib/sock.h"
#include <poll.h>
#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);

View File

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

View File

@@ -257,7 +257,7 @@ int main(int argc, char *const argv[]) {
workers_init();
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");

View File

@@ -21,7 +21,7 @@ typedef struct {
unsigned char in_use: 1, s_keep_alive:1, c_keep_alive:1;
char cc[3], host[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];
long cnx_s, cnx_e, req_s, res_ts, req_e;
http_req req;
@@ -33,7 +33,7 @@ typedef struct {
host_config_t *conf;
FILE *file;
long content_length;
char msg_buf[8192], msg_content[1024];
char *msg_buf, *msg_buf_ptr, msg_content[1024];
proxy_ctx_t *proxy;
} client_ctx_t;

View File

@@ -13,6 +13,7 @@
#include "../workers.h"
#include <string.h>
#include <errno.h>
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);
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++) {
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;
@@ -110,6 +113,7 @@ static int local_handler(client_ctx_t *ctx) {
ctx->file = fopen(uri->meta->filename_comp_br, "rb");
if (ctx->file == NULL) {
cache_mark_dirty(ctx->conf->cache, uri->filename);
errno = 0;
} else {
http_add_header_field(&res->hdr, "Content-Encoding", "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");
if (ctx->file == NULL) {
cache_mark_dirty(ctx->conf->cache, uri->filename);
errno = 0;
} else {
http_add_header_field(&res->hdr, "Content-Encoding", "gzip");
enc = COMPRESS_GZ;

View File

@@ -57,7 +57,8 @@ static int request_handler(client_ctx_t *ctx) {
ctx->use_proxy = 0;
ctx->proxy = NULL;
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->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);
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;
res->status= http_get_status(200);
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) {
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, "Server", 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;
}
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,
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,
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
unsigned long snd_len = 0;
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);
if (ret <= 0) {
error("Unable to send: %s", sock_strerror(client));
@@ -372,6 +375,8 @@ void request_complete(client_ctx_t *ctx) {
ctx->req_e = clock_micros();
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);
http_free_req(&ctx->req);
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) {
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 {
tcp_close(ctx);
return 0;