This chapter forms an integral part of module "The Networking Module" - should "The Input/Output Module" be implemneted, this chapter along with any chapter constituting part of "The Input/Output Module" must be implemented in their entirity.
This module depend on module "The Input/Output Module", should this module be implemented, module "The Input/Output Module" must also be implemented.
If the platform on which a cxing program runs uses separate namespace
for either the identifier or the value (or both) of error numbers for socket-specific
errors than the errno codes of other system-diagnosed errors, the implementation
shall map any socket-specific error codes to the namespace for errno codes.
Note: For example, on Windows, the Winsock 2 API have the WSA prefix to
error values such as WSAEWOULDBLOCK, WSAEINTR, etc. The implementation must
map those to EWOULDBLOCK, EINTR, etc. when they cast them into null for
failure returns.
[Socket(GenericFile): subr socket(dom, typ, proto)] := {
method send(str, flags),
method recv(len, flags), // returns a string object.
method sendto(str, flags, peer),
method recvfrom(len, flags, peer), // returns a string object
method shutdown(how),
method bind(name),
method connect(peer),
method listen(backlog),
method accept(), // returns a socket,
method __get__(k),
method __set__(k, v),
method __copy__(),
method __final__(),
}
The parameters peer and name for sendto, recvfrom, and bind, as well
as the return value from accept are 'socket address' objects described below.
The methods for a socket object return null that uncasts to errno codes
on failures. The correspondence between the socket methods and POSIX socket API
are as follow:
| Method Name | POSIX API | Return Value on Success | Special Return Values |
|---|---|---|---|
| `send` | `send` | The number of bytes sent, | - |
| `recv` | `recv` | The received data as a string object, | 0 on EOF. |
| `sendto` | `sendto` | The number of bytes sent, | - |
| `recvfrom` | `recvfrom` | The received data as a string object, | 0 on EOF. |
| `shutdown` | `shutdown` | 0 | - |
| `bind` | `bind` | 0 | - |
| `connect` | `connect` | 0 | - |
| `listen` | `listen` | 0 | - |
| `listen` | `listen` | 0 | - |
| `accept` | `accept` | A socket for interacting with the accepted connection. | - |
The implementation shall define at least the following integer constants corresponding respectively to those in the POSIX socket API:
AF_INET, AF_INET6, AF_UNIX (if platform supports), AF_UNSPEC,SOCK_STREAM, SOCK_DGRAM,MSG_NOSIGNAL, MSG_PEEK, MSG_WAITALL,SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_CLOEXEC.The __get__ and __set__ methods of a socket object can be used to configure
and inspect socket options and properties.
The sockname and peername properties are the socket addresses of the socket
object and its peer respectively, and are retrieved using the __get__ method.
The options on the other hand consist of a 'level' and a 'name', separated by
a solidus /. Implementations shall support the following options, and may
support additional options, Boolean options are of type long and may assume
the value of either true or false.
| Option Name, | Configuration Value Type, |
|---|---|
| `SOL_SOCKET/SO_ACCEPTCONN` (read-only) | Boolean |
| `SOL_SOCKET/SO_BROADCAST` | Boolean |
| `SOL_SOCKET/SO_DEBUG` | Boolean |
| `SOL_SOCKET/SO_DOMAIN` (read-only) | Socket Domain Enumeration, |
| `SOL_SOCKET/SO_DONTROUTE` | Boolean |
| `SOL_SOCKET/SO_ERROR` (read-only, cleared on read) | `long` |
| `SOL_SOCKET/SO_KEEPALIVE` | Boolean |
| `SOL_SOCKET/SO_LINGER` | Socket Linger Object |
| `SOL_SOCKET/SO_OOBINLINE` (read-only) | Boolean (always `true`, see rationale below). |
| `SOL_SOCKET/SO_PROTOCOL` | Boolean |
| `SOL_SOCKET/SO_RCVBUF` | `long` |
| `SOL_SOCKET/SO_RCVLOWAT` | `long` |
| `SOL_SOCKET/SO_RCVTIMEO` | `double` interpreted in seconds. |
| `SOL_SOCKET/SO_REUSEADDR` | Boolean |
| `SOL_SOCKET/SO_SNDBUF` | `long` |
| `SOL_SOCKET/SO_SNDLOWAT` | `long` |
| `SOL_SOCKET/SO_SNDTIMEO` | `double` interpreted in seconds. |
| `SOL_SOCKET/SO_TYPE` (read-only) | Socket Type Enumeration |
| `IPPROTO_IPV6/IPV6_JOIN_GROUP` | `ipv6_mreq` |
| `IPPROTO_IPV6/IPV6_LEAVE_GROUP` | `ipv6_mreq` |
| `IPPROTO_IPV6/IPV6_MULTICAST_HOPS` | `long` |
| `IPPROTO_IPV6/IPV6_MULTICAST_IF` | `ulong` |
| `IPPROTO_IPV6/IPV6_MULTICAST_LOOP` | Boolean |
| `IPPROTO_IPV6/IPV6_UNICAST_HOPS` | `long` |
| `IPPROTO_IPV6/IPV6_V6ONLY` | Boolean |
| `IPPROTO_TCP/TCP_NODELAY` | Boolean |
The newer RFC-9293 on the TCP protocol has advised against the use of
the 'urgent' flag in new applications. Although support for compatibility with
older applications that does use out-of-band from implementations are allowed,
CXING is not one of those older language to begin with,
so we're omitting its support, and requiring that the socket subroutine to
set the SO_OOBINLINE option for all of its newly created sockets.
The setsync method of a socket (which is inherited from generic files)
shall be implemented using (i.e. on top of) the TCP_NODELAY option.
Certain POSIX socket APIs expect pointers to structures that require language
bindings. Implementations may represent these structures as actual structures
in memory, and expose their members through the __get__ and the __set__
methods, by reading from and writing to fields in the structures directly.
All subroutines that creates these so-called DirectStructFieldAccess types
shall initialize them to all-bit-zero before returning them.
[DirectStructFieldAccess] := {
method __get__(k),
method __set__(k, v),
method __initset__(k, v),
method __copy__(),
method __final__(),
}
[sockaddr(DirectStructFieldAccess): subr sockaddr()]
sa_family,AF_INET:
sin_family, sin_port, sin_addrAF_INET6:
sin6_family, sin6_port, sin6_addr.The fields *_family and *_port shall be of integer type in appropriate range
in network byte order (e.g. 16-bit port number in host byte order converted to
big-endian represented in a long); sin_addr shall be of integer type in
unsigned 32-bit range in network byte order; sin6_addr shall be a 16-byte
string object.
[sock_linger(DirectStructFieldAccess): subr sock_linger()]
l_onoff (Boolean), l_linger (integer).[ipv6_mreq(DirectStructFieldAccess): subr ipv6_mreq()]
ipv6mr_multiaddr (string object), ipv6mr_interface (integer).