aboutsummaryrefslogtreecommitdiff
path: root/src/graveyard/linux_net_stream.c
diff options
context:
space:
mode:
authorfschildt <florian.schildt@protonmail.com>2025-08-22 15:23:11 +0200
committerfschildt <florian.schildt@protonmail.com>2025-08-22 15:23:11 +0200
commit2050c0e0576f05156f192aa4caf48834d2f28b14 (patch)
treeee58bd35b0df0a1bacfbc9700ed99ce80c99294e /src/graveyard/linux_net_stream.c
first commitHEADmaster
Diffstat (limited to 'src/graveyard/linux_net_stream.c')
-rw-r--r--src/graveyard/linux_net_stream.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/graveyard/linux_net_stream.c b/src/graveyard/linux_net_stream.c
new file mode 100644
index 0000000..f08cdc5
--- /dev/null
+++ b/src/graveyard/linux_net_stream.c
@@ -0,0 +1,192 @@
+#include <basic/basic.h>
+#include <os/os.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+typedef struct {
+ int fd;
+} OSNetStream;
+
+
+internal_var u32 s_max_stream_count;
+internal_var OSNetStream *s_streams;
+
+internal_var u32 s_free_id_count;
+internal_var u32 *s_free_ids;
+
+
+
+internal_fn void
+os_net_stream_free(u32 stream_id)
+{
+ s_free_ids[s_free_id_count] = stream_id;
+ s_free_id_count += 1;
+}
+
+internal_fn u32
+os_net_stream_alloc()
+{
+ if (s_free_id_count == 0) {
+ return OS_NET_STREAM_ID_INVALID;
+ }
+
+ u32 id = s_free_ids[s_free_id_count-1];
+ s_free_id_count -= 1;
+
+ return id;
+}
+
+
+
+b32
+os_net_stream_send(u32 stream_id, void *buffer, size_t size)
+{
+ OSNetStream *stream = &s_streams[stream_id];
+
+ size_t sent = send(stream->fd, buffer, size, 0);
+ if (sent == -1) {
+ printf("send failed\n");
+ return false;
+ } else if (sent < size) {
+ printf("send only sent %ld/%ld bytes\n", sent, size);
+ return false;
+ }
+ return true;
+}
+
+b32
+os_net_stream_recv(u32 stream_id, void *buffer, size_t size)
+{
+ OSNetStream *stream = &s_streams[stream_id];
+
+ ssize_t recvd = recv(stream->fd, buffer, size, 0);
+ if (unlikely(recvd == -1 || recvd != size)) {
+ return false;
+ }
+
+ return true;
+}
+
+int
+os_net_stream_get_fd(u32 stream_id)
+{
+ OSNetStream *stream = &s_streams[stream_id];
+ return stream->fd;
+}
+
+void
+os_net_stream_close(u32 stream_id)
+{
+ OSNetStream *stream = &s_streams[stream_id];
+ close(stream->fd);
+}
+
+u32
+os_net_stream_accept(u32 listener_id)
+{
+ int fd;
+ struct sockaddr_in addr;
+ socklen_t addr_size = sizeof(addr);
+
+ OSNetStream *listener = &s_streams[listener_id];
+ fd = accept(listener->fd, (struct sockaddr*)&addr, &addr_size);
+ if (fd == -1) {
+ printf("accept failed\n");
+ return 0;
+ }
+
+ u32 stream_id = os_net_stream_alloc();
+ OSNetStream *stream = &s_streams[stream_id];
+ stream->fd = fd;
+ return stream_id;
+}
+
+u32
+os_net_stream_listen(u16 port)
+{
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == -1) {
+ perror("socket()");
+ return 0;
+ }
+
+ int enable_reuse = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable_reuse, sizeof(int)) < 0) {
+ perror("setsockopt(SO_REUSEADDR)");
+ close(fd);
+ return 0;
+ }
+
+ struct sockaddr_in local_addr;
+ local_addr.sin_family = AF_INET;
+ local_addr.sin_port = htons(port);
+ local_addr.sin_addr.s_addr = INADDR_ANY;
+ if (bind(fd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
+ perror("bind()");
+ close(fd);
+ return 0;
+ }
+
+ int backlog = 128;
+ if (listen(fd, backlog) == -1) {
+ perror("listen()");
+ close(fd);
+ return 0;
+ }
+
+ u32 listener_id = os_net_stream_alloc();
+ OSNetStream *stream = &s_streams[listener_id];
+ stream->fd = fd;
+
+ return listener_id;
+}
+
+u32
+os_net_stream_connect(char *address, u16 port)
+{
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == -1) {
+ printf("cant open socket\n");
+ return 0;
+ }
+
+ // note: connect binds a local address automatically
+ struct sockaddr_in target_addr;
+ memset(&target_addr, 0, sizeof(target_addr));
+ target_addr.sin_family = AF_INET;
+ target_addr.sin_port = htons(1338);
+ target_addr.sin_addr.s_addr = inet_addr(address);
+ if (connect(fd, (struct sockaddr*)&target_addr, sizeof(target_addr)) == -1) {
+ printf("connect failed\n");
+ close(fd);
+ return 0;
+ }
+
+ u32 stream_id = os_net_stream_alloc();
+ OSNetStream *stream = &s_streams[stream_id];
+ stream->fd = fd;
+
+ return stream_id;
+}
+
+void
+os_net_streams_init(MemArena *arena, size_t max_stream_count)
+{
+ s_max_stream_count = max_stream_count;
+ s_streams = mem_arena_push(arena, max_stream_count * sizeof(OSNetStream));
+
+ s_free_id_count = max_stream_count;
+ s_free_ids = mem_arena_push(arena, max_stream_count * sizeof(u32));
+ for (size_t i = 0; i < max_stream_count; i++) {
+ s_free_ids[i] = i;
+ }
+}
+