Fix windows compilation errors

This commit is contained in:
2025-07-21 12:06:23 +02:00
parent acf4746611
commit 5cb3977c3c
14 changed files with 286 additions and 227 deletions
+132 -107
View File
@@ -62,6 +62,27 @@
#include <stdint.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#define SOCKET_TYPE SOCKET
#define BAD_SOCKET INVALID_SOCKET
#define POLL WSAPoll
#define CLOSE_SOCKET closesocket
#endif
#ifdef __linux__
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
#define SOCKET_TYPE int
#define BAD_SOCKET -1
#define POLL poll
#define CLOSE_SOCKET close
#endif
#ifdef HTTPS_ENABLED
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -100,7 +121,7 @@ typedef enum {
typedef struct {
SocketState state;
SocketWantEvent event;
int fd;
SOCKET_TYPE fd;
#if HTTPS_ENABLED
SSL *ssl;
SSL_CTX *ssl_ctx;
@@ -128,6 +149,9 @@ typedef struct {
#endif
} SocketGroup;
SOCKET_TYPE listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog);
void socket_global_init (void);
void socket_global_free (void);
int socket_group_init (SocketGroup *group);
@@ -135,7 +159,7 @@ int socket_group_init_server(SocketGroup *group, HTTP_String cert_file,
int socket_group_add_domain(SocketGroup *group, HTTP_String domain, HTTP_String cert_key, HTTP_String private_key);
void socket_group_free (SocketGroup *group);
SocketState socket_state (Socket *sock);
void socket_accept (Socket *sock, SocketGroup *group, int fd);
void socket_accept (Socket *sock, SocketGroup *group, SOCKET_TYPE fd);
void socket_connect (Socket *sock, SocketGroup *group, HTTP_String host, uint16_t port);
void socket_connect_ipv4 (Socket *sock, SocketGroup *group, HTTP_IPv4 addr, uint16_t port);
void socket_connect_ipv6 (Socket *sock, SocketGroup *group, HTTP_IPv6 addr, uint16_t port);
@@ -2491,11 +2515,15 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#define POLL WSAPoll
#endif
#ifdef __linux__
#include <poll.h>
#include <netdb.h>
#include <fcntl.h>
#define POLL poll
#endif
#ifdef HTTPS_ENABLED
@@ -2511,6 +2539,71 @@ int http_create_test_certificate(HTTP_String C, HTTP_String O, HTTP_String CN,
#include "socket.h"
#endif
static int set_socket_blocking(SOCKET_TYPE sock, bool value)
{
#ifdef _WIN32
u_long mode = !value;
if (ioctlsocket(sock, FIONBIO, &mode) == SOCKET_ERROR)
return -1;
#endif
#ifdef __linux__
int flags = fcntl(listen_fd, F_GETFL, 0);
if (flags < 0)
return -1;
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) < 0)
return BAD_SOCKET;
#endif
return 0;
}
SOCKET_TYPE listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog)
{
SOCKET_TYPE listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd == BAD_SOCKET)
return BAD_SOCKET;
if (set_socket_blocking(listen_fd, false) < 0) {
CLOSE_SOCKET(listen_fd);
return BAD_SOCKET;
}
if (reuse_addr) {
int one = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*) &one, sizeof(one));
}
struct in_addr addr_buf;
if (addr.len == 0)
addr_buf.s_addr = htonl(INADDR_ANY);
else {
_Static_assert(sizeof(struct in_addr) == sizeof(HTTP_IPv4));
if (http_parse_ipv4(addr.ptr, addr.len, (HTTP_IPv4*) &addr_buf) < 0) {
CLOSE_SOCKET(listen_fd);
return BAD_SOCKET;
}
}
struct sockaddr_in bind_buf;
bind_buf.sin_family = AF_INET;
bind_buf.sin_addr = addr_buf;
bind_buf.sin_port = htons(port);
if (bind(listen_fd, (struct sockaddr*) &bind_buf, sizeof(bind_buf)) < 0) { // TODO: how does bind fail on windows?
CLOSE_SOCKET(listen_fd);
return BAD_SOCKET;
}
if (listen(listen_fd, backlog) < 0) { // TODO: how does listen fail on windows?
CLOSE_SOCKET(listen_fd);
return BAD_SOCKET;
}
return listen_fd;
}
void socket_global_init(void)
{
#ifdef HTTPS_ENABLED
@@ -2764,7 +2857,7 @@ SocketState socket_state(Socket *sock)
return sock->state;
}
void socket_accept(Socket *sock, SocketGroup *group, int fd)
void socket_accept(Socket *sock, SocketGroup *group, SOCKET_TYPE fd)
{
#ifdef HTTPS_ENABLED
sock->ssl = NULL;
@@ -2785,13 +2878,12 @@ void socket_accept(Socket *sock, SocketGroup *group, int fd)
sock->addr_cursor = 0;
sock->hostname = NULL;
sock->port = 0;
// Set non-blocking mode for the accepted socket
int flags = fcntl(fd, F_GETFL, 0); // TODO: fail on error
if (flags >= 0) {
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if (set_socket_blocking(fd, false) < 0) {
sock->state = SOCKET_STATE_DIED;
return;
}
// Start the TLS handshake process
socket_update(sock);
}
@@ -2946,8 +3038,8 @@ void socket_update(Socket *sock)
}
#endif
if (sock->fd != -1)
close(sock->fd);
if (sock->fd != BAD_SOCKET)
CLOSE_SOCKET(sock->fd);
// If cursor reached the end, die
if (sock->addr_cursor >= sock->addr_count) {
@@ -2959,8 +3051,8 @@ void socket_update(Socket *sock)
// Take current address
AddrInfo *ai = &sock->addr_list[sock->addr_cursor];
int family = ai->is_ipv6 ? AF_INET6 : AF_INET;
int fd = socket(family, SOCK_STREAM, 0);
if (fd < 0) {
SOCKET_TYPE fd = socket(family, SOCK_STREAM, 0);
if (fd == BAD_SOCKET) {
// Try next address
sock->addr_cursor++;
sock->event = SOCKET_WANT_NONE;
@@ -2969,9 +3061,12 @@ void socket_update(Socket *sock)
break;
}
// Set non-blocking
int flags = fcntl(fd, F_GETFL, 0);
if (flags >= 0) fcntl(fd, F_SETFL, flags | O_NONBLOCK); // TODO: Handle error by setting the socket to DIED
if (set_socket_blocking(fd, false) < 0) {
CLOSE_SOCKET(fd);
sock->event = SOCKET_WANT_NONE;
sock->state = SOCKET_STATE_DIED;
break;
}
// Prepare sockaddr
int ret;
@@ -2998,7 +3093,7 @@ void socket_update(Socket *sock)
break;
}
if (ret < 0 && errno == EINPROGRESS) {
if (ret < 0 && errno == EINPROGRESS) { // TODO: I'm pretty sure all the error numbers need to be changed for windows
// Connection pending
sock->fd = fd;
sock->event = SOCKET_WANT_WRITE;
@@ -3025,7 +3120,7 @@ void socket_update(Socket *sock)
// Check connect result
int err = 0;
socklen_t len = sizeof(err);
if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0 || err != 0) {
if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, (void*) &err, &len) < 0 || err != 0) {
close(sock->fd);
// If remote peer not working, try next address
if (err == ECONNREFUSED || err == ETIMEDOUT || err == ENETUNREACH || err == EHOSTUNREACH) {
@@ -3302,9 +3397,9 @@ void socket_free(Socket *sock)
SSL_free(sock->ssl);
#endif
if (sock->fd >= 0) {
close(sock->fd);
sock->fd = -1;
if (sock->fd != BAD_SOCKET) {
CLOSE_SOCKET(sock->fd);
sock->fd = BAD_SOCKET;
}
if (sock->hostname) {
@@ -3344,7 +3439,7 @@ int socket_wait(Socket **socks, int num_socks) // TODO: is this used?
polled[i].revents = 0;
}
int ret = poll(polled, num_socks, -1);
int ret = POLL(polled, num_socks, -1);
if (ret < 0)
return -1;
@@ -3842,23 +3937,6 @@ HTTP_Response *http_post(HTTP_String url, HTTP_String *headers, int num_headers,
#include <stdlib.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 <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
#define POLL poll
#define CLOSE_SOCKET close
#endif
#ifndef HTTP_AMALGAMATION
#include "engine.h"
#include "socket.h"
@@ -3877,8 +3955,8 @@ typedef struct {
struct HTTP_Server {
SocketGroup group;
int listen_fd;
int secure_fd;
SOCKET_TYPE listen_fd;
SOCKET_TYPE secure_fd;
int num_conns;
Connection conns[MAX_CONNS];
@@ -3888,59 +3966,6 @@ struct HTTP_Server {
int ready[MAX_CONNS];
};
static int listen_socket(HTTP_String addr, uint16_t port, bool reuse_addr, int backlog)
{
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0)
return -1;
{
int flags = fcntl(listen_fd, F_GETFL, 0);
if (flags < 0) {
CLOSE_SOCKET(listen_fd);
return -1;
}
if (fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
CLOSE_SOCKET(listen_fd);
return -1;
}
}
if (reuse_addr) {
int one = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
}
struct in_addr addr_buf;
if (addr.len == 0)
addr_buf.s_addr = htonl(INADDR_ANY);
else {
_Static_assert(sizeof(struct in_addr) == sizeof(HTTP_IPv4));
if (http_parse_ipv4(addr.ptr, addr.len, (HTTP_IPv4*) &addr_buf) < 0) {
CLOSE_SOCKET(listen_fd);
return -1;
}
}
struct sockaddr_in bind_buf;
bind_buf.sin_family = AF_INET;
bind_buf.sin_addr = addr_buf;
bind_buf.sin_port = htons(port);
if (bind(listen_fd, (struct sockaddr*) &bind_buf, sizeof(bind_buf)) < 0) {
CLOSE_SOCKET(listen_fd);
return -1;
}
if (listen(listen_fd, backlog) < 0) {
CLOSE_SOCKET(listen_fd);
return -1;
}
return listen_fd;
}
HTTP_Server *http_server_init(HTTP_String addr, uint16_t port)
{
return http_server_init_ex(addr, port, 0, HTTP_STR(""), HTTP_STR(""));
@@ -3963,17 +3988,17 @@ HTTP_Server *http_server_init_ex(HTTP_String addr, uint16_t port,
}
if (port == 0)
server->listen_fd = -1;
server->listen_fd = BAD_SOCKET;
else {
server->listen_fd = listen_socket(addr, port, reuse_addr, backlog);
if (server->listen_fd < 0) {
if (server->listen_fd == BAD_SOCKET) {
free(server);
return NULL;
}
}
if (secure_port == 0)
server->secure_fd = -1;
server->secure_fd = BAD_SOCKET;
else {
if (socket_group_init_server(&server->group, cert_key, private_key) < 0) {
@@ -3983,7 +4008,7 @@ HTTP_Server *http_server_init_ex(HTTP_String addr, uint16_t port,
}
server->secure_fd = listen_socket(addr, secure_port, reuse_addr, backlog);
if (server->secure_fd < 0) {
if (server->secure_fd == BAD_SOCKET) {
socket_group_free(&server->group);
CLOSE_SOCKET(server->listen_fd);
free(server);
@@ -4016,7 +4041,7 @@ void http_server_free(HTTP_Server *server)
CLOSE_SOCKET(server->secure_fd);
CLOSE_SOCKET(server->listen_fd);
if (server->secure_fd != -1)
if (server->secure_fd != BAD_SOCKET)
socket_group_free(&server->group);
free(server);
}
@@ -4048,7 +4073,7 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
if (server->num_conns < MAX_CONNS) {
if (server->listen_fd != -1) {
if (server->listen_fd != BAD_SOCKET) {
polled[num_polled].fd = server->listen_fd;
polled[num_polled].events = POLLIN;
polled[num_polled].revents = 0;
@@ -4056,7 +4081,7 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
num_polled++;
}
if (server->secure_fd != -1) {
if (server->secure_fd != BAD_SOCKET) {
polled[num_polled].fd = server->secure_fd;
polled[num_polled].events = POLLIN;
polled[num_polled].revents = 0;
@@ -4102,7 +4127,10 @@ int http_server_wait(HTTP_Server *server, HTTP_Request **req, HTTP_ResponseHandl
if ((polled[i].revents & POLLIN) && server->num_conns < MAX_CONNS) {
int new_fd = accept(polled[i].fd, NULL, NULL);
SOCKET_TYPE new_fd = accept(polled[i].fd, NULL, NULL);
if (new_fd == BAD_SOCKET) {
// TODO
}
int k = 0;
while (server->conns[k].used)
@@ -4211,16 +4239,13 @@ void http_response_status(HTTP_ResponseHandle res, int status)
http_engine_status(&conn->engine, status);
}
void http_response_header(HTTP_ResponseHandle res, const char *fmt, ...)
void http_response_header(HTTP_ResponseHandle res, HTTP_String str)
{
Connection *conn = handle2conn(res);
if (conn == NULL)
return;
va_list args;
va_start(args, fmt);
http_engine_header_fmt2(&conn->engine, fmt, args);
va_end(args);
http_engine_header(&conn->engine, str);
}
void http_response_body(HTTP_ResponseHandle res, HTTP_String str)