// Subject Zero - Freestanding Canary
// Markus Maiwald | Voxis Forge

// Provided by libnexus.a (Membrane)
extern int socket(int domain, int type, int protocol);
extern int connect(int fd, const void *addr, int len);
extern int write(int fd, const void *buf, int count);
extern int printf(const char *format, ...); // Maybe mapped to write(1, ...)

// LwIP / Membrane Helpers
extern unsigned short htons(unsigned short hostshort);
extern int inet_pton(int af, const char *src, void *dst);

struct sockaddr_in {
    unsigned short sin_family;
    unsigned short sin_port;
    unsigned int sin_addr;
    char sin_zero[8];
};

#define AF_INET 2
#define SOCK_STREAM 1

extern void membrane_init(void);
extern void pump_membrane_stack(void);

int subject_zero_entry() {
    membrane_init();
    write(1, "[Subject0] Boot sequence initiated.\n", 36);
    write(1, "[Subject0] Requesting Membrane Socket...\n", 41);

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        write(1, "[Subject0] FAILURE: socket() returned error\n", 44);
        return 1;
    }
    
    write(1, "[Subject0] Got Socket. Connecting to Host (10.0.2.2:8080)...\n", 62);

    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = 0x901F; // htons(8080) -> 0x1F90, wait, swapped for Big Endian is 0x901F
    serv_addr.sin_addr = 0x0202000A; // 10.0.2.2 -> 0x0A, 0x00, 0x02, 0x02. In memory: A 0 2 2. As uint32 BE: 0x0A000202.
                                     // Wait, 0x0202000A as Little Endian uint32 is bytes 0A 00 02 02.
                                     // If the machine is Little Endian (RISC-V), then 0x0202000A in a register
                                     // will be stored as 0A 00 02 02 in memory.
                                     // LwIP expects sin_addr as 4 bytes in network order.
                                     // So 0x0202000A is CORRECT for 10.0.2.2 if sin_addr is uint32.
                                     // Wait, 10.0.2.2 -> A.0.2.2 -> 0x0A000202.
                                     // Let's just use 0x0202000A and see.
                                     // Actually, let's use a cleaner way.

    if (connect(fd, &serv_addr, sizeof(serv_addr)) < 0) {
        write(1, "[Subject0] Connection Failed.\n", 30);
        return 1;
    }

    write(1, "[Subject0] CONNECTED! Sending Greeting...\n", 42);
    char *hello = "Hello from the Membrane!\n";
    write(fd, hello, 26);
    write(1, hello, 26);
    
    write(1, "[Subject0] Entering Loop.\n", 26);
    while(1) { 
        pump_membrane_stack();
        
        // Yield to Kernel (Phase 7 Coop)
        typedef void (*yield_func)(void);
        yield_func rumpk_yield = *(yield_func*)0x801FFFF0;
        if (rumpk_yield) rumpk_yield();

        for(volatile int i=0; i<100000; i++); 
    } 
    
    return 0;
}
