RyanHub - file viewer
filename: includes/rch.h
branch: main
back to repo
#ifndef RCH_H
#define RCH_H

/*
welcome to ryans cute helpers (rch)

Ryan Alport, October 2025

this file provides implementations for a number of functions, each in the category of...
 - windowing
 - rendering
 - clienting
 - servering
this is by no means best practices but it is cool for a demo and getting started
*/

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
typedef SOCKET socket_t;

#include <windows.h>
typedef HANDLE thread_t;

#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
typedef int socket_t;

#include <pthread.h>
typedef pthread_t thread_t;

#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// ----------------- cross-platform helpers -----------------
static void close_socket(socket_t sock) {
#ifdef _WIN32
    closesocket(sock);
#else
    close(sock);
#endif
}

static thread_t start_thread(void* (*func)(void*), void* arg) {
#ifdef _WIN32
    return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL);
#else
    pthread_t tid;
    pthread_create(&tid, NULL, func, arg);
    return tid;
#endif
}

// ----------------- client networking -----------------
static socket_t client_start(const char* ip, int port) {
#ifdef _WIN32
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1;
#endif
    socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) return -1;

    struct sockaddr_in server_addr = {0};
    server_addr.sin_family = AF_INET;
    server_addr.sin_port   = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(ip);

    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        close_socket(sock);
        return -1;
    }
    return sock;
}

static int client_send(socket_t sock, const void* buf, int len) {
    return send(sock, buf, len, 0);
}
static int client_recv(socket_t sock, void* buf, int len) {
    return recv(sock, buf, len, 0);
}

// ----------------- server networking -----------------
static socket_t server_start(int port) {
#ifdef _WIN32
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1;
#endif
    socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) return -1;

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        close_socket(sock);
        return -1;
    }
    if (listen(sock, 5) < 0) {
        close_socket(sock);
        return -1;
    }
    return sock;
}

static socket_t server_accept(socket_t server_sock) {
    struct sockaddr_in client_addr;
    socklen_t len = sizeof(client_addr);
    return accept(server_sock, (struct sockaddr*)&client_addr, &len);
}

static int server_send(socket_t client_sock, const void* buf, int len) {
    return send(client_sock, buf, len, 0);
}
static int server_recv(socket_t client_sock, void* buf, int len) {
    return recv(client_sock, buf, len, 0);
}

#endif