aboutsummaryrefslogtreecommitdiffstats
path: root/usr/sock.h
blob: c27b0f49261eadfd1750c93db702469b020b9183 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#ifndef SOCK_H
#define SOCK_H
/* gbos socket API - the kernel owns SLIP/IP/ICMP/UDP/TCP; programs just do
   socket()/connect()/send()/recv()/close(). Header-only: one copy per program.
   The netreq layout must match include/gbos.inc (NR_* / NET_* / SOCK_*). */
#include "gbos.h"

#define SOCK_ICMP 1
#define SOCK_UDP  2
#define SOCK_TCP  3

struct netreq {
    unsigned char op;
    unsigned char sock;
    unsigned char *buf;
    unsigned char len;
    unsigned char ip[4];
    unsigned char port_hi, port_lo;
};
static struct netreq _nr;

/* -> socket id, or 0xFF if the table is full */
static unsigned char net_socket(unsigned char type) {
    _nr.op = 0;
    _nr.sock = type;
    return sys_net(&_nr);
}
/* set the remote address/port for send()/recv() */
static unsigned char net_connect(unsigned char s, const unsigned char *ip, unsigned int port) {
    unsigned char i;
    _nr.op = 1;
    _nr.sock = s;
    for (i = 0; i < 4; i++) _nr.ip[i] = ip[i];
    _nr.port_hi = (unsigned char)(port >> 8);
    _nr.port_lo = (unsigned char)port;
    return sys_net(&_nr);
}
/* send 'len' payload bytes to the connected peer -> 0 ok / 0xFF error */
static unsigned char net_send(unsigned char s, void *buf, unsigned char len) {
    _nr.op = 2;
    _nr.sock = s;
    _nr.buf = (unsigned char *)buf;
    _nr.len = len;
    return sys_net(&_nr);
}
/* receive up to 'max' payload bytes -> length, or 0xFF on timeout */
static unsigned char net_recv(unsigned char s, void *buf, unsigned char max) {
    _nr.op = 3;
    _nr.sock = s;
    _nr.buf = (unsigned char *)buf;
    _nr.len = max;
    return sys_net(&_nr);
}
/* non-blocking recv: one RX pump -> length, 0xFE if nothing buffered yet,
   0 on TCP EOF. Loop it with msleep() to own your timeout (see ping). */
static unsigned char net_recv_nb(unsigned char s, void *buf, unsigned char max) {
    _nr.op = 8;
    _nr.sock = s;
    _nr.buf = (unsigned char *)buf;
    _nr.len = max;
    return sys_net(&_nr);
}
/* passive open: take connections on a local port (TCP). The listener stays a
   listener - accept() hands back a separate socket for each client. */
static unsigned char net_listen(unsigned char s, unsigned int port) {
    _nr.op = 9;
    _nr.sock = s;
    _nr.port_hi = (unsigned char)(port >> 8);
    _nr.port_lo = (unsigned char)port;
    return sys_net(&_nr);
}
/* -> the new client's socket id, or 0xFE if nobody is waiting. Never blocks:
   one RX pump per call, so loop it with yield()/msleep(). Talk to the returned
   socket with the ordinary send/recv/close; closing it leaves the listener
   alone, so a server can hold several clients at once (see usr/ircd.c). */
static unsigned char net_accept(unsigned char s) {
    _nr.op = 10;
    _nr.sock = s;
    return sys_net(&_nr);
}
/* set the local (source) port - needed so UDP replies demux back to us */
static unsigned char net_bind(unsigned char s, unsigned int port) {
    _nr.op = 5;
    _nr.sock = s;
    _nr.port_hi = (unsigned char)(port >> 8);
    _nr.port_lo = (unsigned char)port;
    return sys_net(&_nr);
}
static void net_close(unsigned char s) {
    _nr.op = 4;
    _nr.sock = s;
    sys_net(&_nr);
}
/* pump the RX path once (answers inbound pings) without blocking */
static void net_poll(void) {
    _nr.op = 6;
    sys_net(&_nr);
}
/* set our IPv4 address (the DHCP client calls this once it has a lease) */
static void net_setip(const unsigned char *ip) {
    unsigned char i;
    _nr.op = 7;
    for (i = 0; i < 4; i++) _nr.ip[i] = ip[i];
    sys_net(&_nr);
}
#endif