From d62bebee78c436f1236176dd61e581948de8390c Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 27 Jan 2026 21:19:42 +0100 Subject: [PATCH] add run_server and threading so both client and server are in same program --- src/basic.cpp | 15 ++-- src/main.cpp | 187 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 147 insertions(+), 55 deletions(-) diff --git a/src/basic.cpp b/src/basic.cpp index 63713d4..b499d68 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -1,9 +1,8 @@ #define lengthof(x) (sizeof((x)) / sizeof((x)[0])) -#define panicf(...) (fprintf(stderr, "%s:%d: ", __FILE__, __LINE__), fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n"), exit(1)) -#define debugf(...) (printf("%s:%d: ", __FILE__, __LINE__), printf(__VA_ARGS__), printf("\n")) +#define panicf(...) (fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, strf(__VA_ARGS__)), exit(1)) +#define debugf(...) printf("%s:%d: %s\n", __FILE__, __LINE__, strf(__VA_ARGS__)) #define assert(x) ((!(x)) && (panicf("%s:%d: assertion failed " #x, __FILE__, __LINE__), 0)) - template struct DEFER_ExitScope { T lambda; @@ -46,22 +45,22 @@ struct Slice { }; #define PLEN(x) {(x), lengthof(x)} +#define ENUM_VALUE(x) {x, #x} -struct EnumValue { +struct Enum_Value { int value; const char *name; }; -#define ENUM_VALUE(x) {x, #x} -const char *serialize(Slice table, int value) { +const char *serialize(Slice table, int value) { for (int i = 0; i < table.len; i += 1) { - EnumValue *it = table.data + i; + Enum_Value *it = table.data + i; if (it->value == value) return it->name; } return ""; } -char *serialize_flags(Slice table, int n) { // @leak +char *serialize_flags(Slice table, int n) { // @leak char *result = strf("%d", n); for (int i = 0; i < table.len; i += 1) { auto *it = table.data + i; diff --git a/src/main.cpp b/src/main.cpp index 446c8fb..d8b90a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,39 @@ #pragma comment(lib, "ws2_32") #include "basic.cpp" +Enum_Value _ai_flags_table[] = { + ENUM_VALUE(AI_PASSIVE), + ENUM_VALUE(AI_CANONNAME), + ENUM_VALUE(AI_NUMERICHOST), +}; +Slice ai_flags_table = PLEN(_ai_flags_table); + +Enum_Value _ai_family_table[] = { + {0, "AF_UNSPEC"}, + {2, "AF_INET"}, + {17, "AF_NETBIOS"}, + {23, "AF_INET6"}, + {26, "AF_IRDA"}, + {32, "AF_BTH"}, +}; +Slice ai_family_table = PLEN(_ai_family_table); + +Enum_Value _ai_socktype_table[] = { + ENUM_VALUE(SOCK_STREAM), + ENUM_VALUE(SOCK_DGRAM), + ENUM_VALUE(SOCK_RAW), + ENUM_VALUE(SOCK_RDM), + ENUM_VALUE(SOCK_SEQPACKET), +}; +Slice ai_socktype_table = PLEN(_ai_socktype_table); + +Enum_Value _ai_protocol_table[] = { + ENUM_VALUE(IPPROTO_TCP), + ENUM_VALUE(IPPROTO_UDP), + ENUM_VALUE(IPPROTO_PGM), +}; +Slice ai_protocol_table = PLEN(_ai_protocol_table); + char *serialize_error_code(DWORD errorCode) { char* message = NULL; @@ -37,39 +70,6 @@ char *serialize_error_code(DWORD errorCode) { return message; // @leak - LocalFree } -EnumValue _ai_flags_table[] = { - ENUM_VALUE(AI_PASSIVE), - ENUM_VALUE(AI_CANONNAME), - ENUM_VALUE(AI_NUMERICHOST), -}; -Slice ai_flags_table = PLEN(_ai_flags_table); - -EnumValue _ai_family_table[] = { - {0, "AF_UNSPEC"}, - {2, "AF_INET"}, - {17, "AF_NETBIOS"}, - {23, "AF_INET6"}, - {26, "AF_IRDA"}, - {32, "AF_BTH"}, -}; -Slice ai_family_table = PLEN(_ai_family_table); - -EnumValue _ai_socktype_table[] = { - ENUM_VALUE(SOCK_STREAM), - ENUM_VALUE(SOCK_DGRAM), - ENUM_VALUE(SOCK_RAW), - ENUM_VALUE(SOCK_RDM), - ENUM_VALUE(SOCK_SEQPACKET), -}; -Slice ai_socktype_table = PLEN(_ai_socktype_table); - -EnumValue _ai_protocol_table[] = { - ENUM_VALUE(IPPROTO_TCP), - ENUM_VALUE(IPPROTO_UDP), - ENUM_VALUE(IPPROTO_PGM), -}; -Slice ai_protocol_table = PLEN(_ai_protocol_table); - void serialize_addrinfo(struct addrinfo* in) { for (struct addrinfo* p = in; p != NULL; p = p->ai_next) { printf("addrinfo %p {\n", p); @@ -103,18 +103,6 @@ void serialize_addrinfo(struct addrinfo* in) { #define PORT "8000" void run_server() { - WSADATA wsaData; - - int err_wsa_startup = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (err_wsa_startup != 0) { - panicf("WSAStartup failed, error code: %d", err_wsa_startup); - } - defer { WSACleanup(); }; - - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { - panicf("Version 2.2 of Winsock not available"); - } - struct addrinfo *servinfo = {}; struct addrinfo hints = {}; hints.ai_family = AF_UNSPEC; @@ -126,7 +114,7 @@ void run_server() { panicf("getaddrinfo failed, error code: %s\n", gai_strerrorA(err)); } defer { freeaddrinfo(servinfo); }; - serialize_addrinfo(servinfo); + // serialize_addrinfo(servinfo); SOCKET socket_fd = -1; for (addrinfo *it = servinfo; it; it = it->ai_next) { @@ -186,8 +174,113 @@ void run_server() { } } +void *get_in_addr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + +void run_client() { + struct addrinfo *servinfo = {}; + struct addrinfo hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; // tcp + // hints.ai_flags = AI_PASSIVE; + // hints.ai_protocol = IPROTO_TCP; // tcp + INT err = getaddrinfo(NULL, PORT, &hints, &servinfo); + if (err != 0) { + panicf("client: getaddrinfo failed, error code: %s\n", gai_strerrorA(err)); + } + defer { freeaddrinfo(servinfo); }; + // serialize_addrinfo(servinfo); + + SOCKET socket_fd = -1; + for (addrinfo *it = servinfo; it; it = it->ai_next) { + socket_fd = socket(it->ai_family, it->ai_socktype, it->ai_protocol); + if (socket_fd == -1) { + debugf("skipping socket call %s", serialize_error_code(WSAGetLastError())); + continue; + } + + char s[INET6_ADDRSTRLEN]; + inet_ntop(it->ai_family, get_in_addr(it->ai_addr), s, sizeof(s)); + debugf("client: attempting connection to: %s", s); + + if (connect(socket_fd, it->ai_addr, (int)it->ai_addrlen) != 0) { + debugf("client: failed to connect %s", serialize_error_code(WSAGetLastError())); + closesocket(socket_fd); + socket_fd = -1; + continue; + } + + break; + } + + if (socket_fd == -1) { + panicf("client: failed to connect"); + } else { + debugf("client: connected!"); + } + + char buf[1024]; + int numbytes = recv(socket_fd, buf, lengthof(buf) - 1, 0); + if (numbytes == -1) { + panicf("client: recv failed %s", serialize_error_code(WSAGetLastError())); + } + + buf[numbytes] = '\0'; + debugf("client: received '%s'",buf); + closesocket(socket_fd); + +} + +struct Thread_Data { + int idx; +}; + +DWORD thread_entry(LPVOID param) { + Thread_Data *thread_data = (Thread_Data *)param; + printf("thread %d, reporting in!\n", thread_data->idx); + if (thread_data->idx == 0) { + run_server(); + } else { + run_client(); + } + printf("thread %d, exiting...\n", thread_data->idx); + return 0; +} + int main() { - run_server(); + WSADATA wsaData; + + int err_wsa_startup = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err_wsa_startup != 0) { + panicf("WSAStartup failed, error code: %d", err_wsa_startup); + } + defer { WSACleanup(); }; + + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + panicf("Version 2.2 of Winsock not available"); + } + + constexpr int thread_count = 8; + HANDLE thread_handles[32]; + Thread_Data thread_data[32]; + DWORD thread_ids[32]; + static_assert(thread_count < lengthof(thread_ids)); + for (int i = 0; i < thread_count; i += 1) { + thread_data[i].idx = i; + LPSECURITY_ATTRIBUTES attribs = NULL; + SIZE_T stack_size = 0; + DWORD creation_flags = 0; + thread_handles[i] = CreateThread(attribs, stack_size, thread_entry, &thread_data[i], creation_flags, &thread_ids[i]); + } + WaitForMultipleObjects(thread_count, thread_handles, TRUE, INFINITE); + + // run_server(); debugf("exiting..."); return 0; }