#pragma once #include "types.h" // Unix domain sockets. // // These exist for Schcom. A compositor and its clients have to exchange // messages, and a pipe cannot do it: a pipe is one-directional, has no // notion of a connection, and gives no way for a server to be *found* by a // client that starts later. A socket with a name in the filesystem is // exactly the missing piece. // // AF_INET arrived later, and exactly as planned: underneath the same syscalls // rather than reshaping them. A socket carries its domain and every entry point // dispatches on it -- kernel/net/unix.c for AF_UNIX, kernel/net/inet.c (lwIP) // for AF_INET. #define AF_UNIX 1 #define AF_LOCAL 1 #define AF_INET 2 #define SOCK_STREAM 1 #define SOCK_DGRAM 2 // Flags ORed into socket()'s and accept4()'s `type`/`flags` argument. Linux's // values, because a musl program passes Linux's constants. #define SOCK_NONBLOCK 0x800 // O_NONBLOCK #define SOCK_CLOEXEC 0x80000 // O_CLOEXEC // setsockopt/getsockopt levels and names, Linux's numbering. // // Only what is listed here is accepted; anything else is answered with // ENOPROTOOPT rather than a success it did not earn. See the comment above // sys_setsockopt for why that is worth the risk of failing a caller that never // checked before. #define SOL_SOCKET 1 #define IPPROTO_ICMP 1 #define IPPROTO_TCP 6 #define SO_REUSEADDR 2 #define SO_TYPE 3 #define SO_ERROR 4 #define SO_BROADCAST 6 #define SO_SNDBUF 7 #define SO_RCVBUF 8 #define SO_KEEPALIVE 9 #define SO_ACCEPTCONN 30 #define TCP_NODELAY 1 #define UNIX_PATH_MAX 108 #define SHUT_RD 0 #define SHUT_WR 1 #define SHUT_RDWR 2 struct sockaddr_un { uint16 sun_family; char sun_path[UNIX_PATH_MAX]; }; // The generic form syscalls take. Same shape as Linux's, so a musl-linked // program's struct lines up byte for byte. struct sockaddr { uint16 sa_family; char sa_data[UNIX_PATH_MAX]; }; // The AF_INET address. Same layout as Linux's, so a musl-linked program's // struct lines up byte for byte. sin_port and sin_addr are network byte order // and stay that way: lwIP wants them so, and converting on the way in and out // again would be two swaps that cancel. struct sockaddr_in { uint16 sin_family; uint16 sin_port; uint32 sin_addr; char sin_zero[8]; }; #ifdef _KERNEL_SOCKET_INTERNALS #define NSOCK 32 // sockets in the system #define SOCKBUF 4096 // receive buffer per connected socket #define NBACKLOG 8 enum sockstate { SS_FREE = 0, SS_UNBOUND, SS_BOUND, SS_LISTENING, SS_CONNECTED, }; // Every field here is protected by the socket table's single lock in // kernel/net/unix.c -- there is deliberately no per-socket lock; see the // comment at the top of that file for why. struct socket { int ref; int type; int state; int domain; // AF_UNIX or AF_INET // For AF_INET: the lwIP-backed socket in kernel/net/inet.c. Opaque here so // that socket.h does not have to drag lwIP's headers into every file that // wants a struct socket. void *inet; char name[UNIX_PATH_MAX]; // the bound path, for a listener // A connected socket's peer. Writing to a socket appends to the *peer's* // buffer, which is what makes one buffer per socket enough for a // bidirectional connection. struct socket *peer; int peer_closed; char data[SOCKBUF]; uint nread, nwrite; // Connections waiting to be accepted, on a listener. struct socket *queue[NBACKLOG]; int nqueue; // Socket options that are genuinely honoured. Kept here rather than only in // lwIP's pcb because getsockopt has to answer for an AF_UNIX socket too, and // because a flag set before bind() has to survive until there is a pcb to // apply it to. int o_reuseaddr; int o_keepalive; int o_broadcast; int o_nodelay; }; #endif