Fix compilation errors

This commit is contained in:
2024-04-09 14:34:06 +02:00
parent 14f33a7ef5
commit b8232cce15
5 changed files with 107 additions and 61 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
gcc example.c io.c -o example -Wall -Wextra -ggdb gcc example.c io2.c -o example -Wall -Wextra -ggdb -lws2_32
gcc example2.c io.c -o example2 -Wall -Wextra -ggdb -lws2_32 gcc example2.c io2.c -o example2 -Wall -Wextra -ggdb -lws2_32
+4 -4
View File
@@ -18,15 +18,15 @@ int main()
for (int i = 0; i < NUM_OPS; i++) { for (int i = 0; i < NUM_OPS; i++) {
char name[1<<8]; char name[1<<8];
snprintf(name, sizeof(name), "file_%d.txt", i); snprintf(name, sizeof(name), "file_%d.txt", i);
files[i] = io_create_file(&ioc, name, IO_CREATE_CANTEXIST, NULL); files[i] = io_create_file(&ioc, name, IO_CREATE_CANTEXIST);
if (files[i] == IO_INVALID_HANDLE) if (files[i] == IO_INVALID)
fprintf(stderr, "Couldn't create '%s'\n", name); fprintf(stderr, "Couldn't create '%s'\n", name);
} }
int started = 0; int started = 0;
char msg[] = "Hello, world!\n"; char msg[] = "Hello, world!\n";
for (int i = 0; i < NUM_OPS; i++) { for (int i = 0; i < NUM_OPS; i++) {
if (io_start_send(&ioc, files[i], msg, sizeof(msg)-1)) if (io_send(&ioc, NULL, files[i], msg, sizeof(msg)-1))
started++; started++;
else else
fprintf(stderr, "ERROR\n"); fprintf(stderr, "ERROR\n");
@@ -38,7 +38,7 @@ int main()
fprintf(stderr, "CONCLUDED\n"); fprintf(stderr, "CONCLUDED\n");
} }
io_context_free(&ioc); io_free(&ioc);
io_global_free(); io_global_free();
return 0; return 0;
} }
+11 -4
View File
@@ -1,6 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include "io.h" #include "io2.h"
#define MAX_RES 100 #define MAX_RES 100
#define MAX_OPS 100 #define MAX_OPS 100
@@ -14,6 +14,12 @@ int main(void)
struct io_operation ops[MAX_OPS]; struct io_operation ops[MAX_OPS];
struct io_resource res[MAX_RES]; struct io_resource res[MAX_RES];
struct io_context ioc; struct io_context ioc;
if (!io_global_init()) {
fprintf(stderr, "Couldn't perform the global initialization\n");
return -1;
}
if (!io_init(&ioc, res, ops, MAX_RES, MAX_OPS)) { if (!io_init(&ioc, res, ops, MAX_RES, MAX_OPS)) {
fprintf(stderr, "Couldn't initialize I/O context\n"); fprintf(stderr, "Couldn't initialize I/O context\n");
return -1; return -1;
@@ -24,7 +30,7 @@ int main(void)
fprintf(stderr, "Couldn't start listening\n"); fprintf(stderr, "Couldn't start listening\n");
return -1; return -1;
} }
if (!io_accept(&ioc, socket, NULL)) { if (!io_accept(&ioc, NULL, socket)) {
fprintf(stderr, "Couldn't start accept operation\n"); fprintf(stderr, "Couldn't start accept operation\n");
return -1; return -1;
} }
@@ -40,12 +46,13 @@ int main(void)
io_close(&ioc, accepted); io_close(&ioc, accepted);
if (!io_accept(&ioc, socket)) { if (!io_accept(&ioc, NULL, socket)) {
fprintf(stderr, "Couldn't start accept operation\n"); fprintf(stderr, "Couldn't start accept operation\n");
return -1; return -1;
} }
} }
io_context_free(&ioc); io_free(&ioc);
io_global_free();
return 0; return 0;
} }
+85 -49
View File
@@ -1,6 +1,6 @@
#include "io2.h" #include "io2.h"
#include <stdint.h> #include <assert.h>
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
@@ -9,11 +9,20 @@
#include <mswsock.h> #include <mswsock.h>
#endif #endif
#define IO_DEBUG
#ifdef IO_DEBUG
#include <stdio.h>
#define DEBUG_LOG(fmt, ...) fprintf(stderr, "Log :: %s:%d :: " fmt, __FILE__, __LINE__, ## __VA_ARGS__);
#else
#define DEBUG_LOG(...)
#endif
bool io_global_init(void) bool io_global_init(void)
{ {
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
WSADATA data; WSADATA data;
return WSAStartup(MAKEWORD(2, 2), &data) != NO_ERROR; return WSAStartup(MAKEWORD(2, 2), &data) == NO_ERROR;
#endif #endif
#if IO_PLATFORM_LINUX #if IO_PLATFORM_LINUX
@@ -31,7 +40,7 @@ void io_global_free(void)
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
bool io_init_windows(struct io_context *ioc) bool io_init_windows(struct io_context *ioc)
{ {
io_os_handle os_handle = CreateIoCompletionPort(IO_INVALID_HANDLE, NULL, 0, 1); io_os_handle os_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
if (os_handle == INVALID_HANDLE_VALUE) if (os_handle == INVALID_HANDLE_VALUE)
return false; return false;
@@ -189,7 +198,7 @@ close_internal(struct io_context *ioc,
{ {
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
if (res->type == IO_RES_SOCKET) if (res->type == IO_RES_SOCKET)
closesocket(res->os_handle); closesocket((SOCKET) res->os_handle);
else else
CloseHandle(res->os_handle); CloseHandle(res->os_handle);
#elif IO_PLATFORM_LINUX #elif IO_PLATFORM_LINUX
@@ -198,7 +207,7 @@ close_internal(struct io_context *ioc,
// Mark associated operation structures as unused // Mark associated operation structures as unused
for (uint16_t i = 0, marked = 0; marked < res->pending; i++) { for (uint16_t i = 0, marked = 0; marked < res->pending; i++) {
strct io_operation *op; struct io_operation *op;
op = &ioc->ops[i]; op = &ioc->ops[i];
if (op->type != IO_VOID && op->res == res) { if (op->type != IO_VOID && op->res == res) {
op->type = IO_VOID; op->type = IO_VOID;
@@ -214,8 +223,8 @@ close_internal(struct io_context *ioc,
res->gen = 0; res->gen = 0;
} }
struct io_resource *res_from_handle(struct io_context *ioc, static struct io_resource*
io_handle handle) res_from_handle(struct io_context *ioc, io_handle handle)
{ {
if (handle == IO_INVALID) if (handle == IO_INVALID)
return NULL; return NULL;
@@ -254,7 +263,7 @@ void io_close(struct io_context *ioc,
{ {
struct io_resource *res; struct io_resource *res;
res = res_from_handle(handle); res = res_from_handle(ioc, handle);
if (res == NULL) if (res == NULL)
return; return;
@@ -271,7 +280,7 @@ void io_free(struct io_context *ioc)
io_free_windows(ioc); io_free_windows(ioc);
#endif #endif
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_LINUX
io_free_linux(ioc); io_free_linux(ioc);
#endif #endif
} }
@@ -342,8 +351,10 @@ static bool io_recv_windows(struct io_context *ioc,
struct io_operation *op, struct io_operation *op,
void *dst, uint32_t max) void *dst, uint32_t max)
{ {
(void) ioc;
memset(&op->ov, 0, sizeof(struct io_os_overlap)); memset(&op->ov, 0, sizeof(struct io_os_overlap));
int ok = ReadFile(res->os_handle, dst, max, NULL, &op->ov); int ok = ReadFile(res->os_handle, dst, max, NULL, (OVERLAPPED*) &op->ov);
if (!ok && GetLastError() != ERROR_IO_PENDING) if (!ok && GetLastError() != ERROR_IO_PENDING)
return false; return false;
return true; return true;
@@ -356,8 +367,10 @@ static bool io_send_windows(struct io_context *ioc,
struct io_operation *op, struct io_operation *op,
void *src, uint32_t num) void *src, uint32_t num)
{ {
(void) ioc;
memset(&op->ov, 0, sizeof(struct io_os_overlap)); memset(&op->ov, 0, sizeof(struct io_os_overlap));
int ok = ReadFile(res->os_handle, src, num, NULL, &op->ov); int ok = ReadFile(res->os_handle, src, num, NULL, (OVERLAPPED*) &op->ov);
if (!ok && GetLastError() != ERROR_IO_PENDING) if (!ok && GetLastError() != ERROR_IO_PENDING)
return false; return false;
return true; return true;
@@ -370,44 +383,48 @@ static bool io_accept_windows(struct io_context *ioc,
struct io_operation *op, struct io_operation *op,
io_os_handle os_handle) io_os_handle os_handle)
{ {
(void) ioc;
(void) res;
memset(&op->ov, 0, sizeof(struct io_os_overlap)); memset(&op->ov, 0, sizeof(struct io_os_overlap));
SOCKET new_os_handle = socket(AF_INET, SOCK_STREAM, 0); SOCKET new_os_handle = socket(AF_INET, SOCK_STREAM, 0);
if (new_os_handle == INVALID_HANDLE_VALUE) if (new_os_handle == INVALID_SOCKET)
return false; return false;
LPFN_ACCEPTEX lpfnAcceptEx = NULL; LPFN_ACCEPTEX lpfnAcceptEx = NULL;
GUID GuidAcceptEx = WSAID_ACCEPTEX; GUID GuidAcceptEx = WSAID_ACCEPTEX;
unsigned long num; unsigned long num;
int ret = WSAIoctl(res->os_handle, int ret = WSAIoctl((SOCKET) os_handle,
SIO_GET_EXTENSION_FUNCTION_POINTER, SIO_GET_EXTENSION_FUNCTION_POINTER,
&GuidAcceptEx, sizeof(GuidAcceptEx), &GuidAcceptEx, sizeof(GuidAcceptEx),
&lpfnAcceptEx, sizeof(lpfnAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx),
&num, NULL, NULL); &num, NULL, NULL);
if (ret == SOCKET_ERROR) { if (ret == SOCKET_ERROR) {
DEBUG_LOG("WSAIoctl failure\n");
closesocket(new_os_handle); closesocket(new_os_handle);
return false; return false;
} }
_Static_assert(IO_SOCKADDR_IN_SIZE == sizeof(struct sockaddr_in)); _Static_assert(IO_SOCKADDR_IN_SIZE == sizeof(struct sockaddr_in));
int ok = lpfnAcceptEx(handle2, os_handle, op->accept_buffer, int ok = lpfnAcceptEx((SOCKET) os_handle, new_os_handle, op->accept_buffer,
sizeof(op->accept_buffer) - ((sizeof(struct sockaddr_in) + 16) * 2), sizeof(op->accept_buffer) - ((sizeof(struct sockaddr_in) + 16) * 2),
sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
&num, &op->ov); &num, (OVERLAPPED*) &op->ov);
if (!ok) { if (!ok && GetLastError() != ERROR_IO_PENDING) {
DEBUG_LOG("AcceptEx failure\n");
closesocket(new_os_handle); closesocket(new_os_handle);
return false; return false;
} }
op->accepted = new_os_handle; op->accepted = (io_os_handle) new_os_handle;
return true; return true;
} }
#endif #endif
bool io_recv(struct io_context *ioc, bool io_recv(struct io_context *ioc,
void *user, io_handle handle, void *user, io_handle handle,
void *dst, uint32_t max) void *dst, uint32_t max)
@@ -530,12 +547,12 @@ io_open_file_windows(struct io_context *ioc,
if (flags & IO_ACCESS_WR) access |= GENERIC_WRITE; if (flags & IO_ACCESS_WR) access |= GENERIC_WRITE;
io_os_handle os_handle = CreateFileA(file, access, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); io_os_handle os_handle = CreateFileA(file, access, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (os_handle == IO_INVALID_HANDLE) if (os_handle == INVALID_HANDLE_VALUE)
return IO_INVALID_HANDLE; return INVALID_HANDLE_VALUE;
if (CreateIoCompletionPort(os_handle, ioc->os_handle, NULL, 0) == NULL) { if (CreateIoCompletionPort(os_handle, ioc->os_handle, 0, 0) == NULL) {
CloseHandle(os_handle); CloseHandle(os_handle);
return IO_INVALID_HANDLE; return INVALID_HANDLE_VALUE;
} }
return os_handle; return os_handle;
@@ -603,12 +620,12 @@ io_create_file_windows(struct io_context *ioc,
if (os_handle == INVALID_HANDLE_VALUE) if (os_handle == INVALID_HANDLE_VALUE)
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
if (CreateIoCompletionPort(handle, ioc->os_handle, NULL, 0) == NULL) { if (CreateIoCompletionPort(os_handle, ioc->os_handle, 0, 0) == NULL) {
CloseHandle(os_handle); CloseHandle(os_handle);
return INVALID_HANDLE_VALUE; return INVALID_HANDLE_VALUE;
} }
return handle; return os_handle;
} }
#endif #endif
@@ -673,66 +690,77 @@ io_handle io_start_server(struct io_context *ioc,
return IO_INVALID; return IO_INVALID;
} }
io_os_handle os_handle; #if IO_PLATFORM_WINDOWS
SOCKET fd;
#endif
#if IO_PLATFORM_LINUX
int fd;
#endif
struct io_resource *res; struct io_resource *res;
res = find_unused_res(ioc); res = find_unused_res(ioc);
if (res == NULL) if (res == NULL)
return IO_INVALID; return IO_INVALID;
os_handle = socket(AF_INET, SOCK_STREAM, 0); fd = socket(AF_INET, SOCK_STREAM, 0);
#if IO_PLATFORM_LINUX #if IO_PLATFORM_LINUX
if (os_handle < 0) if (fd < 0)
return IO_INVALID; return IO_INVALID;
#endif #endif
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
if (os_handle == INVALID_HANDLE_VALUE) if (fd == INVALID_SOCKET)
return IO_INVALID; return IO_INVALID;
#endif #endif
int one = 1; int one = 1;
setsockopt(os_handle, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one));
struct sockaddr_in buf; struct sockaddr_in buf;
buf.sin_family = AF_INET; buf.sin_family = AF_INET;
buf.sin_port = htons(port); buf.sin_port = htons(port);
buf.sin_addr = addr2; buf.sin_addr = addr2;
if (bind(os_handle, (struct sockaddr*) &buf, sizeof(buf))) { if (bind(fd, (struct sockaddr*) &buf, sizeof(buf))) {
close(os_handle); #if IO_PLATFORM_WINDOWS
closesocket(fd);
#else
close(fd);
#endif
return IO_INVALID; return IO_INVALID;
} }
int backlog = 32; int backlog = 32;
if (listen(os_handle, backlog)) { if (listen(fd, backlog)) {
close(os_handle); #if IO_PLATFORM_WINDOWS
closesocket(fd);
#else
close(fd);
#endif
return IO_INVALID; return IO_INVALID;
} }
#if IO_PLATFORM_WINDOWS
if (CreateIoCompletionPort((HANDLE) fd, ioc->os_handle, 0, 0) == NULL) {
closesocket(fd);
return IO_INVALID;
}
#endif
res->type = IO_RES_SOCKET; res->type = IO_RES_SOCKET;
res->pending = 0; res->pending = 0;
res->os_handle = os_handle; res->os_handle = (io_os_handle) fd;
return handle_from_res(ioc, res); return handle_from_res(ioc, res);
} }
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
static unsigned long
convert_timeout(int timeout)
{
if (timeout < 0)
return ~0U;
else
return timeout;
}
static struct io_operation* static struct io_operation*
op_from_ov(struct io_os_overlap *ov) op_from_ov(struct io_os_overlap *ov)
{ {
return (struct io_operation*) ((char*) ov - offsetof(struct io_operation, ov)); return (struct io_operation*) ((char*) ov - offsetof(struct io_operation, ov));
} }
#endif #endif
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
@@ -740,10 +768,18 @@ static void
io_wait_windows(struct io_context *ioc, io_wait_windows(struct io_context *ioc,
struct io_event *ev) struct io_event *ev)
{ {
void *unused; int timeout = -1;
unsigned long timeout2;
if (timeout < 0)
timeout2 = INFINITE;
else
timeout2 = timeout;
unsigned long long unused;
struct io_os_overlap *ov; struct io_os_overlap *ov;
unsigned long num; unsigned long num;
int ok = GetQueuedCompletionStatus(ioc->os_handle, &num, &unused, &ov, convert_timeout(-1)); int ok = GetQueuedCompletionStatus(ioc->os_handle, &num, &unused, (OVERLAPPED**) &ov, timeout2);
if (!ok) { if (!ok) {
@@ -773,7 +809,7 @@ io_wait_windows(struct io_context *ioc,
ev->user = op->user; ev->user = op->user;
if (op->type == IO_ACCEPT) if (op->type == IO_ACCEPT)
closesocket(op->accepted); closesocket((SOCKET) op->accepted);
op->type = IO_VOID; // Mark unused op->type = IO_VOID; // Mark unused
@@ -805,7 +841,7 @@ io_wait_windows(struct io_context *ioc,
res2 = find_unused_res(ioc); res2 = find_unused_res(ioc);
if (res2 == NULL) { if (res2 == NULL) {
closesocket(op->accepted); closesocket((SOCKET) op->accepted);
ev->evtype = IO_ABORT; ev->evtype = IO_ABORT;
ev->optype = IO_ACCEPT; ev->optype = IO_ACCEPT;
+5 -2
View File
@@ -1,3 +1,5 @@
#include <stdint.h>
#include <stdbool.h>
#define IO_VERSION_MAJOR 0 #define IO_VERSION_MAJOR 0
#define IO_VERSION_MINOR 0 #define IO_VERSION_MINOR 0
@@ -38,7 +40,7 @@ struct io_os_overlap {
void *pointer; void *pointer;
}; };
void *event; void *event;
}: };
enum io_optype { enum io_optype {
IO_VOID, IO_VOID,
@@ -56,7 +58,7 @@ struct io_operation {
void *user; void *user;
#if IO_PLATFORM_WINDOWS #if IO_PLATFORM_WINDOWS
struct io_os_handle accepted; io_os_handle accepted;
struct io_os_overlap ov; struct io_os_overlap ov;
char accept_buffer[2 * (IO_SOCKADDR_IN_SIZE + 16)]; char accept_buffer[2 * (IO_SOCKADDR_IN_SIZE + 16)];
#endif #endif
@@ -72,6 +74,7 @@ struct io_resource {
enum io_restype type; enum io_restype type;
io_os_handle os_handle; io_os_handle os_handle;
uint16_t pending; uint16_t pending;
uint16_t gen;
}; };
struct io_context { struct io_context {