std1.0.0-beta-7 SafeC docs

Source net/net_core.h

View in the repository

// SafeC Standard Library — Network Core
// Packet buffer and network interface abstraction. Freestanding-safe.
#pragma once
#include <std/erased.h>

#define NET_MTU        1514   // Ethernet max frame size (excl. preamble/FCS)
#define NET_MAC_LEN       6
#define NET_IP4_LEN       4

// ── Byte-order conversions (network = big-endian) ─────────────────────────────
namespace std {

unsigned short net_htons(unsigned short v);
unsigned short net_ntohs(unsigned short v);
unsigned int   net_htonl(unsigned int v);
unsigned int   net_ntohl(unsigned int v);

// ── IP / MAC utilities ────────────────────────────────────────────────────────
// Format an IPv4 address into buf as "a.b.c.d\0" (at least 16 bytes).
void net_ip4_str(unsigned int ip_be, &char buf);

// Format a MAC address into buf as "xx:xx:xx:xx:xx:xx\0" (at least 18 bytes).
void net_mac_str(const unsigned char mac[NET_MAC_LEN], &char buf);

// Build an IPv4 address from four octets: a<<24 | b<<16 | c<<8 | d.
// Every std::net API takes and returns IPv4 addresses (and ports, seq
// numbers, …) as plain host integers in this numeric form; the build/parse
// functions do the big-endian wire (de)serialization themselves, so callers
// never need net_htons/net_htonl for them.
unsigned int net_ip4(unsigned char a, unsigned char b,
                     unsigned char c, unsigned char d);

// ── PacketBuf ─────────────────────────────────────────────────────────────────

struct PacketBuf {
    unsigned char data[NET_MTU];
    unsigned long len;   // bytes in use

    // The byte at `offset`, or null past the end of the buffer.
    ?&unsigned char at(unsigned long offset);

    // Zero the buffer and reset len.
    void  reset();
};

// ── NetIf — abstract network interface ───────────────────────────────────────
// Over any driver type with a transmit method (NetDriver); the caller then
// fills in mac[] and the addresses.

trait NetDriver {
    // Sends one frame. 0 on success.
    int transmit([]const unsigned char frame);
}

struct NetIf {
    unsigned char mac[NET_MAC_LEN];    // hardware MAC address
    unsigned int  ip4;                 // assigned IPv4, numeric form (see net_ip4)
    unsigned int  gateway;             // default gateway IPv4 (numeric form, see net_ip4)
    unsigned int  netmask;             // subnet mask (numeric form, see net_ip4)

    // The driver's transmit and context, stored type-erased (one stack
    // may run interfaces from different drivers); NetIf::new<T> is the
    // only writer and always pairs T's thunk with a &T (see std/erased.h).
    ?fn int(&Erased, []const unsigned char) tx_fn;   // null for an interface with no driver
    ?&Erased      iface_ctx;           // the &T

    // An interface whose tx() calls drv.transmit(frame). drv must
    // outlive it.
    generic<T: NetDriver>
    static struct NetIf new(&T drv);

    // Transmit a packet.  Returns 0 on success.
    int  tx(&PacketBuf pkt);
};

generic<T: NetDriver>
int netif_tx_thunk_(&T drv, []const unsigned char frame) {
    return drv.transmit(frame);
}

generic<T: NetDriver>
struct NetIf NetIf::new(&T drv) {
    struct NetIf nif;
    unsigned long i = 0UL;
    while (i < (unsigned long)NET_MAC_LEN) { unsafe { nif.mac[i] = (unsigned char)0; } i = i + 1UL; }
    nif.ip4 = 0U;
    nif.gateway = 0U;
    nif.netmask = 0U;
    fn int(&T, []const unsigned char) tx = netif_tx_thunk_;
    unsafe {
        nif.tx_fn = (?fn int(&Erased, []const unsigned char))tx;
        nif.iface_ctx = (?&Erased)drv;
    }
    return nif;
}

} // namespace std