Files

300 lines
6.3 KiB
C++
Raw Permalink Normal View History

2025-03-02 16:15:54 -07:00
#include "server.h"
#include "debug_utility.h"
2025-03-02 16:48:19 -07:00
#include "socket_utility.h"
2025-02-26 20:54:23 -07:00
#include <xtl.h>
#include <winsockx.h>
2025-02-27 09:51:38 -07:00
#include <stdio.h>
2026-01-30 20:01:50 -05:00
#include <string.h>
2025-03-02 16:48:19 -07:00
#include <bearssl.h>
2025-02-26 20:54:23 -07:00
#if !(SERVER_RSA || SERVER_EC || SERVER_MIXED)
#define SERVER_RSA 1
#define SERVER_EC 0
#define SERVER_MIXED 0
#endif
#if SERVER_RSA
#include "chain-rsa.h"
#include "key-rsa.h"
#define SKEY RSA
#elif SERVER_EC
#include "chain-ec.h"
#include "key-ec.h"
#define SKEY EC
#elif SERVER_MIXED
#include "chain-ec+rsa.h"
#include "key-ec.h"
#define SKEY EC
#else
#error Must use one of RSA, EC or MIXED chains.
#endif
2025-03-03 12:21:16 -07:00
#define MAX_NUM_THREADS 5
typedef struct {
int client_socket;
int thread_complete;
uint16_t port;
} thread_info_t;
typedef struct {
int active;
thread_info_t data;
HANDLE thread;
} pthread_info_t;
static pthread_info_t threads[MAX_NUM_THREADS];
2026-01-30 20:01:50 -05:00
static volatile bool server_running = false;
static int listen_socket_global = INVALID_SOCKET;
2025-03-03 12:21:16 -07:00
2025-02-26 20:54:23 -07:00
static const char *HTTP_RES =
2025-03-03 12:21:16 -07:00
"HTTP/1.1 200 OK\r\n"
"Cache-Control: no-store, no-cache, must-revalidate\r\n"
"Pragma: no-cache\r\n"
"Expires: 0\r\n"
2025-03-02 19:56:46 -07:00
//"Content-Length: 46\r\n"
2025-02-26 20:54:23 -07:00
"Connection: close\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n"
"\r\n"
2025-03-02 19:56:46 -07:00
"<head><link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css\"></head>"
2025-02-26 20:54:23 -07:00
"<html>\r\n"
"<body>\r\n"
2025-03-02 19:56:46 -07:00
"<main class=\"container\"><h1>BearSSL Test by EqUiNoX</h1><a href=\"https://doomonline1.vercel.app/dos.html\" target=\"_blank\">Play Doom</a></main>\r\n"
2025-02-26 20:54:23 -07:00
"</body>\r\n"
"</html>\r\n";
2025-03-03 12:21:16 -07:00
static void client_process(void* data)
{
thread_info_t *thread_info = (thread_info_t*)data;
unsigned char io_buffer[BR_SSL_BUFSIZE_BIDI];
br_ssl_server_context server_context;
#if SERVER_RSA /* RSA */
#if SERVER_PROFILE_MIN_FS
#if SERVER_CHACHA20
br_ssl_server_init_mine2c(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#else
br_ssl_server_init_mine2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#endif
#elif SERVER_PROFILE_MIN_NOFS
br_ssl_server_init_minr2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#else
br_ssl_server_init_full_rsa(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#endif
#elif SERVER_EC /* EC */
#if SERVER_PROFILE_MIN_FS
#if SERVER_CHACHA20
br_ssl_server_init_minf2c(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#else
br_ssl_server_init_minf2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#endif
#elif SERVER_PROFILE_MIN_NOFS
br_ssl_server_init_minv2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#else
br_ssl_server_init_full_ec(&server_context, CHAIN, CHAIN_LEN, BR_KEYTYPE_EC, &SKEY);
#endif
#else /* SERVER_MIXED */
#if SERVER_PROFILE_MIN_FS
#if SERVER_CHACHA20
br_ssl_server_init_minf2c(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#else
br_ssl_server_init_minf2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#endif
#elif SERVER_PROFILE_MIN_NOFS
br_ssl_server_init_minu2g(&server_context, CHAIN, CHAIN_LEN, &SKEY);
#else
br_ssl_server_init_full_ec(&server_context, CHAIN, CHAIN_LEN, BR_KEYTYPE_RSA, &SKEY);
#endif
#endif
br_ssl_engine_set_buffer(&server_context.eng, io_buffer, BR_SSL_BUFSIZE_BIDI, 1);
br_ssl_server_reset(&server_context);
br_sslio_context io_context;
br_sslio_init(&io_context, &server_context.eng, socket_utility::socket_read, &thread_info->client_socket, socket_utility::socket_write, &thread_info->client_socket);
bool client_dropped = false;
int feed_count = 0;
while (true)
{
unsigned char current_char;
if (br_sslio_read(&io_context, &current_char, 1) < 0)
{
client_dropped = true;
break;
}
if (current_char == 0x0D)
{
continue;
}
if (current_char == 0x0A)
{
if (feed_count == 1)
{
break;
}
feed_count = 1;
}
else
{
feed_count = 0;
}
}
if (client_dropped == false)
{
br_sslio_write_all(&io_context, HTTP_RES, strlen(HTTP_RES));
}
int error = br_ssl_engine_last_error(&server_context.eng);
if (error == 0)
{
debug_utility::debug_print("SSL closed (correctly).\n");
}
else
{
debug_utility::debug_print("SSL error: %d\n", error);
}
br_sslio_close(&io_context);
closesocket(thread_info->client_socket);
thread_info->thread_complete = 1;
}
2026-01-30 20:01:50 -05:00
static uint64_t WINAPI process(void* data)
2025-02-26 20:54:23 -07:00
{
2025-03-02 19:10:14 -07:00
uint16_t port = (uint16_t)data;
2025-02-26 20:54:23 -07:00
2025-03-03 12:21:16 -07:00
int listen_socket = socket_utility::host_bind(port);
2026-01-30 20:01:50 -05:00
if (listen_socket == INVALID_SOCKET)
2025-03-02 19:10:14 -07:00
{
2026-01-30 20:01:50 -05:00
server_running = false;
2025-02-26 20:54:23 -07:00
return EXIT_FAILURE;
}
2026-01-30 20:01:50 -05:00
listen_socket_global = listen_socket;
while (server_running)
2025-03-02 16:48:19 -07:00
{
2025-03-03 12:21:16 -07:00
int read_status = socket_utility::get_read_status(listen_socket);
2025-03-02 19:56:46 -07:00
if (read_status == SOCKET_ERROR)
{
2026-01-30 20:01:50 -05:00
break;
2025-03-02 19:56:46 -07:00
}
int client_socket = INVALID_SOCKET;
if (read_status == 1)
{
2025-03-03 12:21:16 -07:00
client_socket = socket_utility::accept_client(listen_socket);
2025-03-02 19:56:46 -07:00
}
else
{
2025-03-03 12:21:16 -07:00
Sleep(50);
2025-03-02 19:56:46 -07:00
continue;
}
2026-01-30 20:01:50 -05:00
if (client_socket == INVALID_SOCKET)
2025-03-02 19:10:14 -07:00
{
2026-01-30 20:01:50 -05:00
continue;
2025-02-26 20:54:23 -07:00
}
2025-03-03 12:21:16 -07:00
int i;
for (i = 0; i < MAX_NUM_THREADS; i++)
2025-03-02 16:48:19 -07:00
{
2025-03-03 12:21:16 -07:00
if (threads[i].active == 0)
2025-03-02 19:10:14 -07:00
{
break;
2025-02-26 20:54:23 -07:00
}
2025-03-03 12:21:16 -07:00
if (threads[i].data.thread_complete == 1)
2025-03-02 19:10:14 -07:00
{
2025-03-03 12:21:16 -07:00
CloseHandle(threads[i].thread);
memset(&threads[i], 0, sizeof(pthread_info_t));
break;
2025-02-26 20:54:23 -07:00
}
}
2025-03-03 12:21:16 -07:00
if (i == MAX_NUM_THREADS)
2025-03-02 19:10:14 -07:00
{
2026-01-30 20:01:50 -05:00
closesocket(client_socket);
2025-03-03 12:21:16 -07:00
continue;
2025-02-26 20:54:23 -07:00
}
2025-03-02 19:10:14 -07:00
2025-03-03 12:21:16 -07:00
threads[i].active = 1;
threads[i].data.client_socket = client_socket;
threads[i].data.port = port;
2026-01-30 20:01:50 -05:00
threads[i].thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)client_process, (void*)&threads[i].data, 0, NULL);
2025-02-26 20:54:23 -07:00
}
2025-03-02 19:10:14 -07:00
2026-01-30 20:01:50 -05:00
closesocket(listen_socket);
listen_socket_global = INVALID_SOCKET;
2025-03-02 19:10:14 -07:00
return 0;
}
2025-03-03 12:21:16 -07:00
2026-01-30 20:01:50 -05:00
server::server()
: thread(NULL), running(false)
{
}
2025-03-02 19:10:14 -07:00
void server::start(uint16_t port)
{
2025-03-03 12:21:16 -07:00
memset(threads, 0, sizeof(threads));
2026-01-30 20:01:50 -05:00
running = true;
server_running = true;
2025-03-02 19:10:14 -07:00
thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)port, 0, NULL);
}
void server::stop()
{
2026-01-30 20:01:50 -05:00
if (!running)
{
return;
}
running = false;
server_running = false;
// Close the listening socket to unblock accept
if (listen_socket_global != INVALID_SOCKET)
{
closesocket(listen_socket_global);
}
// Wait for the main server thread to finish
if (thread != NULL)
{
WaitForSingleObject(thread, 5000);
CloseHandle(thread);
thread = NULL;
}
// Wait for all client threads to complete
for (int i = 0; i < MAX_NUM_THREADS; i++)
{
if (threads[i].active && threads[i].thread != NULL)
{
WaitForSingleObject(threads[i].thread, 2000);
CloseHandle(threads[i].thread);
}
}
memset(threads, 0, sizeof(threads));
}
bool server::is_running()
{
return running;
2025-02-26 20:54:23 -07:00
}
2025-03-02 17:52:32 -07:00