Compare commits
6 Commits
a54a6af497
...
896486b64a
Author | SHA1 | Date | |
---|---|---|---|
896486b64a
|
|||
c1706edcea
|
|||
f8d3253a9f
|
|||
ec3183e99b
|
|||
27d514ae12
|
|||
e82869e993
|
4
Makefile
4
Makefile
@@ -58,8 +58,10 @@ bin/res/%.txt: res/%.*
|
||||
bin/sesimos: bin/server.o bin/logger.o bin/cache_handler.o bin/async.o bin/workers.o \
|
||||
bin/worker/request_handler.o bin/worker/tcp_acceptor.o \
|
||||
bin/worker/fastcgi_handler.o bin/worker/local_handler.o bin/worker/proxy_handler.o \
|
||||
bin/worker/ws_frame_handler.o \
|
||||
bin/lib/http_static.o bin/res/default.o bin/res/proxy.o bin/res/style.o \
|
||||
bin/res/icon_error.o bin/res/icon_info.o bin/res/icon_success.o bin/res/icon_warning.o \
|
||||
bin/res/globe.o \
|
||||
bin/lib/compress.o bin/lib/config.o bin/lib/fastcgi.o bin/lib/geoip.o \
|
||||
bin/lib/http.o bin/lib/proxy.o bin/lib/sock.o bin/lib/uri.o \
|
||||
bin/lib/utils.o bin/lib/websocket.o bin/lib/mpmc.o bin/lib/list.o
|
||||
@@ -87,6 +89,8 @@ bin/worker/local_handler.o: src/worker/func.h
|
||||
|
||||
bin/worker/proxy_handler.o: src/worker/func.h
|
||||
|
||||
bin/worker/ws_frame_handler.o: src/worker/func.h
|
||||
|
||||
bin/lib/compress.o: src/lib/compress.h
|
||||
|
||||
bin/lib/config.o: src/lib/config.h src/lib/utils.h src/lib/uri.h src/logger.h
|
||||
|
3
res/globe.svg
Normal file
3
res/globe.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="64" height="64" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2,32 a30,30,0,1,0,60,0 a30,30,0,1,0,-60,0 L62,32 M6,16 L58,16 M6,48 L58,48 M32,2 L32,62 a15,30,0,1,0,0,-60 a15,30,0,1,0,0,60 Z" stroke="#008000" stroke-width="2" fill="#00000000"/>
|
||||
</svg>
|
After Width: | Height: | Size: 266 B |
@@ -2,7 +2,7 @@
|
||||
<div class="box%1$s">
|
||||
<div class="content">
|
||||
<span>Client</span>
|
||||
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIsMzIgYTMwLDMwLDAsMSwwLDYwLDAgYTMwLDMwLDAsMSwwLC02MCwwIEw2MiwzMiBNNiwxNiBMNTgsMTYgTTYsNDggTDU4LDQ4IE0zMiwyIEwzMiw2MiBhMTUsMzAsMCwxLDAsMCwtNjAgYTE1LDMwLDAsMSwwLDAsNjAgWiIgc3Ryb2tlPSIjMDA4MDAwIiBzdHJva2Utd2lkdGg9IjIiIGZpbGw9IiMwMDAwMDAwMCIvPjwvc3ZnPgo="/>
|
||||
<img src="/.sesimos/res/globe.svg"/>
|
||||
<span>Your Browser</span>
|
||||
</div>
|
||||
<div class="arrow request%2$s"></div>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#ifndef SESIMOS_DEF_H
|
||||
#define SESIMOS_DEF_H
|
||||
|
||||
#define SERVER_VERSION "4.6"
|
||||
#define SERVER_VERSION "5.0-wip"
|
||||
#define SERVER_STR "sesimos/" SERVER_VERSION
|
||||
#define SERVER_STR_HTML "sesimos web server " SERVER_VERSION
|
||||
|
||||
|
@@ -9,12 +9,11 @@
|
||||
#include "fastcgi.h"
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
#include "../server.h"
|
||||
#include "../logger.h"
|
||||
#include "list.h"
|
||||
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -154,7 +153,7 @@ int fastcgi_init(fastcgi_cnx_t *conn, int mode, unsigned int req_num, const sock
|
||||
// param_ptr = fastcgi_add_param(param_ptr, "REMOTE_INFO", conn->ctx->geoip);
|
||||
//}
|
||||
|
||||
for (int i = 0; i < req->hdr.field_num; i++) {
|
||||
for (int i = 0; i < list_size(&req->hdr); i++) {
|
||||
const http_field *f = &req->hdr.fields[i];
|
||||
const char *name = http_field_get_name(f);
|
||||
char *ptr = buf0;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "http.h"
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
#include "list.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -69,10 +70,10 @@ void http_free_field(http_field *f) {
|
||||
}
|
||||
|
||||
void http_free_hdr(http_hdr *hdr) {
|
||||
for (int i = 0; i < hdr->field_num; i++) {
|
||||
for (int i = 0; i < list_size(hdr->fields); i++) {
|
||||
http_free_field(&hdr->fields[i]);
|
||||
}
|
||||
hdr->field_num = 0;
|
||||
list_free(hdr->fields);
|
||||
hdr->last_field_num = -1;
|
||||
}
|
||||
|
||||
@@ -86,8 +87,16 @@ void http_free_res(http_res *res) {
|
||||
http_free_hdr(&res->hdr);
|
||||
}
|
||||
|
||||
int http_init_hdr(http_hdr *hdr) {
|
||||
hdr->fields = list_create(sizeof(http_field), HTTP_INIT_HEADER_FIELD_NUM);
|
||||
if (hdr->fields == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr, int flags) {
|
||||
if (hdr->last_field_num > hdr->field_num) {
|
||||
if (hdr->last_field_num > list_size(hdr->fields)) {
|
||||
error("Unable to parse header: Invalid state");
|
||||
return 3;
|
||||
}
|
||||
@@ -117,7 +126,7 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr,
|
||||
str_trim_lws(&pos1, &pos2);
|
||||
long len2 = pos2 - pos1;
|
||||
|
||||
char field_num = hdr->field_num;
|
||||
int field_num = list_size(hdr->fields);
|
||||
int found = http_get_header_field_num_len(hdr, buf, len1);
|
||||
if (!(flags & HTTP_MERGE_FIELDS) || found == -1) {
|
||||
if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0) {
|
||||
@@ -125,12 +134,12 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr,
|
||||
return 3;
|
||||
}
|
||||
} else {
|
||||
field_num = (char) found;
|
||||
field_num = found;
|
||||
http_append_to_header_field(&hdr->fields[found], ", ", 2);
|
||||
http_append_to_header_field(&hdr->fields[found], pos1, len2);
|
||||
}
|
||||
|
||||
hdr->last_field_num = (char) field_num;
|
||||
hdr->last_field_num = field_num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -142,8 +151,8 @@ int http_receive_request(sock *client, http_req *req) {
|
||||
memset(req->method, 0, sizeof(req->method));
|
||||
memset(req->version, 0, sizeof(req->version));
|
||||
req->uri = NULL;
|
||||
req->hdr.field_num = 0;
|
||||
req->hdr.last_field_num = -1;
|
||||
http_init_hdr(&req->hdr);
|
||||
|
||||
while (1) {
|
||||
rcv_len = sock_recv(client, buf, CLIENT_MAX_HEADER_SIZE, MSG_PEEK);
|
||||
@@ -228,7 +237,7 @@ const char *http_get_header_field(const http_hdr *hdr, const char *field_name) {
|
||||
|
||||
const char *http_get_header_field_len(const http_hdr *hdr, const char *field_name, unsigned long len) {
|
||||
int num = http_get_header_field_num_len(hdr, field_name, len);
|
||||
return (num >= 0 && num < HTTP_MAX_HEADER_FIELD_NUM) ? http_field_get_value(&hdr->fields[num]) : NULL;
|
||||
return (num >= 0 && num < list_size(hdr->fields)) ? http_field_get_value(&hdr->fields[num]) : NULL;
|
||||
}
|
||||
|
||||
int http_get_header_field_num(const http_hdr *hdr, const char *field_name) {
|
||||
@@ -241,7 +250,7 @@ int http_get_header_field_num_len(const http_hdr *hdr, const char *field_name, u
|
||||
field_name_1[len] = 0;
|
||||
http_to_camel_case(field_name_1, HTTP_LOWER);
|
||||
|
||||
for (int i = 0; i < hdr->field_num; i++) {
|
||||
for (int i = 0; i < list_size(hdr->fields); i++) {
|
||||
strcpy(field_name_2, http_field_get_name(&hdr->fields[i]));
|
||||
http_to_camel_case(field_name_2, HTTP_LOWER);
|
||||
|
||||
@@ -257,10 +266,8 @@ int http_add_header_field(http_hdr *hdr, const char *field_name, const char *fie
|
||||
}
|
||||
|
||||
int http_add_header_field_len(http_hdr *hdr, const char *name, unsigned long name_len, const char *value, unsigned long value_len) {
|
||||
if (hdr->field_num >= HTTP_MAX_HEADER_FIELD_NUM)
|
||||
return -1;
|
||||
|
||||
http_field *f = &hdr->fields[(int) hdr->field_num];
|
||||
http_field *f;
|
||||
hdr->fields = list_append_ptr(hdr->fields, (void **) &f);
|
||||
|
||||
if (name_len < sizeof(f->normal.name) && value_len < sizeof(f->normal.value)) {
|
||||
f->type = HTTP_FIELD_NORMAL;
|
||||
@@ -288,7 +295,6 @@ int http_add_header_field_len(http_hdr *hdr, const char *name, unsigned long nam
|
||||
http_to_camel_case(f->ex_name.name, HTTP_PRESERVE);
|
||||
}
|
||||
|
||||
hdr->field_num++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -321,16 +327,15 @@ void http_remove_header_field(http_hdr *hdr, const char *field_name, int mode) {
|
||||
int i = 0;
|
||||
int diff = 1;
|
||||
if (mode == HTTP_REMOVE_LAST) {
|
||||
i = hdr->field_num - 1;
|
||||
i = list_size(hdr->fields) - 1;
|
||||
diff = -1;
|
||||
}
|
||||
for (; i < hdr->field_num && i >= 0; i += diff) {
|
||||
for (; i < list_size(hdr->fields) && i >= 0; i += diff) {
|
||||
strcpy(field_name_2, http_field_get_name(&hdr->fields[i]));
|
||||
http_to_camel_case(field_name_2, HTTP_LOWER);
|
||||
if (strcmp(field_name_1, field_name_2) == 0) {
|
||||
http_free_field(&hdr->fields[i]);
|
||||
memmove(&hdr->fields[i], &hdr->fields[i + 1], sizeof(hdr->fields[0]) * (hdr->field_num - i));
|
||||
hdr->field_num--;
|
||||
list_remove(hdr->fields, i);
|
||||
if (mode == HTTP_REMOVE_ALL) {
|
||||
i -= diff;
|
||||
} else {
|
||||
@@ -343,7 +348,7 @@ void http_remove_header_field(http_hdr *hdr, const char *field_name, int mode) {
|
||||
int http_send_response(sock *client, http_res *res) {
|
||||
char buf[CLIENT_MAX_HEADER_SIZE];
|
||||
long off = sprintf(buf, "HTTP/%s %03i %s\r\n", res->version, res->status->code, res->status->msg);
|
||||
for (int i = 0; i < res->hdr.field_num; i++) {
|
||||
for (int i = 0; i < list_size(res->hdr.fields); i++) {
|
||||
const http_field *f = &res->hdr.fields[i];
|
||||
off += sprintf(buf + off, "%s: %s\r\n", http_field_get_name(f), http_field_get_value(f));
|
||||
}
|
||||
@@ -357,7 +362,7 @@ int http_send_response(sock *client, http_res *res) {
|
||||
int http_send_request(sock *server, http_req *req) {
|
||||
char buf[CLIENT_MAX_HEADER_SIZE];
|
||||
long off = sprintf(buf, "%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 < list_size(req->hdr.fields); i++) {
|
||||
const http_field *f = &req->hdr.fields[i];
|
||||
off += sprintf(buf + off, "%s: %s\r\n", http_field_get_name(f), http_field_get_value(f));
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@
|
||||
#define HTTP_COLOR_ERROR "#C00000"
|
||||
|
||||
#define CLIENT_MAX_HEADER_SIZE 8192
|
||||
#define HTTP_MAX_HEADER_FIELD_NUM 32
|
||||
#define HTTP_INIT_HEADER_FIELD_NUM 16
|
||||
|
||||
#ifndef SERVER_STR
|
||||
# define SERVER_STR "sesimos"
|
||||
@@ -84,9 +84,8 @@ typedef struct {
|
||||
} http_field;
|
||||
|
||||
typedef struct {
|
||||
char field_num;
|
||||
char last_field_num;
|
||||
http_field fields[HTTP_MAX_HEADER_FIELD_NUM];
|
||||
int last_field_num;
|
||||
http_field *fields;
|
||||
} http_hdr;
|
||||
|
||||
typedef struct {
|
||||
@@ -125,6 +124,8 @@ const char *http_field_get_name(const http_field *field);
|
||||
|
||||
const char *http_field_get_value(const http_field *field);
|
||||
|
||||
int http_init_hdr(http_hdr *hdr);
|
||||
|
||||
void http_free_field(http_field *f);
|
||||
|
||||
void http_free_hdr(http_hdr *hdr);
|
||||
|
@@ -217,13 +217,14 @@ int proxy_response_header(http_req *req, http_res *res, host_config_t *conf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config_t *conf, sock *client, http_status *custom_status, char *err_msg) {
|
||||
int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_status_ctx *ctx, host_config_t *conf, sock *client, http_status *custom_status, char *err_msg) {
|
||||
char buffer[CHUNK_SIZE];
|
||||
const char *connection, *upgrade, *ws_version;
|
||||
long ret;
|
||||
int tries = 0, retry = 0;
|
||||
|
||||
proxy_ctx_t *proxy = proxy_get_by_conf(conf);
|
||||
*proxy_ptr = proxy_get_by_conf(conf);
|
||||
proxy_ctx_t *proxy = *proxy_ptr;
|
||||
proxy->in_use = 1;
|
||||
|
||||
if (proxy->initialized && sock_has_pending(&proxy->proxy) == 0)
|
||||
@@ -243,7 +244,7 @@ proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host
|
||||
error("Unable to create socket");
|
||||
res->status = http_get_status(500);
|
||||
ctx->origin = INTERNAL;
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sock_set_timeout(&proxy->proxy, SERVER_TIMEOUT_INIT) != 0)
|
||||
@@ -331,7 +332,7 @@ proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host
|
||||
} else {
|
||||
res->status = http_get_status(501);
|
||||
ctx->origin = INTERNAL;
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
|
||||
@@ -342,7 +343,7 @@ proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host
|
||||
if (ret != 0) {
|
||||
res->status = http_get_status(500);
|
||||
ctx->origin = INTERNAL;
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = http_send_request(&proxy->proxy, req);
|
||||
@@ -379,12 +380,12 @@ proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host
|
||||
ctx->origin = CLIENT_REQ;
|
||||
error("Unable to receive request from client: %s", sock_strerror(client));
|
||||
sprintf(err_msg, "Unable to receive request from client: %s.", sock_strerror(client));
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
res->status = http_get_status(500);
|
||||
ctx->origin = INTERNAL;
|
||||
error("Unknown Error");
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sock_recv(&proxy->proxy, buffer, sizeof(buffer), MSG_PEEK);
|
||||
@@ -480,15 +481,15 @@ proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host
|
||||
if (ret != 0) {
|
||||
res->status = http_get_status(500);
|
||||
ctx->origin = INTERNAL;
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return proxy;
|
||||
return 0;
|
||||
|
||||
proxy_err:
|
||||
errno = 0;
|
||||
if (retry) goto retry;
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int flags) {
|
||||
|
@@ -35,7 +35,7 @@ int proxy_request_header(http_req *req, sock *sock);
|
||||
|
||||
int proxy_response_header(http_req *req, http_res *res, host_config_t *conf);
|
||||
|
||||
proxy_ctx_t *proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config_t *conf, sock *client, http_status *custom_status, char *err_msg);
|
||||
int proxy_init(proxy_ctx_t **proxy, http_req *req, http_res *res, http_status_ctx *ctx, host_config_t *conf, sock *client, http_status *custom_status, char *err_msg);
|
||||
|
||||
int proxy_send(proxy_ctx_t *proxy, sock *client, unsigned long len_to_send, int flags);
|
||||
|
||||
|
@@ -25,6 +25,9 @@
|
||||
#define http_icon_warning _binary_bin_res_icon_warning_txt_start
|
||||
#define http_icon_warning_size ((unsigned int) (_binary_bin_res_icon_warning_txt_end - _binary_bin_res_icon_warning_txt_start) - 1)
|
||||
|
||||
#define http_icon_globe _binary_bin_res_globe_txt_start
|
||||
#define http_icon_globe_size ((unsigned int) (_binary_bin_res_globe_txt_end - _binary_bin_res_globe_txt_start) - 1)
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *type;
|
||||
@@ -53,4 +56,7 @@ extern const char _binary_bin_res_icon_success_txt_end[];
|
||||
extern const char _binary_bin_res_icon_warning_txt_start[];
|
||||
extern const char _binary_bin_res_icon_warning_txt_end[];
|
||||
|
||||
extern const char _binary_bin_res_globe_txt_start[];
|
||||
extern const char _binary_bin_res_globe_txt_end[];
|
||||
|
||||
#endif //SESIMOS_RES_H
|
||||
|
@@ -6,22 +6,14 @@
|
||||
* @date 2022-08-16
|
||||
*/
|
||||
|
||||
#include "../defs.h"
|
||||
#include "../logger.h"
|
||||
#include "websocket.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
static const char ws_key_uuid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
static volatile sig_atomic_t terminate = 0;
|
||||
|
||||
void ws_terminate(int _) {
|
||||
terminate = 1;
|
||||
}
|
||||
|
||||
int ws_calc_accept_key(const char *key, char *accept_key) {
|
||||
if (key == NULL || accept_key == NULL)
|
||||
@@ -144,65 +136,3 @@ int ws_send_frame_header(sock *s, ws_frame *frame) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_handle_connection(sock *s1, sock *s2) {
|
||||
sock *poll_socks[2] = {s1, s2};
|
||||
sock *readable[2], *error[2];
|
||||
int n_sock = 2, n_readable = 0, n_error = 0;
|
||||
ws_frame frame;
|
||||
char buf[CHUNK_SIZE];
|
||||
int closes = 0;
|
||||
long ret;
|
||||
|
||||
signal(SIGINT, ws_terminate);
|
||||
signal(SIGTERM, ws_terminate);
|
||||
|
||||
while (!terminate && closes != 3) {
|
||||
ret = sock_poll_read(poll_socks, readable, error, n_sock, &n_readable, &n_error, WS_TIMEOUT * 1000);
|
||||
if (terminate) {
|
||||
break;
|
||||
} else if (ret < 0) {
|
||||
error("Unable to poll sockets");
|
||||
return -1;
|
||||
} else if (n_readable == 0) {
|
||||
error("Connection timed out");
|
||||
return -2;
|
||||
} else if (n_error > 0) {
|
||||
error("Peer closed connection");
|
||||
return -3;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_readable; i++) {
|
||||
sock *s = readable[i];
|
||||
sock *o = (s == s1) ? s2 : s1;
|
||||
if (ws_recv_frame_header(s, &frame) != 0) return -3;
|
||||
|
||||
// debug("WebSocket: Peer %s, Opcode=0x%X, Len=%li", (s == s1) ? "1" : "2", frame.opcode, frame.len);
|
||||
|
||||
if (frame.opcode == 0x8) {
|
||||
n_sock--;
|
||||
if (s == s1) {
|
||||
poll_socks[0] = s2;
|
||||
closes |= 1;
|
||||
} else {
|
||||
closes |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (ws_send_frame_header(o, &frame) != 0) return -3;
|
||||
|
||||
if (frame.len > 0) {
|
||||
ret = sock_splice(o, s, buf, sizeof(buf), frame.len);
|
||||
if (ret < 0) {
|
||||
error("Unable to forward data in WebSocket");
|
||||
return -4;
|
||||
} else if (ret != frame.len) {
|
||||
error("Unable to forward correct number of bytes in WebSocket");
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -30,6 +30,4 @@ int ws_recv_frame_header(sock *s, ws_frame *frame);
|
||||
|
||||
int ws_send_frame_header(sock *s, ws_frame *frame);
|
||||
|
||||
int ws_handle_connection(sock *s1, sock *s2);
|
||||
|
||||
#endif //SESIMOS_WEBSOCKET_H
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#define CLIENT_TIMEOUT 3600
|
||||
#define SERVER_TIMEOUT_INIT 4
|
||||
#define SERVER_TIMEOUT 3600
|
||||
#define MAX_CLIENTS 4096
|
||||
|
||||
#define CNX_HANDLER_WORKERS 8
|
||||
#define REQ_HANDLER_WORKERS 16
|
||||
|
@@ -38,7 +38,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
client_ctx_t *client;
|
||||
sock *s1, *s2, *s, *r;
|
||||
sock *socket;
|
||||
void *other;
|
||||
} ws_ctx_t;
|
||||
|
||||
void tcp_acceptor_func(client_ctx_t *ctx);
|
||||
@@ -61,4 +62,8 @@ void tcp_close(client_ctx_t *ctx);
|
||||
|
||||
void proxy_close(proxy_ctx_t *ctx);
|
||||
|
||||
int ws_handle_connection(client_ctx_t *ctx);
|
||||
|
||||
void ws_close(ws_ctx_t *ctx);
|
||||
|
||||
#endif //SESIMOS_FUNC_H
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "../lib/utils.h"
|
||||
#include "../lib/compress.h"
|
||||
#include "../workers.h"
|
||||
#include "../lib/list.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -51,7 +52,7 @@ static int local_handler(client_ctx_t *ctx) {
|
||||
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 < list_size(&req->hdr); i++) {
|
||||
const http_field *f = &req->hdr.fields[i];
|
||||
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));
|
||||
}
|
||||
|
@@ -25,19 +25,17 @@ void proxy_handler_func(client_ctx_t *ctx) {
|
||||
proxy_handler_1(ctx);
|
||||
respond(ctx);
|
||||
|
||||
if (ctx->use_proxy == 2) {
|
||||
if (ctx->use_proxy == 0) {
|
||||
proxy_close(ctx->proxy);
|
||||
} else if (ctx->use_proxy == 1) {
|
||||
proxy_handler_2(ctx);
|
||||
} else if (ctx->use_proxy == 2) {
|
||||
// WebSocket
|
||||
info("Upgrading connection to WebSocket connection");
|
||||
if (ws_handle_connection(&ctx->socket, &ctx->proxy->proxy) != 0) {
|
||||
ctx->c_keep_alive = 0;
|
||||
proxy_close(ctx->proxy);
|
||||
}
|
||||
info("WebSocket connection closed");
|
||||
ws_handle_connection(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
proxy_handler_2(ctx);
|
||||
request_complete(ctx);
|
||||
|
||||
handle_request(ctx);
|
||||
}
|
||||
|
||||
@@ -51,8 +49,7 @@ static int proxy_handler_1(client_ctx_t *ctx) {
|
||||
http_remove_header_field(&res->hdr, "Date", HTTP_REMOVE_ALL);
|
||||
http_remove_header_field(&res->hdr, "Server", HTTP_REMOVE_ALL);
|
||||
|
||||
ctx->proxy = proxy_init(&ctx->req, res, status, ctx->conf, &ctx->socket, &ctx->custom_status, ctx->err_msg);
|
||||
ctx->use_proxy = (ctx->proxy != NULL);
|
||||
ctx->use_proxy = proxy_init(&ctx->proxy, &ctx->req, res, status, ctx->conf, &ctx->socket, &ctx->custom_status, ctx->err_msg) == 0;
|
||||
|
||||
if (res->status->code == 101) {
|
||||
const char *connection = http_get_header_field(&res->hdr, "Connection");
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "../lib/mpmc.h"
|
||||
#include "../logger.h"
|
||||
#include "../lib/utils.h"
|
||||
#include "../lib/websocket.h"
|
||||
#include "../server.h"
|
||||
#include "../lib/res.h"
|
||||
|
||||
@@ -55,6 +54,7 @@ static int request_handler(client_ctx_t *ctx) {
|
||||
ctx->proxy = NULL;
|
||||
ctx->use_fastcgi = 0;
|
||||
ctx->use_proxy = 0;
|
||||
ctx->ws_close = 0;
|
||||
ctx->proxy = NULL;
|
||||
ctx->msg_content[0] = 0;
|
||||
ctx->msg_buf = NULL;
|
||||
@@ -64,7 +64,7 @@ static int request_handler(client_ctx_t *ctx) {
|
||||
|
||||
http_res *res = &ctx->res;
|
||||
res->status = http_get_status(501);
|
||||
res->hdr.field_num = 0;
|
||||
http_init_hdr(&res->hdr);
|
||||
res->hdr.last_field_num = -1;
|
||||
sprintf(res->version, "1.1");
|
||||
|
||||
@@ -143,6 +143,7 @@ static int request_handler(client_ctx_t *ctx) {
|
||||
{"icon-info.svg", "image/svg+xml; charset=UTF-8", http_icon_info, http_icon_info_size},
|
||||
{"icon-success.svg", "image/svg+xml; charset=UTF-8", http_icon_success, http_icon_success_size},
|
||||
{"icon-warning.svg", "image/svg+xml; charset=UTF-8", http_icon_warning, http_icon_warning_size},
|
||||
{"globe.svg", "image/svg+xml; charset=UTF-8", http_icon_globe, http_icon_globe_size},
|
||||
};
|
||||
|
||||
res->status = http_get_status(404);
|
||||
@@ -362,6 +363,7 @@ int respond(client_ctx_t *ctx) {
|
||||
snd_len += ret;
|
||||
}
|
||||
} else if (ctx->use_fastcgi) {
|
||||
// FastCGI
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@@ -6,15 +6,89 @@
|
||||
* @date 2022-12-30
|
||||
*/
|
||||
|
||||
#include "../defs.h"
|
||||
#include "func.h"
|
||||
#include "../logger.h"
|
||||
#include "../lib/websocket.h"
|
||||
#include "../workers.h"
|
||||
#include <errno.h>
|
||||
|
||||
static int ws_frame_handler(ws_ctx_t *ctx);
|
||||
|
||||
void ws_frame_handler_func(ws_ctx_t *ctx) {
|
||||
logger_set_prefix("[%*s]%s", INET6_ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix);
|
||||
|
||||
if (ws_frame_handler(ctx) == 0) {
|
||||
if (ctx->client->ws_close == 3) {
|
||||
ws_close(ctx);
|
||||
} else {
|
||||
ws_handle_frame(ctx);
|
||||
}
|
||||
} else {
|
||||
ws_close(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int ws_handle_connection(client_ctx_t *ctx) {
|
||||
info("Upgrading to WebSocket connection");
|
||||
sock_set_timeout(&ctx->socket, WS_TIMEOUT);
|
||||
sock_set_timeout(&ctx->proxy->proxy, WS_TIMEOUT);
|
||||
|
||||
ws_ctx_t *a = malloc(sizeof(ws_ctx_t));
|
||||
ws_ctx_t *b = malloc(sizeof(ws_ctx_t));
|
||||
|
||||
a->other = b, b->other = a;
|
||||
a->client = ctx, b->client = ctx;
|
||||
a->socket = &ctx->socket, b->socket = &ctx->proxy->proxy;
|
||||
|
||||
ws_handle_frame(a);
|
||||
ws_handle_frame(b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ws_frame_handler(ws_ctx_t *ctx) {
|
||||
// TODO WebSocket Frame Handler
|
||||
ws_frame frame;
|
||||
char buf[CHUNK_SIZE];
|
||||
|
||||
sock *socket = ctx->socket;
|
||||
sock *other = (ctx->socket == &ctx->client->socket) ? &ctx->client->proxy->proxy : &ctx->client->socket;
|
||||
|
||||
if (ws_recv_frame_header(socket, &frame) != 0)
|
||||
return -1;
|
||||
|
||||
debug("WebSocket: Peer %s, Opcode=0x%X, Len=%li", (ctx->socket == &ctx->client->socket) ? "1" : "2", frame.opcode, frame.len);
|
||||
|
||||
if (frame.opcode == 0x8) {
|
||||
ctx->client->ws_close |= (ctx->socket == &ctx->client->socket) ? 1 : 2;
|
||||
}
|
||||
|
||||
if (ws_send_frame_header(other, &frame) != 0)
|
||||
return -1;
|
||||
|
||||
if (frame.len > 0) {
|
||||
long ret = sock_splice(other, socket, buf, sizeof(buf), frame.len);
|
||||
if (ret < 0) {
|
||||
error("Unable to forward data in WebSocket");
|
||||
return -1;
|
||||
} else if (ret != frame.len) {
|
||||
error("Unable to forward correct number of bytes in WebSocket");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ws_close(ws_ctx_t *ctx) {
|
||||
ws_ctx_t *other = ctx->other;
|
||||
if (other) {
|
||||
other->other = NULL;
|
||||
logger_set_prefix("[%*s]%s", INET6_ADDRSTRLEN, ctx->client->socket.s_addr, ctx->client->log_prefix);
|
||||
info("Closing WebSocket connection");
|
||||
proxy_close(ctx->client->proxy);
|
||||
tcp_close(ctx->client);
|
||||
}
|
||||
free(ctx);
|
||||
errno = 0;
|
||||
}
|
||||
|
@@ -12,15 +12,16 @@
|
||||
#include "worker/func.h"
|
||||
#include "async.h"
|
||||
|
||||
static mpmc_t tcp_acceptor_ctx, request_handler_ctx,
|
||||
local_handler_ctx, fastcgi_handler_cxt, proxy_handler_ctx;
|
||||
static mpmc_t tcp_acceptor_ctx, request_handler_ctx, local_handler_ctx, fastcgi_handler_cxt, proxy_handler_ctx,
|
||||
ws_frame_handler_ctx;
|
||||
|
||||
int workers_init(void) {
|
||||
mpmc_init(&tcp_acceptor_ctx, 8, 64, (void (*)(void *)) tcp_acceptor_func, "tcp");
|
||||
mpmc_init(&request_handler_ctx, 16, 64, (void (*)(void *)) request_handler_func, "req");
|
||||
mpmc_init(&local_handler_ctx, 16, 64, (void (*)(void *)) local_handler_func, "local");
|
||||
mpmc_init(&fastcgi_handler_cxt, 16, 64, (void (*)(void *)) fastcgi_handler_func, "fcgi");
|
||||
mpmc_init(&proxy_handler_ctx, 16, 64, (void (*)(void *)) proxy_handler_func, "proxy");
|
||||
mpmc_init(&tcp_acceptor_ctx, 8, 64, (void (*)(void *)) tcp_acceptor_func, "tcp");
|
||||
mpmc_init(&request_handler_ctx, 16, 64, (void (*)(void *)) request_handler_func, "req");
|
||||
mpmc_init(&local_handler_ctx, 16, 64, (void (*)(void *)) local_handler_func, "local");
|
||||
mpmc_init(&fastcgi_handler_cxt, 16, 64, (void (*)(void *)) fastcgi_handler_func, "fcgi");
|
||||
mpmc_init(&proxy_handler_ctx, 16, 64, (void (*)(void *)) proxy_handler_func, "proxy");
|
||||
mpmc_init(&ws_frame_handler_ctx, 16, 64, (void (*)(void *)) ws_frame_handler_func, "ws");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -30,6 +31,7 @@ void workers_stop(void) {
|
||||
mpmc_stop(&fastcgi_handler_cxt);
|
||||
mpmc_stop(&proxy_handler_ctx);
|
||||
mpmc_stop(&request_handler_ctx);
|
||||
mpmc_stop(&ws_frame_handler_ctx);
|
||||
}
|
||||
|
||||
void workers_destroy(void) {
|
||||
@@ -38,6 +40,7 @@ void workers_destroy(void) {
|
||||
mpmc_destroy(&fastcgi_handler_cxt);
|
||||
mpmc_destroy(&proxy_handler_ctx);
|
||||
mpmc_destroy(&request_handler_ctx);
|
||||
mpmc_destroy(&ws_frame_handler_ctx);
|
||||
}
|
||||
|
||||
int tcp_accept(client_ctx_t *ctx) {
|
||||
@@ -68,3 +71,11 @@ int fastcgi_handle(client_ctx_t *ctx) {
|
||||
int proxy_handle(client_ctx_t *ctx) {
|
||||
return mpmc_queue(&proxy_handler_ctx, ctx);
|
||||
}
|
||||
|
||||
static int ws_handle_frame_cb(ws_ctx_t *ctx) {
|
||||
return mpmc_queue(&ws_frame_handler_ctx, ctx);
|
||||
}
|
||||
|
||||
int ws_handle_frame(ws_ctx_t *ctx) {
|
||||
return async(ctx->socket, POLLIN, 0, (void (*)(void *)) ws_handle_frame_cb, ctx, (void (*)(void *)) ws_close, ctx);
|
||||
}
|
||||
|
@@ -27,4 +27,6 @@ int fastcgi_handle(client_ctx_t *ctx);
|
||||
|
||||
int proxy_handle(client_ctx_t *ctx);
|
||||
|
||||
int ws_handle_frame(ws_ctx_t *ctx);
|
||||
|
||||
#endif //SESIMOS_WORKERS_H
|
||||
|
Reference in New Issue
Block a user