diff options
| author | fschildt <florian.schildt@protonmail.com> | 2025-08-22 15:23:11 +0200 | 
|---|---|---|
| committer | fschildt <florian.schildt@protonmail.com> | 2025-10-15 11:33:23 +0200 | 
| commit | 04e4627e6c11254ee6f49edf5feb1b8d711da41a (patch) | |
| tree | e28f2e62d3e1b83f9686cdeb102e3f47379e6793 /src/graveyard/linux_net_stream.c | |
Diffstat (limited to 'src/graveyard/linux_net_stream.c')
| -rw-r--r-- | src/graveyard/linux_net_stream.c | 192 | 
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; +    } +} +  | 
