std1.0.0-beta-7 SafeC docs

Source net/net_core.sc

View in the repository

// SafeC Standard Library — Network Core Implementation
#pragma once
#include <std/net/net_core.h>

// ── Byte-order conversions ────────────────────────────────────────────────────

namespace std {

inline unsigned short net_htons(unsigned short v) {
    return (unsigned short)(((v & (unsigned short)0xFF) << 8) |
                            ((v >> 8) & (unsigned short)0xFF));
}

inline unsigned short net_ntohs(unsigned short v) {
    return net_htons(v);
}

inline unsigned int net_htonl(unsigned int v) {
    return ((v & (unsigned int)0xFF)         << 24)
         | (((v >> 8)  & (unsigned int)0xFF) << 16)
         | (((v >> 16) & (unsigned int)0xFF) <<  8)
         |  ((v >> 24) & (unsigned int)0xFF);
}

inline unsigned int net_ntohl(unsigned int v) {
    return net_htonl(v);
}

// ── IP / MAC utilities ────────────────────────────────────────────────────────

// Write a decimal number (0-255) into buf; return chars written.
static int net_write_dec_(char* buf, unsigned int val) {
    if (val >= 100) {
        unsafe {
            buf[0] = (char)('0' + val / (unsigned int)100);
            buf[1] = (char)('0' + (val / (unsigned int)10) % (unsigned int)10);
            buf[2] = (char)('0' + val % (unsigned int)10);
        }
        return 3;
    }
    if (val >= 10) {
        unsafe {
            buf[0] = (char)('0' + val / (unsigned int)10);
            buf[1] = (char)('0' + val % (unsigned int)10);
        }
        return 2;
    }
    unsafe { buf[0] = (char)('0' + val); }
    return 1;
}

// Write a hex nibble.
static char net_hex_nibble_(unsigned int v) {
    v = v & (unsigned int)0xF;
    if (v < (unsigned int)10) {
        return (char)('0' + v);
    }
    return (char)('a' + v - (unsigned int)10);
}

inline void net_ip4_str(unsigned int ip_be, &char buf_ref) { char* buf = buf_ref;
    int pos = 0;
    int i = 3;
    while (i >= 0) {
        unsigned int octet;
        unsafe { octet = (ip_be >> ((unsigned int)i * (unsigned int)8)) & (unsigned int)0xFF; }
        int n;
        unsafe { n = net_write_dec_(buf + pos, octet); }
        pos = pos + n;
        if (i > 0) {
            unsafe { buf[pos] = '.'; }
            pos = pos + 1;
        }
        i = i - 1;
    }
    unsafe { buf[pos] = (char)0; }
}

inline void net_mac_str(const unsigned char mac[NET_MAC_LEN], &char buf) {
    int i = 0;
    while (i < NET_MAC_LEN) {
        unsigned int b;
        unsafe { b = (unsigned int)mac[i]; }
        unsafe {
            buf[i*3+0] = net_hex_nibble_(b >> 4);
            buf[i*3+1] = net_hex_nibble_(b);
        }
        if (i < NET_MAC_LEN - 1) {
            unsafe { buf[i*3+2] = ':'; }
        }
        i = i + 1;
    }
    unsafe { buf[NET_MAC_LEN*3 - 1] = (char)0; }
}

unsigned int net_ip4(unsigned char a, unsigned char b,
                     unsigned char c, unsigned char d) {
    return ((unsigned int)a << 24)
         | ((unsigned int)b << 16)
         | ((unsigned int)c <<  8)
         |  (unsigned int)d;
}

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

inline ?&unsigned char PacketBuf::at(unsigned long offset) {
    if (offset >= (unsigned long)NET_MTU) return null;
    unsafe { return (?&unsigned char)&self.data[offset]; }
}

inline void PacketBuf::reset() {
    unsigned long i = (unsigned long)0;
    while (i < (unsigned long)NET_MTU) {
        unsafe { self.data[i] = (unsigned char)0; }
        i = i + (unsigned long)1;
    }
    self.len = (unsigned long)0;
}

// ── NetIf ─────────────────────────────────────────────────────────────────────

inline int NetIf::tx(&PacketBuf pkt) {
    unsigned long n = pkt.len < (unsigned long)NET_MTU ? pkt.len : (unsigned long)NET_MTU;
    match (self.tx_fn) {
        case some(func): {
            match (self.iface_ctx) {
                case some(ctx): return func(ctx, pkt.data[0..n]);
                case null: { }
            }
        }
        case null: { }
    }
    return -1;
}

} // namespace std