Develop (#9)
* Refactor carbon-server service in docker-compose.yml to use pre-built image and remove unnecessary build context and volume mounts * Enhance performance and security features: - Update compiler flags for better optimization and security. - Implement MIME type caching for improved response handling. - Introduce worker thread pool for efficient connection management. - Optimize socket settings for low latency and enhanced performance. - Add support for CPU affinity in worker threads. - Implement graceful shutdown for worker threads during cleanup.
This commit is contained in:
21
Makefile
21
Makefile
@@ -9,8 +9,10 @@ NC := \033[0m
|
|||||||
|
|
||||||
# Compiler and flags
|
# Compiler and flags
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra -O2 -D_GNU_SOURCE
|
CFLAGS = -Wall -Wextra -Werror -O3 -march=native -mtune=native -flto -D_GNU_SOURCE -fstack-protector-strong
|
||||||
LDFLAGS = -pthread
|
CFLAGS += -fPIE -fno-strict-overflow -Wformat -Wformat-security -Werror=format-security
|
||||||
|
CFLAGS += -D_FORTIFY_SOURCE=2 -fvisibility=hidden
|
||||||
|
LDFLAGS = -pthread -Wl,-z,relro,-z,now -pie
|
||||||
LIBS = -lssl -lcrypto -lmagic -lnghttp2
|
LIBS = -lssl -lcrypto -lmagic -lnghttp2
|
||||||
|
|
||||||
# Source files and object files
|
# Source files and object files
|
||||||
@@ -72,11 +74,20 @@ install-deps:
|
|||||||
@echo "$(GREEN)Dependencies installed ✓$(NC)"
|
@echo "$(GREEN)Dependencies installed ✓$(NC)"
|
||||||
|
|
||||||
# Debug build
|
# Debug build
|
||||||
debug: CFLAGS += -g -DDEBUG
|
debug: CFLAGS = -Wall -Wextra -g -DDEBUG -D_GNU_SOURCE -fstack-protector-strong -O0
|
||||||
debug: clean all
|
debug: clean all
|
||||||
|
|
||||||
# Release build
|
# Release build with maximum optimizations
|
||||||
release: CFLAGS += -O3 -march=native -flto
|
release: CFLAGS = -Wall -Wextra -O3 -march=native -mtune=native -flto -D_GNU_SOURCE
|
||||||
|
release: CFLAGS += -fPIE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fomit-frame-pointer
|
||||||
|
release: CFLAGS += -funroll-loops -finline-functions -ffast-math
|
||||||
release: clean all
|
release: clean all
|
||||||
|
|
||||||
|
# Profile-guided optimization build
|
||||||
|
pgo-generate: CFLAGS += -fprofile-generate
|
||||||
|
pgo-generate: clean all
|
||||||
|
|
||||||
|
pgo-use: CFLAGS += -fprofile-use -fprofile-correction
|
||||||
|
pgo-use: clean all
|
||||||
|
|
||||||
.PHONY: all clean install-deps debug release
|
.PHONY: all clean install-deps debug release
|
||||||
|
|||||||
@@ -2,24 +2,14 @@ version: '3.8'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
carbon-server:
|
carbon-server:
|
||||||
build:
|
image: azreyo/carbon:latest
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
container_name: carbon-http-server
|
container_name: carbon-http-server
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080" # HTTP port
|
- "8080:8080" # HTTP port
|
||||||
- "8443:8443" # HTTPS port
|
- "8443:8443" # HTTPS port
|
||||||
volumes:
|
|
||||||
# Mount www directory for easy content updates
|
|
||||||
- ./www:/app/www:ro
|
|
||||||
# Mount log directory to persist logs
|
|
||||||
- ./log:/app/log
|
|
||||||
# Mount SSL certificates if using HTTPS
|
|
||||||
- ./ssl:/app/ssl:ro
|
|
||||||
# Mount config file
|
|
||||||
- ./server.conf:/app/server.conf:ro
|
|
||||||
environment:
|
environment:
|
||||||
- TZ=UTC
|
- TZ=UTC
|
||||||
|
- SERVER_NAME=yourdomain.com # Change this to your domain or IP
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- carbon-net
|
- carbon-net
|
||||||
@@ -42,6 +32,7 @@ services:
|
|||||||
read_only: true
|
read_only: true
|
||||||
tmpfs:
|
tmpfs:
|
||||||
- /tmp
|
- /tmp
|
||||||
|
- /app/log
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
carbon-net:
|
carbon-net:
|
||||||
|
|||||||
@@ -25,6 +25,43 @@ const char *response_404_header = "HTTP/1.1 404 Not Found\r\n\r\nFile Not Found"
|
|||||||
const char *response_403_header = "HTTP/1.1 403 Forbidden\r\n\r\nAccess Denied";
|
const char *response_403_header = "HTTP/1.1 403 Forbidden\r\n\r\nAccess Denied";
|
||||||
const char *response_429_header = "HTTP/1.1 429 Too Many Requests\r\n\r\nRate limit exceeded";
|
const char *response_429_header = "HTTP/1.1 429 Too Many Requests\r\n\r\nRate limit exceeded";
|
||||||
const char *response_500_header = "HTTP/1.1 500 Internal Server Error\r\n\r\nInternal Server Error";
|
const char *response_500_header = "HTTP/1.1 500 Internal Server Error\r\n\r\nInternal Server Error";
|
||||||
|
const char *response_503_header = "HTTP/1.1 503 Service Unavailable\r\n\r\nServer overloaded";
|
||||||
|
|
||||||
|
// Common MIME types cache
|
||||||
|
typedef struct {
|
||||||
|
const char *ext;
|
||||||
|
const char *mime;
|
||||||
|
} mime_cache_t;
|
||||||
|
|
||||||
|
static const mime_cache_t mime_cache[] = {
|
||||||
|
{".html", "text/html"},
|
||||||
|
{".css", "text/css"},
|
||||||
|
{".js", "application/javascript"},
|
||||||
|
{".json", "application/json"},
|
||||||
|
{".png", "image/png"},
|
||||||
|
{".jpg", "image/jpeg"},
|
||||||
|
{".jpeg", "image/jpeg"},
|
||||||
|
{".gif", "image/gif"},
|
||||||
|
{".svg", "image/svg+xml"},
|
||||||
|
{".ico", "image/x-icon"},
|
||||||
|
{".webp", "image/webp"},
|
||||||
|
{".woff", "font/woff"},
|
||||||
|
{".woff2", "font/woff2"},
|
||||||
|
{".ttf", "font/ttf"},
|
||||||
|
{".pdf", "application/pdf"},
|
||||||
|
{".xml", "application/xml"},
|
||||||
|
{".txt", "text/plain"},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *get_mime_from_cache(const char *ext) {
|
||||||
|
for (int i = 0; mime_cache[i].ext != NULL; i++) {
|
||||||
|
if (strcasecmp(ext, mime_cache[i].ext) == 0) {
|
||||||
|
return mime_cache[i].mime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "application/octet-stream";
|
||||||
|
}
|
||||||
|
|
||||||
// Task queue implementation
|
// Task queue implementation
|
||||||
void init_task_queue(task_queue_t *queue)
|
void init_task_queue(task_queue_t *queue)
|
||||||
@@ -38,7 +75,7 @@ void init_task_queue(task_queue_t *queue)
|
|||||||
|
|
||||||
void enqueue_task(task_queue_t *queue, int socket_fd, SSL *ssl, bool is_https)
|
void enqueue_task(task_queue_t *queue, int socket_fd, SSL *ssl, bool is_https)
|
||||||
{
|
{
|
||||||
if (queue->count >= INT_MAX - 1)
|
if (queue->count >= WORKER_QUEUE_SIZE - 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -270,20 +307,37 @@ void init_buffer_pool(void)
|
|||||||
|
|
||||||
char *get_buffer_from_pool(size_t min_size)
|
char *get_buffer_from_pool(size_t min_size)
|
||||||
{
|
{
|
||||||
|
if (min_size > DEFAULT_BUFFER_SIZE * 4)
|
||||||
|
{
|
||||||
|
// For very large requests, allocate directly
|
||||||
|
return malloc(min_size);
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&buffer_pool_mutex);
|
pthread_mutex_lock(&buffer_pool_mutex);
|
||||||
|
|
||||||
buffer_pool_t *current = buffer_pool;
|
buffer_pool_t *current = buffer_pool;
|
||||||
|
buffer_pool_t *best_fit = NULL;
|
||||||
|
|
||||||
|
// Find best fit buffer (smallest that fits)
|
||||||
while (current)
|
while (current)
|
||||||
{
|
{
|
||||||
if (!current->in_use && current->size >= min_size)
|
if (!current->in_use && current->size >= min_size)
|
||||||
{
|
{
|
||||||
current->in_use = true;
|
if (!best_fit || current->size < best_fit->size)
|
||||||
pthread_mutex_unlock(&buffer_pool_mutex);
|
{
|
||||||
return current->buffer;
|
best_fit = current;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (best_fit)
|
||||||
|
{
|
||||||
|
best_fit->in_use = true;
|
||||||
|
pthread_mutex_unlock(&buffer_pool_mutex);
|
||||||
|
return best_fit->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&buffer_pool_mutex);
|
pthread_mutex_unlock(&buffer_pool_mutex);
|
||||||
|
|
||||||
return malloc(min_size);
|
return malloc(min_size);
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define WORKER_QUEUE_SIZE 2048
|
||||||
|
|
||||||
// Connection pool structures
|
// Connection pool structures
|
||||||
typedef struct connection_task_t
|
typedef struct connection_task_t
|
||||||
@@ -68,5 +71,9 @@ extern const char *response_404_header;
|
|||||||
extern const char *response_403_header;
|
extern const char *response_403_header;
|
||||||
extern const char *response_429_header;
|
extern const char *response_429_header;
|
||||||
extern const char *response_500_header;
|
extern const char *response_500_header;
|
||||||
|
extern const char *response_503_header;
|
||||||
|
|
||||||
|
// MIME type cache
|
||||||
|
const char *get_mime_from_cache(const char *ext);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
199
src/server.c
199
src/server.c
@@ -20,6 +20,8 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include "server_config.h"
|
#include "server_config.h"
|
||||||
#include "websocket.h"
|
#include "websocket.h"
|
||||||
@@ -66,7 +68,8 @@
|
|||||||
#define SOCKET_BACKLOG 128 // Increased from 50
|
#define SOCKET_BACKLOG 128 // Increased from 50
|
||||||
#define EPOLL_TIMEOUT 100 // 100ms timeout
|
#define EPOLL_TIMEOUT 100 // 100ms timeout
|
||||||
|
|
||||||
#define MAX_THREAD_POOL_SIZE 32
|
#define MAX_THREAD_POOL_SIZE 64
|
||||||
|
#define WORKER_QUEUE_SIZE 2048
|
||||||
|
|
||||||
#define MAX_CACHE_SIZE 100
|
#define MAX_CACHE_SIZE 100
|
||||||
#define MAX_CACHE_FILE_SIZE (1024 * 1024) // 1MB
|
#define MAX_CACHE_FILE_SIZE (1024 * 1024) // 1MB
|
||||||
@@ -76,6 +79,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
int busy;
|
int busy;
|
||||||
|
int cpu_core;
|
||||||
} ThreadInfo;
|
} ThreadInfo;
|
||||||
|
|
||||||
ThreadInfo *thread_pool;
|
ThreadInfo *thread_pool;
|
||||||
@@ -83,6 +87,12 @@ int thread_pool_size = 0;
|
|||||||
pthread_mutex_t thread_pool_mutex = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t thread_pool_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
pthread_cond_t thread_pool_cond = PTHREAD_COND_INITIALIZER;
|
pthread_cond_t thread_pool_cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
|
// Worker thread queue
|
||||||
|
task_queue_t worker_queue;
|
||||||
|
pthread_t *worker_threads = NULL;
|
||||||
|
int num_worker_threads = 0;
|
||||||
|
volatile int workers_running = 1;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char ip[INET_ADDRSTRLEN];
|
char ip[INET_ADDRSTRLEN];
|
||||||
@@ -122,6 +132,9 @@ pthread_mutex_t rate_limit_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|||||||
void cleanup_thread_pool(void);
|
void cleanup_thread_pool(void);
|
||||||
void *handle_http_client(void *arg);
|
void *handle_http_client(void *arg);
|
||||||
void *handle_https_client(void *arg);
|
void *handle_https_client(void *arg);
|
||||||
|
void *worker_thread(void *arg);
|
||||||
|
void set_cpu_affinity(int thread_id);
|
||||||
|
void optimize_socket_for_send(int socket_fd);
|
||||||
void log_event(const char *message);
|
void log_event(const char *message);
|
||||||
void initialize_openssl();
|
void initialize_openssl();
|
||||||
void cleanup_openssl();
|
void cleanup_openssl();
|
||||||
@@ -183,6 +196,13 @@ void configure_ssl_context(SSL_CTX *ctx)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Security hardening
|
||||||
|
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
|
||||||
|
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
|
||||||
|
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); // Disable compression (CRIME attack)
|
||||||
|
SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||||
|
|
||||||
|
// Use secure ciphers only - TLS 1.3 and strong TLS 1.2 ciphers
|
||||||
const char *cipher_list = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:"
|
const char *cipher_list = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:"
|
||||||
"TLS_AES_128_GCM_SHA256:" // TLS 1.3
|
"TLS_AES_128_GCM_SHA256:" // TLS 1.3
|
||||||
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:"
|
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:"
|
||||||
@@ -195,8 +215,6 @@ void configure_ssl_context(SSL_CTX *ctx)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
|
|
||||||
|
|
||||||
// Enable HTTP/2 ALPN if configured
|
// Enable HTTP/2 ALPN if configured
|
||||||
if (config.enable_http2)
|
if (config.enable_http2)
|
||||||
{
|
{
|
||||||
@@ -205,6 +223,18 @@ void configure_ssl_context(SSL_CTX *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void optimize_socket_for_send(int socket_fd)
|
||||||
|
{
|
||||||
|
int flag = 1;
|
||||||
|
// Enable TCP_NODELAY to disable Nagle's algorithm for low latency
|
||||||
|
setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||||
|
|
||||||
|
#ifdef TCP_QUICKACK
|
||||||
|
// Enable quick ACK for faster response
|
||||||
|
setsockopt(socket_fd, IPPROTO_TCP, TCP_QUICKACK, &flag, sizeof(flag));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void set_socket_options(int socket_fd)
|
void set_socket_options(int socket_fd)
|
||||||
{
|
{
|
||||||
int flags = fcntl(socket_fd, F_GETFL, 0);
|
int flags = fcntl(socket_fd, F_GETFL, 0);
|
||||||
@@ -321,37 +351,18 @@ void *start_http_server(void *arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&thread_count_mutex);
|
// Enqueue task to worker thread pool instead of creating new thread
|
||||||
if (num_client_threads < config.max_connections)
|
if (worker_queue.count < WORKER_QUEUE_SIZE)
|
||||||
{
|
{
|
||||||
pthread_t client_thread;
|
enqueue_task(&worker_queue, client_socket, NULL, false);
|
||||||
int *client_socket_ptr = malloc(sizeof(int));
|
|
||||||
if (!client_socket_ptr)
|
|
||||||
{
|
|
||||||
perror("Failed to allocate memory for client socket");
|
|
||||||
close(client_socket);
|
|
||||||
pthread_mutex_unlock(&thread_count_mutex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*client_socket_ptr = client_socket;
|
|
||||||
|
|
||||||
if (pthread_create(&client_thread, NULL, handle_http_client, client_socket_ptr) == 0)
|
|
||||||
{
|
|
||||||
client_threads[num_client_threads++] = client_thread;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
perror("Error creating HTTP client thread");
|
log_event("Worker queue full, rejecting connection.");
|
||||||
close(client_socket);
|
const char *overload_response = "HTTP/1.1 503 Service Unavailable\r\n\r\nServer overloaded";
|
||||||
free(client_socket_ptr);
|
send(client_socket, overload_response, strlen(overload_response), 0);
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_event("Max client threads reached, rejecting connection.");
|
|
||||||
close(client_socket);
|
close(client_socket);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&thread_count_mutex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -411,37 +422,18 @@ void *start_https_server(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&thread_count_mutex);
|
// Enqueue task to worker thread pool instead of creating new thread
|
||||||
if (num_client_threads < config.max_connections)
|
if (worker_queue.count < WORKER_QUEUE_SIZE)
|
||||||
{
|
{
|
||||||
pthread_t client_thread;
|
enqueue_task(&worker_queue, client_socket, NULL, true);
|
||||||
int *client_socket_ptr = malloc(sizeof(int));
|
|
||||||
if (!client_socket_ptr)
|
|
||||||
{
|
|
||||||
perror("Failed to allocate memory for client socket");
|
|
||||||
close(client_socket);
|
|
||||||
pthread_mutex_unlock(&thread_count_mutex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*client_socket_ptr = client_socket;
|
|
||||||
|
|
||||||
if (pthread_create(&client_thread, NULL, handle_https_client, client_socket_ptr) == 0)
|
|
||||||
{
|
|
||||||
client_threads[num_client_threads++] = client_thread;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
perror("Error creating HTTPS client thread");
|
log_event("Worker queue full (HTTPS), rejecting connection.");
|
||||||
close(client_socket);
|
const char *overload_response = "HTTP/1.1 503 Service Unavailable\r\n\r\nServer overloaded";
|
||||||
free(client_socket_ptr);
|
send(client_socket, overload_response, strlen(overload_response), 0);
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_event("Max client threads reached, rejecting connection.");
|
|
||||||
close(client_socket);
|
close(client_socket);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&thread_count_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(https_socket);
|
close(https_socket);
|
||||||
@@ -1271,6 +1263,75 @@ void signal_handler(int sig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_cpu_affinity(int thread_id)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (num_cpus > 0)
|
||||||
|
{
|
||||||
|
cpu_set_t cpuset;
|
||||||
|
CPU_ZERO(&cpuset);
|
||||||
|
CPU_SET(thread_id % num_cpus, &cpuset);
|
||||||
|
|
||||||
|
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) != 0)
|
||||||
|
{
|
||||||
|
log_event("Warning: Failed to set CPU affinity");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void *worker_thread(void *arg)
|
||||||
|
{
|
||||||
|
int thread_id = *((int *)arg);
|
||||||
|
free(arg);
|
||||||
|
|
||||||
|
// Set CPU affinity for this worker thread
|
||||||
|
set_cpu_affinity(thread_id);
|
||||||
|
|
||||||
|
char log_msg[256];
|
||||||
|
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
snprintf(log_msg, sizeof(log_msg), "Worker thread %d started on CPU %d", thread_id, thread_id % num_cpus);
|
||||||
|
log_event(log_msg);
|
||||||
|
|
||||||
|
while (workers_running)
|
||||||
|
{
|
||||||
|
connection_task_t *task = dequeue_task(&worker_queue);
|
||||||
|
|
||||||
|
if (!task || !workers_running)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize socket before handling
|
||||||
|
optimize_socket_for_send(task->socket_fd);
|
||||||
|
|
||||||
|
// Handle the connection based on type
|
||||||
|
if (task->is_https)
|
||||||
|
{
|
||||||
|
int *socket_ptr = malloc(sizeof(int));
|
||||||
|
if (socket_ptr)
|
||||||
|
{
|
||||||
|
*socket_ptr = task->socket_fd;
|
||||||
|
handle_https_client(socket_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int *socket_ptr = malloc(sizeof(int));
|
||||||
|
if (socket_ptr)
|
||||||
|
{
|
||||||
|
*socket_ptr = task->socket_fd;
|
||||||
|
handle_http_client(socket_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void initialize_thread_pool()
|
void initialize_thread_pool()
|
||||||
{
|
{
|
||||||
thread_pool = calloc(MAX_THREAD_POOL_SIZE, sizeof(ThreadInfo));
|
thread_pool = calloc(MAX_THREAD_POOL_SIZE, sizeof(ThreadInfo));
|
||||||
@@ -1692,6 +1753,29 @@ int check_rate_limit(const char *ip)
|
|||||||
|
|
||||||
void cleanup_thread_pool()
|
void cleanup_thread_pool()
|
||||||
{
|
{
|
||||||
|
// Signal worker threads to stop
|
||||||
|
workers_running = 0;
|
||||||
|
|
||||||
|
// Wake up all waiting workers
|
||||||
|
pthread_mutex_lock(&worker_queue.mutex);
|
||||||
|
pthread_cond_broadcast(&worker_queue.cond);
|
||||||
|
pthread_mutex_unlock(&worker_queue.mutex);
|
||||||
|
|
||||||
|
// Join all worker threads
|
||||||
|
if (worker_threads)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num_worker_threads; i++)
|
||||||
|
{
|
||||||
|
pthread_join(worker_threads[i], NULL);
|
||||||
|
}
|
||||||
|
free(worker_threads);
|
||||||
|
worker_threads = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup worker queue
|
||||||
|
destroy_task_queue(&worker_queue);
|
||||||
|
|
||||||
|
// Cleanup old thread pool structure if exists
|
||||||
if (!thread_pool)
|
if (!thread_pool)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -1699,15 +1783,6 @@ void cleanup_thread_pool()
|
|||||||
|
|
||||||
pthread_mutex_lock(&thread_pool_mutex);
|
pthread_mutex_lock(&thread_pool_mutex);
|
||||||
|
|
||||||
for (int i = 0; i < thread_pool_size; i++)
|
|
||||||
{
|
|
||||||
if (thread_pool[i].busy)
|
|
||||||
{
|
|
||||||
pthread_cancel(thread_pool[i].thread);
|
|
||||||
pthread_join(thread_pool[i].thread, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadInfo *temp = thread_pool;
|
ThreadInfo *temp = thread_pool;
|
||||||
thread_pool = NULL;
|
thread_pool = NULL;
|
||||||
thread_pool_size = 0;
|
thread_pool_size = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user