Fix compiler errors
This commit is contained in:
@@ -7,3 +7,6 @@ coverage_report
|
|||||||
|
|
||||||
*.out
|
*.out
|
||||||
*.exe
|
*.exe
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
@@ -2,17 +2,30 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -I. -Wall -Wextra -O0 -g3
|
CFLAGS = -I. -Wall -Wextra -O0 -g3
|
||||||
LFLAGS = -lssl -lcrypto
|
LFLAGS = -lssl -lcrypto
|
||||||
|
AR = ar
|
||||||
|
|
||||||
CFILES = $(shell find src -name "*.c")
|
CFILES = $(shell find src -name "*.c")
|
||||||
HFILES = $(shell find src -name "*.h")
|
HFILES = $(shell find src -name "*.h")
|
||||||
|
OFILES = $(patsubst %.c,%.o,$(CFILES))
|
||||||
|
|
||||||
|
# Library names
|
||||||
|
LIBNAME = chttp
|
||||||
|
STATIC_LIB = lib$(LIBNAME).a
|
||||||
|
SHARED_LIB = lib$(LIBNAME).so
|
||||||
|
|
||||||
# Detect OS and set executable extension
|
# Detect OS and set executable extension
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
EXT = .exe
|
EXT = .exe
|
||||||
|
SHARED_LIB = $(LIBNAME).dll
|
||||||
else
|
else
|
||||||
EXT = .out
|
EXT = .out
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Installation directories
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
LIBDIR = $(PREFIX)/lib
|
||||||
|
INCDIR = $(PREFIX)/include
|
||||||
|
|
||||||
EXAMPLES_CLIENT_SRC := $(shell ls examples/client/*.c 2>/dev/null)
|
EXAMPLES_CLIENT_SRC := $(shell ls examples/client/*.c 2>/dev/null)
|
||||||
EXAMPLES_SERVER_SRC := $(shell ls examples/server/*.c 2>/dev/null)
|
EXAMPLES_SERVER_SRC := $(shell ls examples/server/*.c 2>/dev/null)
|
||||||
EXAMPLES_ENGINE_SRC := $(shell ls examples/engine/*.c 2>/dev/null)
|
EXAMPLES_ENGINE_SRC := $(shell ls examples/engine/*.c 2>/dev/null)
|
||||||
@@ -21,11 +34,25 @@ EXAMPLES_CLIENT := $(patsubst %.c,%$(EXT),$(EXAMPLES_CLIENT_SRC))
|
|||||||
EXAMPLES_SERVER := $(patsubst %.c,%$(EXT),$(EXAMPLES_SERVER_SRC))
|
EXAMPLES_SERVER := $(patsubst %.c,%$(EXT),$(EXAMPLES_SERVER_SRC))
|
||||||
EXAMPLES_ENGINE := $(patsubst %.c,%$(EXT),$(EXAMPLES_ENGINE_SRC))
|
EXAMPLES_ENGINE := $(patsubst %.c,%$(EXT),$(EXAMPLES_ENGINE_SRC))
|
||||||
|
|
||||||
all: chttp.c chttp.h examples
|
all: chttp.c chttp.h examples lib
|
||||||
|
|
||||||
|
lib: $(STATIC_LIB) $(SHARED_LIB)
|
||||||
|
|
||||||
chttp.c chttp.h: $(HFILES) $(CFILES)
|
chttp.c chttp.h: $(HFILES) $(CFILES)
|
||||||
python misc/amalg.py
|
python misc/amalg.py
|
||||||
|
|
||||||
|
# Object files from source files
|
||||||
|
%.o: %.c $(HFILES)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Static library
|
||||||
|
$(STATIC_LIB): $(OFILES)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
# Shared library
|
||||||
|
$(SHARED_LIB): $(OFILES)
|
||||||
|
$(CC) -shared -o $@ $^ $(LFLAGS)
|
||||||
|
|
||||||
examples: $(EXAMPLES_CLIENT) $(EXAMPLES_SERVER) $(EXAMPLES_ENGINE)
|
examples: $(EXAMPLES_CLIENT) $(EXAMPLES_SERVER) $(EXAMPLES_ENGINE)
|
||||||
|
|
||||||
examples/client/%$(EXT): examples/client/%.c chttp.c chttp.h
|
examples/client/%$(EXT): examples/client/%.c chttp.c chttp.h
|
||||||
@@ -37,6 +64,28 @@ examples/server/%$(EXT): examples/server/%.c chttp.c chttp.h
|
|||||||
examples/engine/%$(EXT): examples/engine/%.c chttp.c chttp.h
|
examples/engine/%$(EXT): examples/engine/%.c chttp.c chttp.h
|
||||||
$(CC) $(CFLAGS) $< chttp.c -o $@ $(LFLAGS)
|
$(CC) $(CFLAGS) $< chttp.c -o $@ $(LFLAGS)
|
||||||
|
|
||||||
|
# Installation targets
|
||||||
|
install: install-lib install-headers
|
||||||
|
|
||||||
|
install-lib: $(STATIC_LIB) $(SHARED_LIB)
|
||||||
|
install -d $(LIBDIR)
|
||||||
|
install -m 644 $(STATIC_LIB) $(LIBDIR)/
|
||||||
|
install -m 755 $(SHARED_LIB) $(LIBDIR)/
|
||||||
|
|
||||||
|
install-headers: chttp.h
|
||||||
|
install -d $(INCDIR)
|
||||||
|
install -m 644 chttp.h $(INCDIR)/
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(LIBDIR)/$(STATIC_LIB)
|
||||||
|
rm -f $(LIBDIR)/$(SHARED_LIB)
|
||||||
|
rm -f $(INCDIR)/chttp.h
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f client_example server_example
|
rm -f client_example server_example
|
||||||
rm -f examples/client/*$(EXT) examples/server/*$(EXT) examples/engine/*$(EXT)
|
rm -f examples/client/*$(EXT) examples/server/*$(EXT) examples/engine/*$(EXT)
|
||||||
|
rm -f $(OFILES)
|
||||||
|
rm -f $(STATIC_LIB) $(SHARED_LIB)
|
||||||
|
rm -f chttp.c chttp.h
|
||||||
|
|
||||||
|
.PHONY: all lib examples install install-lib install-headers uninstall clean
|
||||||
|
|||||||
@@ -9,15 +9,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/conf.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -27,13 +18,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// src/cert.h
|
// src/cert.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef CERT_INCLUDED
|
||||||
|
#define CERT_INCLUDED
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
|
||||||
// This is an utility to create self-signed certificates
|
// This is an utility to create self-signed certificates
|
||||||
// useful when testing HTTPS servers locally. This is only
|
// useful when testing HTTPS servers locally. This is only
|
||||||
// meant to be used by people starting out with a library
|
// meant to be used by people starting out with a library
|
||||||
@@ -51,10 +46,12 @@
|
|||||||
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
HTTP_String cert_file, HTTP_String key_file);
|
HTTP_String cert_file, HTTP_String key_file);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // CERT_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/socket.h
|
// src/socket.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SOCKET_INCLUDED
|
||||||
|
#define SOCKET_INCLUDED
|
||||||
// This is a socket abstraction module for non-blocking TCP and TLS sockets.
|
// This is a socket abstraction module for non-blocking TCP and TLS sockets.
|
||||||
//
|
//
|
||||||
// Sockets may be in a number of states based on if they are plain TCP or TLS
|
// Sockets may be in a number of states based on if they are plain TCP or TLS
|
||||||
@@ -108,7 +105,13 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|||||||
// which means the user needs to call socket_free to free the socket
|
// which means the user needs to call socket_free to free the socket
|
||||||
// as it's not unusable.
|
// as it's not unusable.
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int is_ipv6;
|
int is_ipv6;
|
||||||
@@ -139,8 +142,10 @@ typedef struct {
|
|||||||
SocketState state;
|
SocketState state;
|
||||||
SocketWantEvent event;
|
SocketWantEvent event;
|
||||||
int fd;
|
int fd;
|
||||||
|
#if HTTPS_ENABLED
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
|
#endif
|
||||||
AddrInfo *addr_list;
|
AddrInfo *addr_list;
|
||||||
int addr_count;
|
int addr_count;
|
||||||
int addr_cursor;
|
int addr_cursor;
|
||||||
@@ -148,16 +153,20 @@ typedef struct {
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
} Socket;
|
} Socket;
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char name[128];
|
char name[128];
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
} Domain;
|
} Domain;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
int num_domains;
|
int num_domains;
|
||||||
int max_domains;
|
int max_domains;
|
||||||
Domain *domains;
|
Domain *domains;
|
||||||
|
#endif
|
||||||
} SocketGroup;
|
} SocketGroup;
|
||||||
|
|
||||||
void socket_global_init (void);
|
void socket_global_init (void);
|
||||||
@@ -178,7 +187,7 @@ void socket_close (Socket *sock);
|
|||||||
void socket_free (Socket *sock);
|
void socket_free (Socket *sock);
|
||||||
int socket_wait (Socket **socks, int num_socks);
|
int socket_wait (Socket **socks, int num_socks);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // SOCKET_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/basic.c
|
// src/basic.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -2296,21 +2305,40 @@ void http_engine_undo(HTTP_Engine *eng)
|
|||||||
// src/socket.c
|
// src/socket.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
void socket_global_init(void)
|
void socket_global_init(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_global_free(void)
|
void socket_global_free(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_group_init(SocketGroup *group)
|
int socket_group_init(SocketGroup *group)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_client_method());
|
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_client_method());
|
||||||
if (!ssl_ctx) {
|
if (!ssl_ctx) {
|
||||||
fprintf(stderr, "Unable to create SSL context\n");
|
fprintf(stderr, "Unable to create SSL context\n");
|
||||||
@@ -2336,9 +2364,13 @@ int socket_group_init(SocketGroup *group)
|
|||||||
group->domains = NULL;
|
group->domains = NULL;
|
||||||
group->num_domains = 0;
|
group->num_domains = 0;
|
||||||
group->max_domains = 0;
|
group->max_domains = 0;
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
static int servername_callback(SSL *ssl, int *ad, void *arg)
|
static int servername_callback(SSL *ssl, int *ad, void *arg)
|
||||||
{
|
{
|
||||||
SocketGroup *group = arg;
|
SocketGroup *group = arg;
|
||||||
@@ -2357,9 +2389,11 @@ static int servername_callback(SSL *ssl, int *ad, void *arg)
|
|||||||
|
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int socket_group_init_server(SocketGroup *group, HTTP_String cert_file, HTTP_String key_file)
|
int socket_group_init_server(SocketGroup *group, HTTP_String cert_file, HTTP_String key_file)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_server_method());
|
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_server_method());
|
||||||
if (!ssl_ctx) {
|
if (!ssl_ctx) {
|
||||||
fprintf(stderr, "Unable to create server SSL context\n");
|
fprintf(stderr, "Unable to create server SSL context\n");
|
||||||
@@ -2420,16 +2454,27 @@ int socket_group_init_server(SocketGroup *group, HTTP_String cert_file, HTTP_Str
|
|||||||
group->domains = NULL;
|
group->domains = NULL;
|
||||||
group->num_domains = 0;
|
group->num_domains = 0;
|
||||||
group->max_domains = 0;
|
group->max_domains = 0;
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
if (cert_file.len > 0 || key_file.len > 0)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_group_free(SocketGroup *group)
|
void socket_group_free(SocketGroup *group)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX_free(group->ssl_ctx);
|
SSL_CTX_free(group->ssl_ctx);
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
if (group->num_domains == group->max_domains) {
|
if (group->num_domains == group->max_domains) {
|
||||||
|
|
||||||
int new_max_domains = 2 * group->max_domains;
|
int new_max_domains = 2 * group->max_domains;
|
||||||
@@ -2513,6 +2558,13 @@ int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String
|
|||||||
domain_info->ssl_ctx = ssl_ctx;
|
domain_info->ssl_ctx = ssl_ctx;
|
||||||
group->num_domains++;
|
group->num_domains++;
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
(void) domain;
|
||||||
|
(void) cert_file;
|
||||||
|
(void) key_file;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketState socket_state(Socket *sock)
|
SocketState socket_state(Socket *sock)
|
||||||
@@ -2522,12 +2574,20 @@ SocketState socket_state(Socket *sock)
|
|||||||
|
|
||||||
void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize socket for server-side TLS handshake
|
// Initialize socket for server-side TLS handshake
|
||||||
sock->state = SOCKET_STATE_ACCEPTED; // TCP connection already established
|
sock->state = SOCKET_STATE_ACCEPTED; // TCP connection already established
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = fd;
|
sock->fd = fd;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -2535,7 +2595,7 @@ void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
|||||||
sock->port = 0;
|
sock->port = 0;
|
||||||
|
|
||||||
// Set non-blocking mode for the accepted socket
|
// Set non-blocking mode for the accepted socket
|
||||||
int flags = fcntl(fd, F_GETFL, 0);
|
int flags = fcntl(fd, F_GETFL, 0); // TODO: fail on error
|
||||||
if (flags >= 0) {
|
if (flags >= 0) {
|
||||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||||
}
|
}
|
||||||
@@ -2544,12 +2604,20 @@ void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_connect(Socket *sock, SocketGroup *group, HTTP_String host, uint16_t port) {
|
void socket_connect(Socket *sock, SocketGroup *group, HTTP_String host, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -2599,12 +2667,20 @@ void socket_connect(Socket *sock, SocketGroup *group, HTTP_String host, uint16_t
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_connect_ipv4(Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint16_t port) {
|
void socket_connect_ipv4(Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -2620,12 +2696,20 @@ void socket_connect_ipv4(Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint1
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_connect_ipv6(Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint16_t port) {
|
void socket_connect_ipv6(Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -2641,6 +2725,16 @@ void socket_connect_ipv6(Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint1
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool socket_secure(Socket *sock)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
return sock->ssl_ctx != NULL;
|
||||||
|
#else
|
||||||
|
(void) sock;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void socket_update(Socket *sock)
|
void socket_update(Socket *sock)
|
||||||
{
|
{
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
@@ -2653,10 +2747,12 @@ void socket_update(Socket *sock)
|
|||||||
switch (sock->state) {
|
switch (sock->state) {
|
||||||
case SOCKET_STATE_PENDING:
|
case SOCKET_STATE_PENDING:
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
if (sock->ssl) {
|
if (sock->ssl) {
|
||||||
SSL_free(sock->ssl);
|
SSL_free(sock->ssl);
|
||||||
sock->ssl = NULL;
|
sock->ssl = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sock->fd != -1)
|
if (sock->fd != -1)
|
||||||
close(sock->fd);
|
close(sock->fd);
|
||||||
@@ -2762,11 +2858,11 @@ void socket_update(Socket *sock)
|
|||||||
|
|
||||||
case SOCKET_STATE_CONNECTED:
|
case SOCKET_STATE_CONNECTED:
|
||||||
{
|
{
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
// Start SSL handshake
|
// Start SSL handshake
|
||||||
if (!sock->ssl) {
|
if (!sock->ssl) {
|
||||||
sock->ssl = SSL_new(sock->ssl_ctx);
|
sock->ssl = SSL_new(sock->ssl_ctx);
|
||||||
@@ -2798,17 +2894,20 @@ void socket_update(Socket *sock)
|
|||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
again = true;
|
again = true;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOCKET_STATE_ACCEPTED:
|
case SOCKET_STATE_ACCEPTED:
|
||||||
{
|
{
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
// Start server-side SSL handshake
|
// Start server-side SSL handshake
|
||||||
if (!sock->ssl) {
|
if (!sock->ssl) {
|
||||||
sock->ssl = SSL_new(sock->ssl_ctx);
|
sock->ssl = SSL_new(sock->ssl_ctx);
|
||||||
@@ -2837,6 +2936,9 @@ void socket_update(Socket *sock)
|
|||||||
// Server socket error - close the connection
|
// Server socket error - close the connection
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2850,11 +2952,11 @@ void socket_update(Socket *sock)
|
|||||||
|
|
||||||
case SOCKET_STATE_SHUTDOWN:
|
case SOCKET_STATE_SHUTDOWN:
|
||||||
{
|
{
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
int ret = SSL_shutdown(sock->ssl);
|
int ret = SSL_shutdown(sock->ssl);
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
@@ -2875,6 +2977,9 @@ void socket_update(Socket *sock)
|
|||||||
|
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2895,7 +3000,7 @@ int socket_read(Socket *sock, char *dst, int max) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
int ret = read(sock->fd, dst, max);
|
int ret = read(sock->fd, dst, max);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
@@ -2916,6 +3021,7 @@ int socket_read(Socket *sock, char *dst, int max) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
int ret = SSL_read(sock->ssl, dst, max);
|
int ret = SSL_read(sock->ssl, dst, max);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
int err = SSL_get_error(sock->ssl, ret);
|
int err = SSL_get_error(sock->ssl, ret);
|
||||||
@@ -2934,6 +3040,10 @@ int socket_read(Socket *sock, char *dst, int max) {
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2945,7 +3055,7 @@ int socket_write(Socket *sock, char *src, int len) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
int ret = write(sock->fd, src, len);
|
int ret = write(sock->fd, src, len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
@@ -2961,6 +3071,7 @@ int socket_write(Socket *sock, char *src, int len) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
int ret = SSL_write(sock->ssl, src, len);
|
int ret = SSL_write(sock->ssl, src, len);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
int err = SSL_get_error(sock->ssl, ret);
|
int err = SSL_get_error(sock->ssl, ret);
|
||||||
@@ -2979,6 +3090,9 @@ int socket_write(Socket *sock, char *src, int len) {
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2989,20 +3103,23 @@ void socket_close(Socket *sock) {
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_free(Socket *sock) {
|
void socket_free(Socket *sock)
|
||||||
// Release all resources associated to the socket
|
{
|
||||||
if (sock->ssl) {
|
#ifdef HTTPS_ENABLED
|
||||||
|
if (sock->ssl)
|
||||||
SSL_free(sock->ssl);
|
SSL_free(sock->ssl);
|
||||||
sock->ssl = NULL;
|
#endif
|
||||||
}
|
|
||||||
if (sock->fd >= 0) {
|
if (sock->fd >= 0) {
|
||||||
close(sock->fd);
|
close(sock->fd);
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->hostname) {
|
if (sock->hostname) {
|
||||||
free(sock->hostname);
|
free(sock->hostname);
|
||||||
sock->hostname = NULL;
|
sock->hostname = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->addr_list) {
|
if (sock->addr_list) {
|
||||||
free(sock->addr_list);
|
free(sock->addr_list);
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
@@ -3503,6 +3620,164 @@ HTTP_Response *http_post(HTTP_String url, HTTP_String *headers, int num_headers,
|
|||||||
*phandle = handle;
|
*phandle = handle;
|
||||||
return res;
|
return res;
|
||||||
}//////////////////////////////////////////////////////////////////////
|
}//////////////////////////////////////////////////////////////////////
|
||||||
|
// src/cert.c
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
|
||||||
|
static EVP_PKEY *generate_rsa_key_pair(int key_bits)
|
||||||
|
{
|
||||||
|
EVP_PKEY_CTX *ctx;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
|
||||||
|
// Create the context for key generation
|
||||||
|
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||||
|
if (!ctx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (EVP_PKEY_keygen_init(ctx) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return pkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
static X509 *create_certificate(EVP_PKEY *pkey, HTTP_String C, HTTP_String O, HTTP_String CN, int days)
|
||||||
|
{
|
||||||
|
X509 *x509 = X509_new();
|
||||||
|
if (!x509)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Set version (version 3)
|
||||||
|
X509_set_version(x509, 2);
|
||||||
|
|
||||||
|
// Set serial number
|
||||||
|
ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
|
||||||
|
|
||||||
|
// Set validity period
|
||||||
|
X509_gmtime_adj(X509_get_notBefore(x509), 0);
|
||||||
|
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L * days); // days * seconds_per_year
|
||||||
|
|
||||||
|
// Set public key
|
||||||
|
X509_set_pubkey(x509, pkey);
|
||||||
|
|
||||||
|
// Set subject name
|
||||||
|
X509_NAME *name = X509_get_subject_name(x509);
|
||||||
|
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*) C.ptr, C.len, -1, 0);
|
||||||
|
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*) O.ptr, O.len, -1, 0);
|
||||||
|
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*) CN.ptr, CN.len, -1, 0);
|
||||||
|
|
||||||
|
// Set issuer name (same as subject for self-signed)
|
||||||
|
X509_set_issuer_name(x509, name);
|
||||||
|
|
||||||
|
if (!X509_sign(x509, pkey, EVP_sha256())) {
|
||||||
|
X509_free(x509);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return x509;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int save_private_key(EVP_PKEY *pkey, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(filename, "wb");
|
||||||
|
if (!fp)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Write private key in PEM format
|
||||||
|
if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) {
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cert_save(X509 *x509, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(filename, "wb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Error opening file for certificate: %s\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write certificate in PEM format
|
||||||
|
if (!PEM_write_X509(fp, x509)) {
|
||||||
|
fprintf(stderr, "Error writing certificate\n");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
printf("Certificate saved to: %s\n", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
|
HTTP_String cert_file, HTTP_String key_file)
|
||||||
|
{
|
||||||
|
EVP_PKEY *pkey = generate_rsa_key_pair(2048);
|
||||||
|
if (pkey == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
X509 *x509 = create_certificate(pkey, C, O, CN, 1)
|
||||||
|
if (x509 == NULL) {
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_private_key(pkey, key_file) < 0) {
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_certificate(x509, cert_file) < 0) {
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
|
HTTP_String cert_file, HTTP_String key_file)
|
||||||
|
{
|
||||||
|
(void) C;
|
||||||
|
(void) O;
|
||||||
|
(void) CN;
|
||||||
|
(void) cert_file;
|
||||||
|
(void) key_file;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif//////////////////////////////////////////////////////////////////////
|
||||||
// src/server.c
|
// src/server.c
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -3662,7 +3937,7 @@ void http_server_free(HTTP_Server *server)
|
|||||||
free(server);
|
free(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_server_website(HTTP_Server *server, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
int http_server_add_website(HTTP_Server *server, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
||||||
{
|
{
|
||||||
return socket_group_add_domain(&server->group, domain, cert_file, key_file);
|
return socket_group_add_domain(&server->group, domain, cert_file, key_file);
|
||||||
}
|
}
|
||||||
@@ -3708,24 +3983,21 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
|
|||||||
|
|
||||||
for (int i = 0, j = 0; i < server->num_conns; i++) {
|
for (int i = 0, j = 0; i < server->num_conns; i++) {
|
||||||
|
|
||||||
if (!server->conns[i].used)
|
Connection *conn = &server->conns[i];
|
||||||
|
|
||||||
|
if (!conn->used)
|
||||||
continue;
|
continue;
|
||||||
j++;
|
j++;
|
||||||
|
|
||||||
int events = 0;
|
int events = 0;
|
||||||
|
switch (conn->socket.event) {
|
||||||
if (server->conns[i].socket.ssl_ctx)
|
case SOCKET_WANT_NONE: events = 0; break;
|
||||||
events = server->conns[i].socket.event;
|
case SOCKET_WANT_READ: events = POLLIN; break;
|
||||||
else {
|
case SOCKET_WANT_WRITE: events = POLLOUT; break;
|
||||||
switch (http_engine_state(&server->conns[i].engine)) {
|
|
||||||
case HTTP_ENGINE_STATE_SERVER_RECV_BUF: events = POLLIN; break;
|
|
||||||
case HTTP_ENGINE_STATE_SERVER_SEND_BUF: events = POLLOUT; break;
|
|
||||||
default:break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events) {
|
if (events) {
|
||||||
polled[num_polled].fd = server->conns[i].socket.fd;
|
polled[num_polled].fd = conn->socket.fd;
|
||||||
polled[num_polled].events = events;
|
polled[num_polled].events = events;
|
||||||
polled[num_polled].revents = 0;
|
polled[num_polled].revents = 0;
|
||||||
indices[num_polled] = i;
|
indices[num_polled] = i;
|
||||||
@@ -3754,6 +4026,7 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
|
|||||||
|
|
||||||
server->conns[k].used = true;
|
server->conns[k].used = true;
|
||||||
socket_accept(&server->conns[k].socket, secure ? &server->group : NULL, new_fd);
|
socket_accept(&server->conns[k].socket, secure ? &server->group : NULL, new_fd);
|
||||||
|
|
||||||
http_engine_init(&server->conns[k].engine, 0, server_memfunc, NULL);
|
http_engine_init(&server->conns[k].engine, 0, server_memfunc, NULL);
|
||||||
server->num_conns++;
|
server->num_conns++;
|
||||||
}
|
}
|
||||||
@@ -3944,8 +4217,11 @@ void http_response_done(HTTP_ResponseHandle res)
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ROUTE_STATIC_DIR,
|
ROUTE_STATIC_DIR,
|
||||||
ROUTE_DYNAMIC,
|
ROUTE_DYNAMIC,
|
||||||
|
|||||||
@@ -10,13 +10,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// src/basic.h
|
// src/basic.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef CHTTP_BASIC_INCLUDED
|
||||||
|
#define CHTTP_BASIC_INCLUDED
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
// String type used throughout cHTTP.
|
// String type used throughout cHTTP.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@@ -89,10 +91,14 @@ HTTP_String http_trim(HTTP_String s);
|
|||||||
#define HTTP_ASSERT(X) {if (!(X)) { __builtin_trap(); }}
|
#define HTTP_ASSERT(X) {if (!(X)) { __builtin_trap(); }}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // CHTTP_BASIC_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/parse.h
|
// src/parse.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef PARSE_INCLUDED
|
||||||
|
#define PARSE_INCLUDED
|
||||||
|
#include "basic.h"
|
||||||
|
|
||||||
#define HTTP_MAX_HEADERS 32
|
#define HTTP_MAX_HEADERS 32
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -181,10 +187,14 @@ HTTP_String http_getqueryparam (HTTP_Request *req, HTTP_String name);
|
|||||||
HTTP_String http_getbodyparam (HTTP_Request *req, HTTP_String name);
|
HTTP_String http_getbodyparam (HTTP_Request *req, HTTP_String name);
|
||||||
HTTP_String http_getcookie (HTTP_Request *req, HTTP_String name);
|
HTTP_String http_getcookie (HTTP_Request *req, HTTP_String name);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // PARSE_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/engine.h
|
// src/engine.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef HTTP_ENGINE_INCLUDED
|
||||||
|
#define HTTP_ENGINE_INCLUDED
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HTTP_MEMFUNC_MALLOC,
|
HTTP_MEMFUNC_MALLOC,
|
||||||
HTTP_MEMFUNC_FREE,
|
HTTP_MEMFUNC_FREE,
|
||||||
@@ -299,10 +309,16 @@ void http_engine_bodyack (HTTP_Engine *eng, int num);
|
|||||||
void http_engine_done (HTTP_Engine *eng);
|
void http_engine_done (HTTP_Engine *eng);
|
||||||
void http_engine_undo (HTTP_Engine *eng);
|
void http_engine_undo (HTTP_Engine *eng);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // HTTP_ENGINE_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/client.h
|
// src/client.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef CLIENT_INCLUDED
|
||||||
|
#define CLIENT_INCLUDED
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
// Initialize the global state of cHTTP.
|
// Initialize the global state of cHTTP.
|
||||||
//
|
//
|
||||||
// cHTTP tries to avoid global state. What this function
|
// cHTTP tries to avoid global state. What this function
|
||||||
@@ -399,10 +415,16 @@ HTTP_Response *http_post(HTTP_String url,
|
|||||||
HTTP_String *headers, int num_headers,
|
HTTP_String *headers, int num_headers,
|
||||||
HTTP_String body, HTTP_RequestHandle *phandle);
|
HTTP_String body, HTTP_RequestHandle *phandle);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // CLIENT_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/server.h
|
// src/server.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef HTTP_SERVER_INCLUDED
|
||||||
|
#define HTTP_SERVER_INCLUDED
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *data0;
|
void *data0;
|
||||||
int data1;
|
int data1;
|
||||||
@@ -428,10 +450,15 @@ void http_response_bodyack (HTTP_ResponseHandle res, int num);
|
|||||||
void http_response_undo (HTTP_ResponseHandle res);
|
void http_response_undo (HTTP_ResponseHandle res);
|
||||||
void http_response_done (HTTP_ResponseHandle res);
|
void http_response_done (HTTP_ResponseHandle res);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // HTTP_SERVER_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/cert.h
|
// src/cert.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef CERT_INCLUDED
|
||||||
|
#define CERT_INCLUDED
|
||||||
|
|
||||||
|
#include "basic.h"
|
||||||
|
|
||||||
// This is an utility to create self-signed certificates
|
// This is an utility to create self-signed certificates
|
||||||
// useful when testing HTTPS servers locally. This is only
|
// useful when testing HTTPS servers locally. This is only
|
||||||
// meant to be used by people starting out with a library
|
// meant to be used by people starting out with a library
|
||||||
@@ -449,10 +476,15 @@ void http_response_done (HTTP_ResponseHandle res);
|
|||||||
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
HTTP_String cert_file, HTTP_String key_file);
|
HTTP_String cert_file, HTTP_String key_file);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
#endif // CERT_INCLUDED//////////////////////////////////////////////////////////////////////
|
||||||
// src/router.h
|
// src/router.h
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef HTTP_ROUTER_INCLUDED
|
||||||
|
#define HTTP_ROUTER_INCLUDED
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
typedef struct HTTP_Router HTTP_Router;
|
typedef struct HTTP_Router HTTP_Router;
|
||||||
typedef void (*HTTP_RouterFunc)(HTTP_Request*, HTTP_ResponseHandle, void*);;
|
typedef void (*HTTP_RouterFunc)(HTTP_Request*, HTTP_ResponseHandle, void*);;
|
||||||
|
|
||||||
@@ -463,7 +495,7 @@ void http_router_dir (HTTP_Router *router, HTTP_String endpoint, HTT
|
|||||||
void http_router_func (HTTP_Router *router, HTTP_Method method, HTTP_String endpoint, HTTP_RouterFunc func, void*);
|
void http_router_func (HTTP_Router *router, HTTP_Method method, HTTP_String endpoint, HTTP_RouterFunc func, void*);
|
||||||
int http_serve (char *addr, int port, HTTP_Router *router);
|
int http_serve (char *addr, int port, HTTP_Router *router);
|
||||||
|
|
||||||
|
#endif // HTTP_ROUTER_INCLUDED
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -51,10 +51,10 @@ static void produce_response(HTTP_Engine *eng)
|
|||||||
http_engine_status(eng, 200);
|
http_engine_status(eng, 200);
|
||||||
|
|
||||||
// Set zero or more headers
|
// Set zero or more headers
|
||||||
http_engine_header(eng, "Server: tinyhttp", -1);
|
http_engine_header(eng, HTTP_STR("Server: tinyhttp"));
|
||||||
|
|
||||||
// Set some bytes in the body
|
// Set some bytes in the body
|
||||||
http_engine_body(eng, "Hello, world!", 13);
|
http_engine_body(eng, HTTP_STR("Hello, world!"));
|
||||||
|
|
||||||
// This is one difference from the http_response_XXX API.
|
// This is one difference from the http_response_XXX API.
|
||||||
// It's possible to write response content directly into
|
// It's possible to write response content directly into
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <mswsock.h>
|
#include <mswsock.h>
|
||||||
@@ -222,4 +224,16 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("This example only works on windows!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,24 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <chttp.h>
|
#include <chttp.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
typedef void* Thread;
|
||||||
|
typedef unsigned long ThreadReturn;
|
||||||
|
typedef CRITICAL_SECTION Mutex;
|
||||||
|
typedef CONDITION_VARIABLE Condvar;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <pthread.h>
|
||||||
|
typedef pthread_t Thread;
|
||||||
|
typedef void* ThreadReturn;
|
||||||
|
typedef pthread_mutex_t Mutex;
|
||||||
|
typedef pthread_cond_t Condvar;
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: This example doesn't work yet!
|
// NOTE: This example doesn't work yet!
|
||||||
|
|
||||||
// This example shows how to delegate the response creation
|
// This example shows how to delegate the response creation
|
||||||
@@ -56,7 +74,20 @@ Job pop_job(void);
|
|||||||
// with no new job pushed.
|
// with no new job pushed.
|
||||||
bool push_job(Job job, bool block);
|
bool push_job(Job job, bool block);
|
||||||
|
|
||||||
void *worker(void*)
|
void thread_create(Thread *thread, void *arg, ThreadReturn (*func)(void*));
|
||||||
|
ThreadReturn thread_join(Thread thread);
|
||||||
|
|
||||||
|
void mutex_init(Mutex *mutex);
|
||||||
|
void mutex_free(Mutex *mutex);
|
||||||
|
void mutex_lock(Mutex *mutex);
|
||||||
|
void mutex_unlock(Mutex *mutex);
|
||||||
|
|
||||||
|
void condvar_init(Condvar *condvar);
|
||||||
|
void condvar_free(Condvar *condvar);
|
||||||
|
void condvar_wait(Condvar *condvar, Mutex *mutex);
|
||||||
|
void condvar_signal(Condvar *condvar);
|
||||||
|
|
||||||
|
ThreadReturn worker(void*)
|
||||||
{
|
{
|
||||||
for (bool exit = false; !exit; ) {
|
for (bool exit = false; !exit; ) {
|
||||||
|
|
||||||
@@ -82,7 +113,7 @@ void *worker(void*)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
@@ -93,12 +124,15 @@ int main(void)
|
|||||||
if (server == NULL)
|
if (server == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Thread worker_id;
|
||||||
|
thread_create(&worker_id, NULL, worker);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
HTTP_Request *req;
|
HTTP_Request *req;
|
||||||
HTTP_ResponseHandle res;
|
HTTP_ResponseHandle res;
|
||||||
|
|
||||||
int ret = http_server_wait(server, &res, &res);
|
int ret = http_server_wait(server, &req, &res);
|
||||||
if (ret < 0) return -1;
|
if (ret < 0) return -1;
|
||||||
|
|
||||||
if (http_streq(req->url.path, HTTP_STR("/endpoint_A"))) {
|
if (http_streq(req->url.path, HTTP_STR("/endpoint_A"))) {
|
||||||
@@ -139,6 +173,7 @@ int main(void)
|
|||||||
Job job;
|
Job job;
|
||||||
job.type = NO_JOB;
|
job.type = NO_JOB;
|
||||||
push_job(job, true);
|
push_job(job, true);
|
||||||
|
thread_join(worker_id);
|
||||||
|
|
||||||
http_server_free(server);
|
http_server_free(server);
|
||||||
free_job_queue();
|
free_job_queue();
|
||||||
@@ -176,8 +211,8 @@ Job pop_job(void)
|
|||||||
{
|
{
|
||||||
mutex_lock(&queue_lock);
|
mutex_lock(&queue_lock);
|
||||||
|
|
||||||
while (queue_count == 0);
|
while (queue_count == 0)
|
||||||
condvar_wait(&queue_produce_event, &queue_lock, -1);
|
condvar_wait(&queue_produce_event, &queue_lock);
|
||||||
|
|
||||||
Job job = queue[queue_head];
|
Job job = queue[queue_head];
|
||||||
queue_head = (queue_head + 1) % MAX_JOBS;
|
queue_head = (queue_head + 1) % MAX_JOBS;
|
||||||
@@ -199,7 +234,7 @@ bool push_job(Job job, bool block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
condvar_wait(&queue_consume_event, &queue_lock, -1);
|
condvar_wait(&queue_consume_event, &queue_lock);
|
||||||
while (queue_count == 0);
|
while (queue_count == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,3 +246,134 @@ bool push_job(Job job, bool block)
|
|||||||
mutex_unlock(&queue_lock);
|
mutex_unlock(&queue_lock);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
|
||||||
|
void thread_create(Thread *thread, void *arg, ThreadReturn (*func)(void*))
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
Thread thread_ = CreateThread(NULL, 0, func, arg, 0, NULL);
|
||||||
|
if (thread_ == INVALID_HANDLE_VALUE)
|
||||||
|
abort();
|
||||||
|
*thread = thread_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
int ret = pthread_create(thread, NULL, func, arg);
|
||||||
|
if (ret) abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadReturn thread_join(Thread thread)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
ThreadReturn result;
|
||||||
|
WaitForSingleObject(thread, INFINITE);
|
||||||
|
if (!GetExitCodeThread(thread, &result))
|
||||||
|
abort();
|
||||||
|
CloseHandle(thread);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
ThreadReturn result;
|
||||||
|
int ret = pthread_join(thread, &result);
|
||||||
|
if (ret) abort();
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_init(Mutex *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
InitializeCriticalSection(mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_mutex_init(mutex, NULL))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_free(Mutex *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
DeleteCriticalSection(mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_mutex_destroy(mutex))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_lock(Mutex *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
EnterCriticalSection(mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_mutex_lock(mutex))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_unlock(Mutex *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
LeaveCriticalSection(mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_mutex_unlock(mutex))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void condvar_init(Condvar *condvar)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
InitializeConditionVariable(condvar);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_cond_init(condvar, NULL))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void condvar_free(Condvar *condvar)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_cond_destroy(condvar))
|
||||||
|
abort();
|
||||||
|
#else
|
||||||
|
(void) condvar;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void condvar_wait(Condvar *condvar, Mutex *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!SleepConditionVariableCS(condvar, mutex, INFINITE))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
int err = pthread_cond_wait(condvar, mutex);
|
||||||
|
if (err) abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void condvar_signal(Condvar *condvar)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
WakeConditionVariable(condvar);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if (pthread_cond_signal(condvar))
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
int main(void) {}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <chttp.h>
|
#include <chttp.h>
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ int main(void)
|
|||||||
HTTP_Request *req;
|
HTTP_Request *req;
|
||||||
HTTP_ResponseHandle res;
|
HTTP_ResponseHandle res;
|
||||||
|
|
||||||
int ret = http_server_wait(server, &res, &res);
|
int ret = http_server_wait(server, &req, &res);
|
||||||
if (ret < 0) return -1;
|
if (ret < 0) return -1;
|
||||||
|
|
||||||
http_response_status(res, 200);
|
http_response_status(res, 200);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <stddef.h>
|
||||||
#include <chttp.h>
|
#include <chttp.h>
|
||||||
|
|
||||||
// This is an example of how to serve different websites
|
// This is an example of how to serve different websites
|
||||||
@@ -41,6 +42,7 @@ int main(void)
|
|||||||
// certificates using the add_website function
|
// certificates using the add_website function
|
||||||
|
|
||||||
ret = http_server_add_website(server,
|
ret = http_server_add_website(server,
|
||||||
|
HTTP_STR("websiteB.com"),
|
||||||
HTTP_STR("websiteB_cert.pem"),
|
HTTP_STR("websiteB_cert.pem"),
|
||||||
HTTP_STR("websiteB_key.pem")
|
HTTP_STR("websiteB_key.pem")
|
||||||
);
|
);
|
||||||
@@ -48,6 +50,7 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ret = http_server_add_website(server,
|
ret = http_server_add_website(server,
|
||||||
|
HTTP_STR("websiteC.com"),
|
||||||
HTTP_STR("websiteC_cert.pem"),
|
HTTP_STR("websiteC_cert.pem"),
|
||||||
HTTP_STR("websiteC_key.pem")
|
HTTP_STR("websiteC_key.pem")
|
||||||
);
|
);
|
||||||
@@ -94,13 +97,13 @@ int main(void)
|
|||||||
if (http_streq(host, HTTP_STR("websiteB.com"))) {
|
if (http_streq(host, HTTP_STR("websiteB.com"))) {
|
||||||
|
|
||||||
http_response_status(res, 200);
|
http_response_status(res, 200);
|
||||||
http_response_body(res, "Hello from websiteB.com!");
|
http_response_body(res, HTTP_STR("Hello from websiteB.com!"));
|
||||||
http_response_done(res);
|
http_response_done(res);
|
||||||
|
|
||||||
} else if (http_streq(host, HTTP_STR("websiteC.com"))) {
|
} else if (http_streq(host, HTTP_STR("websiteC.com"))) {
|
||||||
|
|
||||||
http_response_status(res, 200);
|
http_response_status(res, 200);
|
||||||
http_response_body(res, "Hello from websiteC.com!");
|
http_response_body(res, HTTP_STR("Hello from websiteC.com!"));
|
||||||
http_response_done(res);
|
http_response_done(res);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -109,7 +112,7 @@ int main(void)
|
|||||||
// with the certificate setup
|
// with the certificate setup
|
||||||
|
|
||||||
http_response_status(res, 200);
|
http_response_status(res, 200);
|
||||||
http_response_body(res, "Hello from websiteA.com!");
|
http_response_body(res, HTTP_STR("Hello from websiteA.com!"));
|
||||||
http_response_done(res);
|
http_response_done(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-2
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
AmalgamationBuilder - Implementation with improved #line support
|
AmalgamationBuilder - Implementation with improved #line support and conditional include preservation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
@@ -25,6 +25,8 @@ class AmalgamationBuilder:
|
|||||||
original_line_number = 1
|
original_line_number = 1
|
||||||
skipped_lines = 0
|
skipped_lines = 0
|
||||||
first_content_line = True
|
first_content_line = True
|
||||||
|
in_conditional_block = False
|
||||||
|
conditional_depth = 0
|
||||||
|
|
||||||
self.body += "//////////////////////////////////////////////////////////////////////\n"
|
self.body += "//////////////////////////////////////////////////////////////////////\n"
|
||||||
self.body += "// " + filepath + "\n"
|
self.body += "// " + filepath + "\n"
|
||||||
@@ -32,7 +34,33 @@ class AmalgamationBuilder:
|
|||||||
self.body += "\n"
|
self.body += "\n"
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
# Check if the line is an include
|
# Check if we're entering a conditional block
|
||||||
|
if self._is_conditional_start(line):
|
||||||
|
if conditional_depth == 0:
|
||||||
|
in_conditional_block = True
|
||||||
|
conditional_depth += 1
|
||||||
|
# Keep conditional blocks in place
|
||||||
|
self.body += line
|
||||||
|
original_line_number += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check if we're exiting a conditional block
|
||||||
|
if self._is_conditional_end(line):
|
||||||
|
conditional_depth -= 1
|
||||||
|
if conditional_depth == 0:
|
||||||
|
in_conditional_block = False
|
||||||
|
# Keep conditional blocks in place
|
||||||
|
self.body += line
|
||||||
|
original_line_number += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If we're inside a conditional block, keep all lines as-is
|
||||||
|
if in_conditional_block:
|
||||||
|
self.body += line
|
||||||
|
original_line_number += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check if the line is an include (outside conditional blocks only)
|
||||||
if self._is_include_line(line):
|
if self._is_include_line(line):
|
||||||
include_info = self._extract_include_info(line)
|
include_info = self._extract_include_info(line)
|
||||||
if include_info:
|
if include_info:
|
||||||
@@ -69,6 +97,18 @@ class AmalgamationBuilder:
|
|||||||
self.body += line
|
self.body += line
|
||||||
original_line_number += 1
|
original_line_number += 1
|
||||||
|
|
||||||
|
def _is_conditional_start(self, line: str) -> bool:
|
||||||
|
"""Check if a line starts a conditional compilation block"""
|
||||||
|
stripped = line.strip()
|
||||||
|
return (stripped.startswith('#ifdef ') or
|
||||||
|
stripped.startswith('#ifndef ') or
|
||||||
|
stripped.startswith('#if '))
|
||||||
|
|
||||||
|
def _is_conditional_end(self, line: str) -> bool:
|
||||||
|
"""Check if a line ends a conditional compilation block"""
|
||||||
|
stripped = line.strip()
|
||||||
|
return stripped.startswith('#endif')
|
||||||
|
|
||||||
def _is_include_line(self, line: str) -> bool:
|
def _is_include_line(self, line: str) -> bool:
|
||||||
"""Check if a line is an #include directive"""
|
"""Check if a line is an #include directive"""
|
||||||
# Skip obviously non-include lines for performance
|
# Skip obviously non-include lines for performance
|
||||||
@@ -185,6 +225,7 @@ def main():
|
|||||||
"src/engine.c",
|
"src/engine.c",
|
||||||
"src/socket.c",
|
"src/socket.c",
|
||||||
"src/client.c",
|
"src/client.c",
|
||||||
|
"src/cert.c",
|
||||||
"src/server.c",
|
"src/server.c",
|
||||||
"src/router.c"
|
"src/router.c"
|
||||||
]
|
]
|
||||||
|
|||||||
+23
-1
@@ -1,12 +1,19 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/conf.h>
|
#include <openssl/conf.h>
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cert.h"
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
|
||||||
static EVP_PKEY *generate_rsa_key_pair(int key_bits)
|
static EVP_PKEY *generate_rsa_key_pair(int key_bits)
|
||||||
{
|
{
|
||||||
@@ -137,4 +144,19 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
|||||||
X509_free(x509);
|
X509_free(x509);
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
|
||||||
|
HTTP_String cert_file, HTTP_String key_file)
|
||||||
|
{
|
||||||
|
(void) C;
|
||||||
|
(void) O;
|
||||||
|
(void) CN;
|
||||||
|
(void) cert_file;
|
||||||
|
(void) key_file;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+17
-12
@@ -1,14 +1,22 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <winsock2.h>
|
||||||
|
#define POLL WSAPoll
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <poll.h>
|
||||||
|
#define POLL poll
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
#include <stdio.h>
|
|
||||||
#define ERROR printf("error at %s:%d\n", __FILE__, __LINE__);
|
|
||||||
|
|
||||||
#define CLIENT_MAX_CONNS 256
|
#define CLIENT_MAX_CONNS 256
|
||||||
|
|
||||||
@@ -200,7 +208,7 @@ int http_client_wait(HTTP_Client *client, HTTP_RequestHandle *handle)
|
|||||||
if (num_polled == 0)
|
if (num_polled == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
poll(polled, num_polled, -1);
|
POLL(polled, num_polled, -1);
|
||||||
|
|
||||||
for (int i = 0; i < num_polled; i++) {
|
for (int i = 0; i < num_polled; i++) {
|
||||||
|
|
||||||
@@ -275,7 +283,6 @@ void http_request_line(HTTP_RequestHandle handle, HTTP_Method method, HTTP_Strin
|
|||||||
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
int ret = http_parse_url(url.ptr, url.len, &parsed_url);
|
||||||
if (ret != url.len) {
|
if (ret != url.len) {
|
||||||
// TODO
|
// TODO
|
||||||
ERROR;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +291,6 @@ void http_request_line(HTTP_RequestHandle handle, HTTP_Method method, HTTP_Strin
|
|||||||
secure = true;
|
secure = true;
|
||||||
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
} else if (!http_streq(parsed_url.scheme, HTTP_STR("http"))) {
|
||||||
// TODO
|
// TODO
|
||||||
ERROR;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +310,6 @@ void http_request_line(HTTP_RequestHandle handle, HTTP_Method method, HTTP_Strin
|
|||||||
|
|
||||||
case HTTP_HOST_MODE_VOID:
|
case HTTP_HOST_MODE_VOID:
|
||||||
// TODO
|
// TODO
|
||||||
ERROR;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,16 +1,16 @@
|
|||||||
|
#include <stdio.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h> // TODO: remove some of these headers
|
#include <assert.h> // TODO: remove some of these headers
|
||||||
#include <stdio.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "basic.h"
|
#include "basic.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "byte_queue.h"
|
|
||||||
|
|
||||||
// This is the implementation of a byte queue useful
|
// This is the implementation of a byte queue useful
|
||||||
// for systems that need to process engs of bytes.
|
// for systems that need to process engs of bytes.
|
||||||
|
|||||||
+17
-2
@@ -1,15 +1,30 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "router.h"
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "router.h"
|
||||||
|
|
||||||
|
bool is_alpha(char c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_digit(char c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ROUTE_STATIC_DIR,
|
ROUTE_STATIC_DIR,
|
||||||
ROUTE_DYNAMIC,
|
ROUTE_DYNAMIC,
|
||||||
|
|||||||
+33
-23
@@ -1,8 +1,20 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <winsock2.h>
|
||||||
|
#define POLL WSAPoll
|
||||||
|
#define CLOSE_SOCKET closesocket
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdlib.h>
|
#define CLOSE_SOCKET close
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
@@ -39,12 +51,12 @@ static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
{
|
{
|
||||||
int flags = fcntl(listen_fd, F_GETFL, 0);
|
int flags = fcntl(listen_fd, F_GETFL, 0);
|
||||||
if (flags < 0) {
|
if (flags < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +73,7 @@ static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
|
|
||||||
_Static_assert(sizeof(struct in_addr) == sizeof(HTTP_IPv4));
|
_Static_assert(sizeof(struct in_addr) == sizeof(HTTP_IPv4));
|
||||||
if (http_parse_ipv4(addr.ptr, addr.len, (HTTP_IPv4*) &addr_buf) < 0) {
|
if (http_parse_ipv4(addr.ptr, addr.len, (HTTP_IPv4*) &addr_buf) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,12 +83,12 @@ static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int b
|
|||||||
bind_buf.sin_addr = addr_buf;
|
bind_buf.sin_addr = addr_buf;
|
||||||
bind_buf.sin_port = htons(port);
|
bind_buf.sin_port = htons(port);
|
||||||
if (bind(listen_fd, (struct sockaddr*) &bind_buf, sizeof(bind_buf)) < 0) {
|
if (bind(listen_fd, (struct sockaddr*) &bind_buf, sizeof(bind_buf)) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(listen_fd, backlog) < 0) {
|
if (listen(listen_fd, backlog) < 0) {
|
||||||
close(listen_fd);
|
CLOSE_SOCKET(listen_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +131,7 @@ HTTP_Server *http_server_init_ex(HTTP_String addr, uint16_t port,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
if (socket_group_init_server(&server->group, cert_key, private_key) < 0) {
|
if (socket_group_init_server(&server->group, cert_key, private_key) < 0) {
|
||||||
close(server->listen_fd);
|
CLOSE_SOCKET(server->listen_fd);
|
||||||
free(server);
|
free(server);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -127,7 +139,7 @@ HTTP_Server *http_server_init_ex(HTTP_String addr, uint16_t port,
|
|||||||
server->secure_fd = listen_socket(addr, secure_port, reuse_addr, backlog);
|
server->secure_fd = listen_socket(addr, secure_port, reuse_addr, backlog);
|
||||||
if (server->secure_fd < 0) {
|
if (server->secure_fd < 0) {
|
||||||
socket_group_free(&server->group);
|
socket_group_free(&server->group);
|
||||||
close(server->listen_fd);
|
CLOSE_SOCKET(server->listen_fd);
|
||||||
free(server);
|
free(server);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -156,14 +168,14 @@ void http_server_free(HTTP_Server *server)
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
close(server->secure_fd);
|
CLOSE_SOCKET(server->secure_fd);
|
||||||
close(server->listen_fd);
|
CLOSE_SOCKET(server->listen_fd);
|
||||||
if (server->secure_fd != -1)
|
if (server->secure_fd != -1)
|
||||||
socket_group_free(&server->group);
|
socket_group_free(&server->group);
|
||||||
free(server);
|
free(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_server_website(HTTP_Server *server, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
int http_server_add_website(HTTP_Server *server, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
||||||
{
|
{
|
||||||
return socket_group_add_domain(&server->group, domain, cert_file, key_file);
|
return socket_group_add_domain(&server->group, domain, cert_file, key_file);
|
||||||
}
|
}
|
||||||
@@ -209,24 +221,21 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
|
|||||||
|
|
||||||
for (int i = 0, j = 0; i < server->num_conns; i++) {
|
for (int i = 0, j = 0; i < server->num_conns; i++) {
|
||||||
|
|
||||||
if (!server->conns[i].used)
|
Connection *conn = &server->conns[i];
|
||||||
|
|
||||||
|
if (!conn->used)
|
||||||
continue;
|
continue;
|
||||||
j++;
|
j++;
|
||||||
|
|
||||||
int events = 0;
|
int events = 0;
|
||||||
|
switch (conn->socket.event) {
|
||||||
if (server->conns[i].socket.ssl_ctx)
|
case SOCKET_WANT_NONE: events = 0; break;
|
||||||
events = server->conns[i].socket.event;
|
case SOCKET_WANT_READ: events = POLLIN; break;
|
||||||
else {
|
case SOCKET_WANT_WRITE: events = POLLOUT; break;
|
||||||
switch (http_engine_state(&server->conns[i].engine)) {
|
|
||||||
case HTTP_ENGINE_STATE_SERVER_RECV_BUF: events = POLLIN; break;
|
|
||||||
case HTTP_ENGINE_STATE_SERVER_SEND_BUF: events = POLLOUT; break;
|
|
||||||
default:break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events) {
|
if (events) {
|
||||||
polled[num_polled].fd = server->conns[i].socket.fd;
|
polled[num_polled].fd = conn->socket.fd;
|
||||||
polled[num_polled].events = events;
|
polled[num_polled].events = events;
|
||||||
polled[num_polled].revents = 0;
|
polled[num_polled].revents = 0;
|
||||||
indices[num_polled] = i;
|
indices[num_polled] = i;
|
||||||
@@ -235,7 +244,7 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
|
|||||||
}
|
}
|
||||||
|
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
poll(polled, num_polled, timeout);
|
POLL(polled, num_polled, timeout);
|
||||||
|
|
||||||
for (int i = 0; i < num_polled; i++) {
|
for (int i = 0; i < num_polled; i++) {
|
||||||
|
|
||||||
@@ -255,6 +264,7 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
|
|||||||
|
|
||||||
server->conns[k].used = true;
|
server->conns[k].used = true;
|
||||||
socket_accept(&server->conns[k].socket, secure ? &server->group : NULL, new_fd);
|
socket_accept(&server->conns[k].socket, secure ? &server->group : NULL, new_fd);
|
||||||
|
|
||||||
http_engine_init(&server->conns[k].engine, 0, server_memfunc, NULL);
|
http_engine_init(&server->conns[k].engine, 0, server_memfunc, NULL);
|
||||||
server->num_conns++;
|
server->num_conns++;
|
||||||
}
|
}
|
||||||
|
|||||||
+129
-27
@@ -1,16 +1,17 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <assert.h>
|
#include <assert.h> // TODO: organize these includes
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/conf.h>
|
#include <openssl/conf.h>
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -18,22 +19,34 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
void socket_global_init(void)
|
void socket_global_init(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_global_free(void)
|
void socket_global_free(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_group_init(SocketGroup *group)
|
int socket_group_init(SocketGroup *group)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_client_method());
|
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_client_method());
|
||||||
if (!ssl_ctx) {
|
if (!ssl_ctx) {
|
||||||
fprintf(stderr, "Unable to create SSL context\n");
|
fprintf(stderr, "Unable to create SSL context\n");
|
||||||
@@ -59,9 +72,13 @@ int socket_group_init(SocketGroup *group)
|
|||||||
group->domains = NULL;
|
group->domains = NULL;
|
||||||
group->num_domains = 0;
|
group->num_domains = 0;
|
||||||
group->max_domains = 0;
|
group->max_domains = 0;
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
static int servername_callback(SSL *ssl, int *ad, void *arg)
|
static int servername_callback(SSL *ssl, int *ad, void *arg)
|
||||||
{
|
{
|
||||||
SocketGroup *group = arg;
|
SocketGroup *group = arg;
|
||||||
@@ -80,9 +97,11 @@ static int servername_callback(SSL *ssl, int *ad, void *arg)
|
|||||||
|
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int socket_group_init_server(SocketGroup *group, HTTP_String cert_file, HTTP_String key_file)
|
int socket_group_init_server(SocketGroup *group, HTTP_String cert_file, HTTP_String key_file)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_server_method());
|
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_server_method());
|
||||||
if (!ssl_ctx) {
|
if (!ssl_ctx) {
|
||||||
fprintf(stderr, "Unable to create server SSL context\n");
|
fprintf(stderr, "Unable to create server SSL context\n");
|
||||||
@@ -143,16 +162,27 @@ int socket_group_init_server(SocketGroup *group, HTTP_String cert_file, HTTP_Str
|
|||||||
group->domains = NULL;
|
group->domains = NULL;
|
||||||
group->num_domains = 0;
|
group->num_domains = 0;
|
||||||
group->max_domains = 0;
|
group->max_domains = 0;
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
if (cert_file.len > 0 || key_file.len > 0)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_group_free(SocketGroup *group)
|
void socket_group_free(SocketGroup *group)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX_free(group->ssl_ctx);
|
SSL_CTX_free(group->ssl_ctx);
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String cert_file, HTTP_String key_file)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
if (group->num_domains == group->max_domains) {
|
if (group->num_domains == group->max_domains) {
|
||||||
|
|
||||||
int new_max_domains = 2 * group->max_domains;
|
int new_max_domains = 2 * group->max_domains;
|
||||||
@@ -236,6 +266,13 @@ int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String
|
|||||||
domain_info->ssl_ctx = ssl_ctx;
|
domain_info->ssl_ctx = ssl_ctx;
|
||||||
group->num_domains++;
|
group->num_domains++;
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
(void) group;
|
||||||
|
(void) domain;
|
||||||
|
(void) cert_file;
|
||||||
|
(void) key_file;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketState socket_state(Socket *sock)
|
SocketState socket_state(Socket *sock)
|
||||||
@@ -245,12 +282,20 @@ SocketState socket_state(Socket *sock)
|
|||||||
|
|
||||||
void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize socket for server-side TLS handshake
|
// Initialize socket for server-side TLS handshake
|
||||||
sock->state = SOCKET_STATE_ACCEPTED; // TCP connection already established
|
sock->state = SOCKET_STATE_ACCEPTED; // TCP connection already established
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = fd;
|
sock->fd = fd;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -258,7 +303,7 @@ void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
|||||||
sock->port = 0;
|
sock->port = 0;
|
||||||
|
|
||||||
// Set non-blocking mode for the accepted socket
|
// Set non-blocking mode for the accepted socket
|
||||||
int flags = fcntl(fd, F_GETFL, 0);
|
int flags = fcntl(fd, F_GETFL, 0); // TODO: fail on error
|
||||||
if (flags >= 0) {
|
if (flags >= 0) {
|
||||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||||
}
|
}
|
||||||
@@ -267,12 +312,20 @@ void socket_accept(Socket *sock, SocketGroup *group, int fd)
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_connect(Socket *sock, SocketGroup *group, HTTP_String host, uint16_t port) {
|
void socket_connect(Socket *sock, SocketGroup *group, HTTP_String host, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -322,12 +375,20 @@ void socket_connect(Socket *sock, SocketGroup *group, HTTP_String host, uint16_t
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_connect_ipv4(Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint16_t port) {
|
void socket_connect_ipv4(Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -343,12 +404,20 @@ void socket_connect_ipv4(Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint1
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_connect_ipv6(Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint16_t port) {
|
void socket_connect_ipv6(Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint16_t port)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
sock->ssl = NULL;
|
||||||
|
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
||||||
|
#else
|
||||||
|
if (group) {
|
||||||
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
sock->ssl = NULL;
|
|
||||||
sock->ssl_ctx = group ? group->ssl_ctx : NULL;
|
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
sock->addr_count = 0;
|
sock->addr_count = 0;
|
||||||
sock->addr_cursor = 0;
|
sock->addr_cursor = 0;
|
||||||
@@ -364,6 +433,16 @@ void socket_connect_ipv6(Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint1
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool socket_secure(Socket *sock)
|
||||||
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
|
return sock->ssl_ctx != NULL;
|
||||||
|
#else
|
||||||
|
(void) sock;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void socket_update(Socket *sock)
|
void socket_update(Socket *sock)
|
||||||
{
|
{
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
@@ -376,10 +455,12 @@ void socket_update(Socket *sock)
|
|||||||
switch (sock->state) {
|
switch (sock->state) {
|
||||||
case SOCKET_STATE_PENDING:
|
case SOCKET_STATE_PENDING:
|
||||||
{
|
{
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
if (sock->ssl) {
|
if (sock->ssl) {
|
||||||
SSL_free(sock->ssl);
|
SSL_free(sock->ssl);
|
||||||
sock->ssl = NULL;
|
sock->ssl = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (sock->fd != -1)
|
if (sock->fd != -1)
|
||||||
close(sock->fd);
|
close(sock->fd);
|
||||||
@@ -485,11 +566,11 @@ void socket_update(Socket *sock)
|
|||||||
|
|
||||||
case SOCKET_STATE_CONNECTED:
|
case SOCKET_STATE_CONNECTED:
|
||||||
{
|
{
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
// Start SSL handshake
|
// Start SSL handshake
|
||||||
if (!sock->ssl) {
|
if (!sock->ssl) {
|
||||||
sock->ssl = SSL_new(sock->ssl_ctx);
|
sock->ssl = SSL_new(sock->ssl_ctx);
|
||||||
@@ -521,17 +602,20 @@ void socket_update(Socket *sock)
|
|||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_PENDING;
|
sock->state = SOCKET_STATE_PENDING;
|
||||||
again = true;
|
again = true;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOCKET_STATE_ACCEPTED:
|
case SOCKET_STATE_ACCEPTED:
|
||||||
{
|
{
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
sock->state = SOCKET_STATE_ESTABLISHED_READY;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
// Start server-side SSL handshake
|
// Start server-side SSL handshake
|
||||||
if (!sock->ssl) {
|
if (!sock->ssl) {
|
||||||
sock->ssl = SSL_new(sock->ssl_ctx);
|
sock->ssl = SSL_new(sock->ssl_ctx);
|
||||||
@@ -560,6 +644,9 @@ void socket_update(Socket *sock)
|
|||||||
// Server socket error - close the connection
|
// Server socket error - close the connection
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -573,11 +660,11 @@ void socket_update(Socket *sock)
|
|||||||
|
|
||||||
case SOCKET_STATE_SHUTDOWN:
|
case SOCKET_STATE_SHUTDOWN:
|
||||||
{
|
{
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
int ret = SSL_shutdown(sock->ssl);
|
int ret = SSL_shutdown(sock->ssl);
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
@@ -598,6 +685,9 @@ void socket_update(Socket *sock)
|
|||||||
|
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
sock->state = SOCKET_STATE_DIED;
|
sock->state = SOCKET_STATE_DIED;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -618,7 +708,7 @@ int socket_read(Socket *sock, char *dst, int max) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
int ret = read(sock->fd, dst, max);
|
int ret = read(sock->fd, dst, max);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
sock->event = SOCKET_WANT_NONE;
|
sock->event = SOCKET_WANT_NONE;
|
||||||
@@ -639,6 +729,7 @@ int socket_read(Socket *sock, char *dst, int max) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
int ret = SSL_read(sock->ssl, dst, max);
|
int ret = SSL_read(sock->ssl, dst, max);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
int err = SSL_get_error(sock->ssl, ret);
|
int err = SSL_get_error(sock->ssl, ret);
|
||||||
@@ -657,6 +748,10 @@ int socket_read(Socket *sock, char *dst, int max) {
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,7 +763,7 @@ int socket_write(Socket *sock, char *src, int len) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->ssl_ctx == NULL) {
|
if (!socket_secure(sock)) {
|
||||||
int ret = write(sock->fd, src, len);
|
int ret = write(sock->fd, src, len);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
@@ -684,6 +779,7 @@ int socket_write(Socket *sock, char *src, int len) {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
int ret = SSL_write(sock->ssl, src, len);
|
int ret = SSL_write(sock->ssl, src, len);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
int err = SSL_get_error(sock->ssl, ret);
|
int err = SSL_get_error(sock->ssl, ret);
|
||||||
@@ -702,6 +798,9 @@ int socket_write(Socket *sock, char *src, int len) {
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
#else
|
||||||
|
HTTP_ASSERT(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,20 +811,23 @@ void socket_close(Socket *sock) {
|
|||||||
socket_update(sock);
|
socket_update(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_free(Socket *sock) {
|
void socket_free(Socket *sock)
|
||||||
// Release all resources associated to the socket
|
{
|
||||||
if (sock->ssl) {
|
#ifdef HTTPS_ENABLED
|
||||||
|
if (sock->ssl)
|
||||||
SSL_free(sock->ssl);
|
SSL_free(sock->ssl);
|
||||||
sock->ssl = NULL;
|
#endif
|
||||||
}
|
|
||||||
if (sock->fd >= 0) {
|
if (sock->fd >= 0) {
|
||||||
close(sock->fd);
|
close(sock->fd);
|
||||||
sock->fd = -1;
|
sock->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->hostname) {
|
if (sock->hostname) {
|
||||||
free(sock->hostname);
|
free(sock->hostname);
|
||||||
sock->hostname = NULL;
|
sock->hostname = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock->addr_list) {
|
if (sock->addr_list) {
|
||||||
free(sock->addr_list);
|
free(sock->addr_list);
|
||||||
sock->addr_list = NULL;
|
sock->addr_list = NULL;
|
||||||
|
|||||||
+11
-2
@@ -53,12 +53,15 @@
|
|||||||
// which means the user needs to call socket_free to free the socket
|
// which means the user needs to call socket_free to free the socket
|
||||||
// as it's not unusable.
|
// as it's not unusable.
|
||||||
|
|
||||||
#include <errno.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "parse.h"
|
#ifdef HTTPS_ENABLED
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int is_ipv6;
|
int is_ipv6;
|
||||||
@@ -89,8 +92,10 @@ typedef struct {
|
|||||||
SocketState state;
|
SocketState state;
|
||||||
SocketWantEvent event;
|
SocketWantEvent event;
|
||||||
int fd;
|
int fd;
|
||||||
|
#if HTTPS_ENABLED
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
|
#endif
|
||||||
AddrInfo *addr_list;
|
AddrInfo *addr_list;
|
||||||
int addr_count;
|
int addr_count;
|
||||||
int addr_cursor;
|
int addr_cursor;
|
||||||
@@ -98,16 +103,20 @@ typedef struct {
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
} Socket;
|
} Socket;
|
||||||
|
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char name[128];
|
char name[128];
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
} Domain;
|
} Domain;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
#ifdef HTTPS_ENABLED
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
int num_domains;
|
int num_domains;
|
||||||
int max_domains;
|
int max_domains;
|
||||||
Domain *domains;
|
Domain *domains;
|
||||||
|
#endif
|
||||||
} SocketGroup;
|
} SocketGroup;
|
||||||
|
|
||||||
void socket_global_init (void);
|
void socket_global_init (void);
|
||||||
|
|||||||
Reference in New Issue
Block a user