Update errno listings. Update ai flags in std::net. Fix incorrect socket error results on Win32. Change behaviour Socket set_option. TcpSocket/TcpServerSocket/UdpSocket. Rename "TimeDuration" to "Duration". Allow @if on enum values.

This commit is contained in:
Christoffer Lerno
2023-08-19 22:29:10 +02:00
committed by Christoffer Lerno
parent ed70f39da8
commit 6c60b0d2a6
21 changed files with 697 additions and 343 deletions

View File

@@ -12,13 +12,13 @@ struct StackTrace
uint line;
}
struct VirtualAny
struct AnyStruct
{
void* ptr;
typeid type_id;
typeid type;
}
struct SubArrayContainer
struct SubArrayStruct
{
void* ptr;
usz len;

View File

@@ -420,160 +420,154 @@ const CLOCKS_PER_SEC = 1000000;
module libc::errno;
const Errno OK = 0;
const Errno EPERM = 1; // Operation not permitted
const Errno ENOENT = 2; // No such file or directory
const Errno ESRCH = 3; // No such process
const Errno EINTR = 4; // Interrupted system call
const Errno EIO = 5; // I/O error
const Errno ENXIO = 6; // No such device or address
const Errno E2BIG = 7; // Argument list too long
const Errno ENOEXEC = 8; // Exec format error
const Errno EBADF = 9; // Bad file number
const Errno ECHILD = 10; // No child processes
const Errno OK = 0;
const Errno EPERM = 1; // Operation not permitted
const Errno ENOENT = 2; // No such file or directory
const Errno ESRCH = 3; // No such process
const Errno EINTR = 4; // Interrupted system call
const Errno EIO = 5; // I/O error
const Errno ENXIO = 6; // No such device or address
const Errno E2BIG = 7; // Argument list too long
const Errno ENOEXEC = 8; // Exec format error
const Errno EBADF = 9; // Bad file number
const Errno ECHILD = 10; // No child processes
const Errno EAGAIN @if(env::DARWIN) = 35; // Try again Macos
const Errno EAGAIN @if(!env::DARWIN) = 11; // Try again
const Errno EAGAIN @if(env::DARWIN) = 35; // Try again Macos
const Errno EAGAIN @if(!env::DARWIN) = 11; // Try again
const Errno ENOMEM = 12; // Out of memory
const Errno EACCES = 13; // Permission denied
const Errno EFAULT = 14; // Bad address
const Errno ENOTBLK = 15; // Block device required, not on Win32
const Errno EBUSY = 16; // Device or resource busy
const Errno EEXIST = 17; // File exists
const Errno EXDEV = 18; // Cross-device link
const Errno ENODEV = 19; // No such device
const Errno ENOTDIR = 20; // Not a directory
const Errno EISDIR = 21; // Is a directory
const Errno EINVAL = 22; // Invalid argument
const Errno ENFILE = 23; // File table overflow
const Errno EMFILE = 24; // Too many open files
const Errno ENOTTY = 25; // Not a typewriter
const Errno ETXTBSY = 26; // Text file busy, not on Win32
const Errno EFBIG = 27; // File too large
const Errno ENOSPC = 28; // No space left on device
const Errno ESPIPE = 29; // Illegal seek
const Errno EROFS = 30; // Read-only file system
const Errno EMLINK = 31; // Too many links
const Errno EPIPE = 32; // Broken pipe
const Errno EDOM = 33; // Math argument out of domain of func
const Errno ERANGE = 34; // Math result not representable
const Errno ENOMEM = 12; // Out of memory
const Errno EACCES = 13; // Permission denied
const Errno EFAULT = 14; // Bad address
const Errno ENOTBLK = 15; // Block device required, not on Win32
const Errno EBUSY = 16; // Device or resource busy
const Errno EEXIST = 17; // File exists
const Errno EXDEV = 18; // Cross-device link
const Errno ENODEV = 19; // No such device
const Errno ENOTDIR = 20; // Not a directory
const Errno EISDIR = 21; // Is a directory
const Errno EINVAL = 22; // Invalid argument
const Errno ENFILE = 23; // File table overflow
const Errno EMFILE = 24; // Too many open files
const Errno ENOTTY = 25; // Not a typewriter
const Errno ETXTBSY = 26; // Text file busy, not on Win32
const Errno EFBIG = 27; // File too large
const Errno ENOSPC = 28; // No space left on device
const Errno ESPIPE = 29; // Illegal seek
const Errno EROFS = 30; // Read-only file system
const Errno EMLINK = 31; // Too many links
const Errno EPIPE = 32; // Broken pipe
const Errno EDOM = 33; // Math argument out of domain of func
const Errno ERANGE = 34; // Math result not representable
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/intro.2.html
module libc::errno @if(env::DARWIN);
const Errno EWOULDBLOCK = EAGAIN; // Operation would block
const Errno EDEADLK = 11; // Resource deadlock would occur
const Errno EINPROGRESS = 36; // Operation now in progress
const Errno EALREADY = 37; // Operation already in progress
const Errno ENOTSOCK = 38; // Socket operation on non-socket
const Errno EDESTADDRREQ = 39; // Destination address required
const Errno EMSGSIZE = 40; // Message too long
const Errno EPROTOTYPE = 41; // Protocol wrong type for socket
const Errno ENOPROTOOPT = 42; // Protocol not available
const Errno EPROTONOSUPPORT = 43; // Protocol not supported
const Errno ESOCKTNOSUPPORT = 44; // Socket type not supported
const Errno ENOTSUP = 45; // Not supported
const Errno EPFNOSUPPORT = 46; // Protocol family not supported
const Errno EAFNOSUPPORT = 47; // Address family not supported by protocol family
const Errno EADDRINUSE = 48; // Address already in use
const Errno EADDRNOTAVAIL = 49; // Cannot assign requested address
const Errno ENETDOWN = 50; // Network is down
const Errno ENETUNREACH = 51; // Network is unreachable
const Errno ENETRESET = 52; // Network dropped connection on reset
const Errno ECONNABORTED = 53; // Software caused connection abort
const Errno ECONNRESET = 54; // Connection reset by peer
const Errno ENOBUFS = 55; // No buffer space available
const Errno EISCONN = 56; // Socket is already connected
const Errno ENOTCONN = 57; // Socket is not connected
const Errno ESHUTDOWN = 58; // Cannot send after socket shutdown
const Errno ETIMEDOUT = 60; // Operation timed out
const Errno ECONNREFUSED = 61; // Connection refused
const Errno ELOOP = 62; // Too many levels of symbolic links
const Errno ENAMETOOLONG = 63; // File name too long
const Errno EHOSTDOWN = 64; // Host is down
const Errno EHOSTUNREACH = 65; // No route to host
const Errno ENOTEMPTY = 66; // Directory not empty
const Errno EPROCLIM = 67; // Too many processes
const Errno EUSERS = 68; // Too many users
const Errno EDQUOT = 69; // Disc quota exceeded
const Errno ESTALE = 70; // Stale NFS file handle
const Errno EBADRPC = 72; // RPC struct is bad
const Errno ERPCMISMATCH = 73; // RPC version wrong
const Errno EPROGUNAVAIL = 74; // RPC prog. not avail
const Errno EPROGMISMATCH = 75; // Program version wrong
const Errno EPROCUNAVAIL = 76; // Bad procedure for program
const Errno ENOLCK = 77; // No locks available
const Errno ENOSYS = 78; // Function not implemented
const Errno EFTYPE = 79; // Inappropriate file type or format
const Errno EAUTH = 80; // Authentication error
const Errno ENEEDAUTH = 81; // Need authenticator
const Errno EPWROFF = 82; // Device power is off
const Errno EDEVERR = 83; // Device error
const Errno EOVERFLOW = 84; // Value too large to be stored in data type
const Errno EBADEXEC = 85; // Bad executable (or shared library)
const Errno EBADARCH = 86; // Bad CPU type in executable
const Errno ESHLIBVERS = 87; // Shared library version mismatch
const Errno EBADMACHO = 88; // Malformed Mach-o file
const Errno ECANCELED = 89; // Operation canceled
const Errno EIDRM = 90; // Identifier removed
const Errno ENOMSG = 91; // No message of desired type
const Errno EILSEQ = 92; // Illegal byte sequence
const Errno ENOATTR = 93; // Attribute not found
const Errno EBADMSG = 94; // Bad message
const Errno EMULTIHOP = 95; // Reserved
const Errno ENODATA = 96; // No message available
const Errno ENOLINK = 97; // Reserved
const Errno ENOSR = 98; // No STREAM resources
const Errno ENOSTR = 99; // Not a STREAM
const Errno EPROTO = 100; // Protocol error
const Errno ETIME = 101; // STREAM ioctl() timeout
const Errno EOPNOTSUPP = 102; // Operation not supported on socket
const Errno EWOULDBLOCK = EAGAIN; // Operation would block
const Errno EDEADLK = 11; // Resource deadlock would occur
const Errno EINPROGRESS = 36; // Operation now in progress
const Errno EALREADY = 37; // Operation already in progress
const Errno ENOTSOCK = 38; // Socket operation on non-socket
const Errno EDESTADDRREQ = 39; // Destination address required
const Errno EMSGSIZE = 40; // Message too long
const Errno EPROTOTYPE = 41; // Protocol wrong type for socket
const Errno ENOPROTOOPT = 42; // Protocol not available
const Errno EPROTONOSUPPORT = 43; // Protocol not supported
const Errno ESOCKTNOSUPPORT = 44; // Socket type not supported
const Errno ENOTSUP = 45; // Not supported
const Errno EPFNOSUPPORT = 46; // Protocol family not supported
const Errno EAFNOSUPPORT = 47; // Address family not supported by protocol family
const Errno EADDRINUSE = 48; // Address already in use
const Errno EADDRNOTAVAIL = 49; // Cannot assign requested address
const Errno ENETDOWN = 50; // Network is down
const Errno ENETUNREACH = 51; // Network is unreachable
const Errno ENETRESET = 52; // Network dropped connection on reset
const Errno ECONNABORTED = 53; // Software caused connection abort
const Errno ECONNRESET = 54; // Connection reset by peer
const Errno ENOBUFS = 55; // No buffer space available
const Errno EISCONN = 56; // Socket is already connected
const Errno ENOTCONN = 57; // Socket is not connected
const Errno ESHUTDOWN = 58; // Cannot send after socket shutdown
const Errno ETIMEDOUT = 60; // Operation timed out
const Errno ECONNREFUSED = 61; // Connection refused
const Errno ELOOP = 62; // Too many levels of symbolic links
const Errno ENAMETOOLONG = 63; // File name too long
const Errno EHOSTDOWN = 64; // Host is down
const Errno EHOSTUNREACH = 65; // No route to host
const Errno ENOTEMPTY = 66; // Directory not empty
const Errno EPROCLIM = 67; // Too many processes
const Errno EUSERS = 68; // Too many users
const Errno EDQUOT = 69; // Disc quota exceeded
const Errno ESTALE = 70; // Stale NFS file handle
const Errno EBADRPC = 72; // RPC struct is bad
const Errno ERPCMISMATCH = 73; // RPC version wrong
const Errno EPROGUNAVAIL = 74; // RPC prog. not avail
const Errno EPROGMISMATCH = 75; // Program version wrong
const Errno EPROCUNAVAIL = 76; // Bad procedure for program
const Errno ENOLCK = 77; // No locks available
const Errno ENOSYS = 78; // Function not implemented
const Errno EFTYPE = 79; // Inappropriate file type or format
const Errno EAUTH = 80; // Authentication error
const Errno ENEEDAUTH = 81; // Need authenticator
const Errno EPWROFF = 82; // Device power is off
const Errno EDEVERR = 83; // Device error
const Errno EOVERFLOW = 84; // Value too large to be stored in data type
const Errno EBADEXEC = 85; // Bad executable (or shared library)
const Errno EBADARCH = 86; // Bad CPU type in executable
const Errno ESHLIBVERS = 87; // Shared library version mismatch
const Errno EBADMACHO = 88; // Malformed Mach-o file
const Errno ECANCELED = 89; // Operation canceled
const Errno EIDRM = 90; // Identifier removed
const Errno ENOMSG = 91; // No message of desired type
const Errno EILSEQ = 92; // Illegal byte sequence
const Errno ENOATTR = 93; // Attribute not found
const Errno EBADMSG = 94; // Bad message
const Errno EMULTIHOP = 95; // Reserved
const Errno ENODATA = 96; // No message available
const Errno ENOLINK = 97; // Reserved
const Errno ENOSR = 98; // No STREAM resources
const Errno ENOSTR = 99; // Not a STREAM
const Errno EPROTO = 100; // Protocol error
const Errno ETIME = 101; // STREAM ioctl() timeout
const Errno EOPNOTSUPP = 102; // Operation not supported on socket
module libc::errno @if(env::WIN32);
const Errno EDEADLK = 36; // Resource deadlock would occur Win32
const Errno ENAMETOOLONG = 38; // File name too long Win32
const Errno ELOOP = 114; // Too many symbolic links encountered
const Errno EOVERFLOW = 132; // Value too large for defined data type
const Errno ENETDOWN = 116; // Network is down
const Errno ECONNRESET = 108; // Connection reset by peer
const Errno ENETUNREACH = 118; // Network is unreachable
const Errno ENETRESET = 117; // Network dropped connection because of reset
const Errno EOPNOTSUPP = 130; // Operation not supported on transport endpoint
const Errno ENOTEMPTY = 41; // Directory not empty
const Errno ETIMEDOUT = 138; // Connection timed out
const Errno EALREADY = 103; // Operation already in progress
const Errno EINPROGRESS = 112; // Operation now in progress Win32
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
const Errno EWOULDBLOCK = 140; // Operation would block
// https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
const Errno ENOTSOCK = 10038; // Network is unreachable
//const Errno EOPNOTSUPP = 10045; // Operation not supported on transport endpoint
const Errno EADDRINUSE = 10048; // Address already in use
const Errno EISCONN = 10056; // Socket is already connected
const Errno ECONNREFUSED = 10061; // Connection refused
//const Errno ENETUNREACH = 10065; // Network is unreachable
const Errno EDEADLK = 36; // Resource deadlock would occur Win32
const Errno ENAMETOOLONG = 38; // File name too long Win32
const Errno ENOTEMPTY = 41; // Directory not empty
const Errno ELOOP = 114; // Too many symbolic links encountered
const Errno EOVERFLOW = 132; // Value too large for defined data type
const Errno ENETDOWN = 116; // Network is down
const Errno ECONNRESET = 108; // Connection reset by peer
const Errno ENETUNREACH = 118; // Network is unreachable
const Errno ENETRESET = 117; // Network dropped connection because of reset
const Errno EOPNOTSUPP = 130; // Operation not supported on transport endpoint
const Errno ETIMEDOUT = 138; // Connection timed out
const Errno EALREADY = 103; // Operation already in progress
const Errno EINPROGRESS = 112; // Operation now in progress Win32
const Errno EDQUOT = -122; // Quota exceeded, not in Win32
const Errno EWOULDBLOCK = 140; // Operation would block
module libc::errno @if(!env::WIN32 && !env::DARWIN);
const Errno EDEADLK = 35; // Resource deadlock would occur Linux (others?)
const Errno ENAMETOOLONG = 36; // File name too long Linux (others?)
const Errno ENOTEMPTY = 39; // Directory not empty
const Errno ELOOP = 40; // Too many symbolic links encountered
const Errno EWOULDBLOCK = EAGAIN; // Operation would block
const Errno EOVERFLOW = 75; // Value too large for defined data type
const Errno ENOTSOCK = 88; // Socket operation on non-socket
const Errno EOPNOTSUPP = 95; // Operation not supported on transport endpoint
const Errno EADDRINUSE = 98; // Address already in use
const Errno ENETDOWN = 100; // Network is down
const Errno ENETUNREACH = 101; // Network is unreachable
const Errno ENETRESET = 102; // Network dropped connection because of reset
const Errno ECONNRESET = 104; // Connection reset by peer
const Errno EISCONN = 106; // Socket is already connected
const Errno ETIMEDOUT = 110; // Connection timed out
const Errno ECONNREFUSED = 111; // Connection refused
const Errno EALREADY = 114; // Operation already in progress
const Errno EINPROGRESS = 115; // Operation now in progress
const Errno EDQUOT = 122; // Quota exceeded
const Errno EDEADLK = 35; // Resource deadlock would occur Linux (others?)
const Errno ENAMETOOLONG = 36; // File name too long Linux (others?)
const Errno ENOTEMPTY = 39; // Directory not empty
const Errno ELOOP = 40; // Too many symbolic links encountered
const Errno EWOULDBLOCK = EAGAIN; // Operation would block
const Errno EOVERFLOW = 75; // Value too large for defined data type
const Errno ENOTSOCK = 88; // Socket operation on non-socket
const Errno EOPNOTSUPP = 95; // Operation not supported on transport endpoint
const Errno EADDRINUSE = 98; // Address already in use
const Errno EADDRNOTAVAIL = 99; // Cannot assign requested address
const Errno ENETDOWN = 100; // Network is down
const Errno ENETUNREACH = 101; // Network is unreachable
const Errno ENETRESET = 102; // Network dropped connection because of reset
const Errno ECONNRESET = 104; // Connection reset by peer
const Errno EISCONN = 106; // Socket is already connected
const Errno ETIMEDOUT = 110; // Connection timed out
const Errno ECONNREFUSED = 111; // Connection refused
const Errno EALREADY = 114; // Operation already in progress
const Errno EINPROGRESS = 115; // Operation now in progress
const Errno EDQUOT = 122; // Quota exceeded
/*
@@ -635,7 +629,6 @@ const Errno ESOCKTNOSUPPORT = 94; /* Socket type not supported */
const Errno EPFNOSUPPORT = 96; /* Protocol family not supported */
const Errno EAFNOSUPPORT = 97; /* Address family not supported by protocol */
const Errno EADDRINUSE = 98; /* Address already in use */
const Errno EADDRNOTAVAIL = 99; /* Cannot assign requested address */
const Errno ECONNABORTED = 103; /* Software caused connection abort */
const Errno ENOBUFS = 105; /* No buffer space available */
const Errno EISCONN = 106; /* Transport endpoint is already connected */

View File

@@ -2,6 +2,13 @@ module std::net;
import std::io;
import std::ascii;
enum IpProtocol : char (AIFamily ai_family)
{
UNSPECIFIED (os::AF_UNSPEC),
IPV4 (os::AF_INET),
IPV6 (os::AF_INET6),
}
struct InetAddress
{
bool is_ipv6;
@@ -250,3 +257,18 @@ fn bool InetAddress.is_multicast_link_local(InetAddress* addr)
}
return addr.ipv4.a == 224 && addr.ipv4.b == 0 && addr.ipv4.c == 0;
}
fn AddrInfo*! addrinfo(String host, uint port, AIFamily ai_family, AISockType ai_socktype) @if(os::SUPPORTS_INET)
{
@pool()
{
ZString zhost = host.zstr_tcopy();
DString str;
str.tinit();
str.printf("%d", port);
AddrInfo hints = { .ai_family = ai_family, .ai_socktype = ai_socktype };
AddrInfo* ai;
if (os::getaddrinfo(zhost, str.copy_zstr(mem::temp()), &hints, &ai)) return NetError.ADDRINFO_FAILED?;
return ai;
};
}

View File

@@ -1,5 +1,4 @@
module std::net;
import std::net::os;
fault NetError
{
@@ -16,6 +15,8 @@ fault NetError
READ_FAILED,
SOCKOPT_FAILED,
SOCKETS_NOT_INITIALIZED,
STILL_PROCESSING_CALLBACK,
BAD_SOCKET_DESCRIPTOR,
NOT_A_SOCKET,
CONNECTION_REFUSED,

View File

@@ -1,6 +1,11 @@
module std::net::os;
const bool SUPPORTS_INET = env::LIBC && (env::WIN32 || env::DARWIN || env::LINUX);
def AIFamily = distinct CInt;
def AIProtocol = distinct CInt;
def AISockType = distinct CInt;
def AIFlags = distinct CInt;
def Socklen_t = CUInt @if(!env::WIN32);
def Socklen_t = usz @if(env::WIN32);
@@ -8,10 +13,10 @@ def SockAddrPtr = distinct void*;
struct AddrInfo
{
CInt ai_flags;
CInt ai_family;
CInt ai_socktype;
CInt ai_protocol;
AIFlags ai_flags;
AIFamily ai_family;
AISockType ai_socktype;
AIProtocol ai_protocol;
Socklen_t ai_addrlen;
struct @if(env::WIN32 || env::DARWIN)
{
@@ -26,26 +31,35 @@ struct AddrInfo
AddrInfo* ai_next;
}
const PLATFORM_O_NONBLOCK @if(!$defined(PLATFORM_O_NONBLOCK)) = 0;
const int PLATFORM_AF_UNIX = 1;
const int PLATFORM_AF_INET = 2;
const int PLATFORM_AF_INET6 @if(env::WIN32) = 23;
const int PLATFORM_AF_INET6 @if(env::DARWIN) = 30;
const int PLATFORM_AF_INET6 @if(env::LINUX) = 10;
const AISockType SOCK_STREAM = 1; // Stream
const AISockType SOCK_DGRAM = 2; // Datagram
const AISockType SOCK_RAW = 3; // Raw
const AISockType SOCK_RDM = 4; // Reliably delivered
const AISockType SOCK_SEQPACKET = 5; // Sequential packet
const AI_PASSIVE = 0x1;
const AI_CANONNAME = 0x2;
const AI_NUMERICHOST = 0x4;
const AIFlags AI_PASSIVE = 0x1;
const AIFlags AI_CANONNAME = 0x2;
const AIFlags AI_NUMERICHOST = 0x4;
const int AF_UNSPEC = 0;
const int AF_INET @if(SUPPORTS_INET) = PLATFORM_AF_INET;
const int AF_APPLETALK @if(SUPPORTS_INET) = PLATFORM_AF_APPLETALK;
const int AF_IPX @if(SUPPORTS_INET) = PLATFORM_AF_IPX;
const int AF_INET6 @if(SUPPORTS_INET) = PLATFORM_AF_INET6;
const AIFamily AF_UNSPEC = 0;
const AIFamily AF_UNIX = 1;
const AIFamily AF_INET = 2;
const AIFamily AF_INET6 = PLATFORM_AF_INET6;
const AIFamily AF_IPX = PLATFORM_AF_IPX;
const AIFamily AF_APPLETALK = PLATFORM_AF_APPLETALK;
const O_NONBLOCK = PLATFORM_O_NONBLOCK;
extern fn CInt getaddrinfo(ZString nodename, ZString servname, AddrInfo* hints, AddrInfo** res) @if(SUPPORTS_INET);
extern fn void freeaddrinfo(AddrInfo* res) @if(SUPPORTS_INET);
extern fn CInt setsockopt(NativeSocket socket, CInt level, CInt optname, void* optval, Socklen_t optlen) @if(SUPPORTS_INET);
extern fn CInt getsockopt(NativeSocket socket, CInt level, CInt optname, void* optval, Socklen_t optlen) @if(SUPPORTS_INET);
module std::net::os @if(!env::LIBC || !(env::WIN32 || env::DARWIN || env::LINUX));
const AIFamily PLATFORM_AF_INET6 = 0;
const AIFamily PLATFORM_AF_IPX = 0;
const AIFamily PLATFORM_AF_APPLETALK = 0;

View File

@@ -1,54 +1,85 @@
module std::net::os @if(env::DARWIN);
import libc;
const AI_NUMERICSERV = 0x1000;
const AI_ALL = 0x100;
const AI_V4MAPPED_CFG = 0x200;
const AI_ADDRCONFIG = 0x400;
const AI_V4MAPPED = 0x800;
const AI_UNUSABLE = 0x10000000;
const AI_DEFAULT = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
const AIFlags AI_NUMERICSERV = 0x1000;
const AIFlags AI_ALL = 0x100;
const AIFlags AI_V4MAPPED_CFG = 0x200;
const AIFlags AI_ADDRCONFIG = 0x400;
const AIFlags AI_V4MAPPED = 0x800;
const AIFlags AI_UNUSABLE = 0x10000000;
const AIFlags AI_DEFAULT = AI_V4MAPPED_CFG | AI_ADDRCONFIG;
const AIFamily PLATFORM_AF_IMPLINK = 3;
const AIFamily PLATFORM_AF_PUP = 4;
const AIFamily PLATFORM_AF_CHAOS = 5;
const AIFamily PLATFORM_AF_NS = 6;
const AIFamily PLATFORM_AF_ISO = 7;
const AIFamily PLATFORM_AF_ECMA = 8;
const AIFamily PLATFORM_AF_DATAKIT = 9;
const AIFamily PLATFORM_AF_CCITT = 10;
const AIFamily PLATFORM_AF_SNA = 11;
const AIFamily PLATFORM_AF_DECNET = 12;
const AIFamily PLATFORM_AF_DLI = 13;
const AIFamily PLATFORM_AF_LAT = 14;
const AIFamily PLATFORM_AF_HYLINK = 15;
const AIFamily PLATFORM_AF_APPLETALK = 16;
const AIFamily PLATFORM_AF_ROUTE = 17;
const AIFamily PLATFORM_AF_LINK = 18;
const AIFamily PLATFORM_PSEUDO_AF_XTP = 19;
const AIFamily PLATFORM_AF_COIP = 20;
const AIFamily PLATFORM_AF_CNT = 21;
const AIFamily PLATFORM_PSEUDO_AF_RTIP = 22;
const AIFamily PLATFORM_AF_IPX = 23;
const AIFamily PLATFORM_AF_SIP = 24;
const AIFamily PLATFORM_PSEUDO_AF_PIP = 25;
const AIFamily PLATFORM_AF_NDRV = 27;
const AIFamily PLATFORM_AF_ISDN = 28;
const AIFamily PLATFORM_PSEUDO_AF_KEY = 29;
const AIFamily PLATFORM_AF_INET6 = 30;
const AIFamily PLATFORM_AF_NATM = 31;
const AIFamily PLATFORM_AF_SYSTEM = 32;
const AIFamily PLATFORM_AF_NETBIOS = 33;
const AIFamily PLATFORM_AF_PPP = 34;
const AIFamily PLATFORM_PSEUDO_AF_HDRCMPLT = 35;
const AIFamily PLATFORM_AF_IEEE80211 = 37;
const AIFamily PLATFORM_AF_UTUN = 38;
const AIFamily PLATFORM_AF_VSOCK = 40;
const AIFamily PLATFORM_AF_MAX = 41;
const int PLATFORM_AF_IMPLINK = 3;
const int PLATFORM_AF_PUP = 4;
const int PLATFORM_AF_CHAOS = 5;
const int PLATFORM_AF_NS = 6;
const int PLATFORM_AF_ISO = 7;
const int PLATFORM_AF_ECMA = 8;
const int PLATFORM_AF_DATAKIT = 9;
const int PLATFORM_AF_CCITT = 10;
const int PLATFORM_AF_SNA = 11;
const int PLATFORM_AF_DECNET = 12;
const int PLATFORM_AF_DLI = 13;
const int PLATFORM_AF_LAT = 14;
const int PLATFORM_AF_HYLINK = 15;
const int PLATFORM_AF_APPLETALK = 16;
const int PLATFORM_AF_ROUTE = 17;
const int PLATFORM_AF_LINK = 18;
const int PLATFORM_PSEUDO_AF_XTP = 19;
const int PLATFORM_AF_COIP = 20;
const int PLATFORM_AF_CNT = 21;
const int PLATFORM_PSEUDO_AF_RTIP = 22;
const int PLATFORM_AF_IPX = 23;
const int PLATFORM_AF_SIP = 24;
const int PLATFORM_PSEUDO_AF_PIP = 25;
const int PLATFORM_AF_NDRV = 27;
const int PLATFORM_AF_ISDN = 28;
const int PLATFORM_PSEUDO_AF_KEY = 29;
const int PLATFORM_AF_NATM = 31;
const int PLATFORM_AF_SYSTEM = 32;
const int PLATFORM_AF_NETBIOS = 33;
const int PLATFORM_AF_PPP = 34;
const int PLATFORM_PSEUDO_AF_HDRCMPLT = 35;
const int PLATFORM_AF_IEEE80211 = 37;
const int PLATFORM_AF_UTUN = 38;
const int PLATFORM_AF_VSOCK = 40;
const int PLATFORM_AF_MAX = 41;
const int PLATFORM_O_NONBLOCK = 0x30;
// https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/sys/socket.h.auto.html
const int SOL_SOCKET = 0xffff;
const int SO_REUSEADDR = 0x0004;
const int SO_KEEPALIVE = 0x0008;
const int SO_BROADCAST = 0x0020;
const int SO_REUSEPORT = 0x0200;
const int SOL_SOCKET = 0xffff;
const int SO_DEBUG = 0x0001; // turn on debugging info recording
const int SO_ACCEPTCONN = 0x0002; // socket has had listen()
const int SO_REUSEADDR = 0x0004; // allow local address reuse
const int SO_KEEPALIVE = 0x0008; // keep connections alive
const int SO_DONTROUTE = 0x0010; // just use interface addresses
const int SO_BROADCAST = 0x0020; // permit sending of broadcast msgs
const int SO_USELOOPBACK = 0x0040; // bypass hardware when possible
const int SO_LINGER = 0x0080; // linger on close if data present (in ticks)
const int SO_OOBINLINE = 0x0100; // leave received OOB data in line
const int SO_REUSEPORT = 0x0200; // allow local address & port reuse
const int SO_TIMESTAMP = 0x0400; // timestamp received dgram traffic
const int SO_TIMESTAMP_MONOTONIC = 0x0800; // Monotonically increasing timestamp on rcvd dgram
const int SO_DONTTRUNC = 0x2000; // Apple Retain unread data
const int SO_WANTMORE = 0x4000; // Apple: Give hint when more data ready
const int SO_WANTOOBFLAG = 0x8000; // Apple: Want OOB in MSG_FLAG on receive
const int SO_SNDBUF = 0x1001; // Send buffer size
const int SO_RCVBUF = 0x1002; // Recieve buffer size
const int SO_SNDLOWAT = 0x1003; // Send low-water mark
const int SO_RCVLOWAT = 0x1004; // Receive low-water mark
const int SO_SNDTIMEO = 0x1005; // Send timeout
const int SO_RCVTIMEO = 0x1006; // Receive timeout
const int SO_ERROR = 0x1007; // Get error status and clear
const int SO_TYPE = 0x1008; // Socket type
const int SO_LABEL = 0x1010; // Socket MAC label
const int SO_PEERLABEL = 0x1011; // Socket peer MAC label
const int SO_NREAD = 0x1020; // Apple: get 1st-packet byte count
const int SO_NKE = 0x1021; // Apple: Install socket-level NKE
const int SO_NOSIGPIPE = 0x1022; // Apple: No SIGPIPE on EPIPE
const int SO_NOADDRERR = 0x1023; // Apple: Returns EADDRNOTAVAIL when src is not available anymore
const int SO_NWRITE = 0x1024; // Apple: Get number of bytes currently in send socket buffer
const int SO_REUSESHAREUID = 0x1025; // Apple: Allow reuse of port/socket by different userids
const int SO_LINGER_SEC = 0x1080; // linger on close if data present (in seconds)

View File

@@ -1,19 +1,80 @@
module std::net::os @if(env::LINUX);
import libc;
const int PLATFORM_AF_AX25 = 3;
const int PLATFORM_AF_IPX = 4;
const int PLATFORM_AF_APPLETALK = 5;
const int PLATFORM_AF_NETROM = 6;
const int PLATFORM_AF_BRIDGE = 7;
const int PLATFORM_AF_AAL5 = 8;
const int PLATFORM_AF_X25 = 9;
const AIFamily PLATFORM_AF_AX25 = 3;
const AIFamily PLATFORM_AF_IPX = 4;
const AIFamily PLATFORM_AF_APPLETALK = 5;
const AIFamily PLATFORM_AF_NETROM = 6;
const AIFamily PLATFORM_AF_BRIDGE = 7;
const AIFamily PLATFORM_AF_AAL5 = 8;
const AIFamily PLATFORM_AF_X25 = 9;
const AIFamily PLATFORM_AF_INET6 = 10;
const PLATFORM_O_NONBLOCK = 0o4000;
// https://git.sr.ht/~sircmpwn/hare/tree/master/item/rt/+linux/socket.ha
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/socket.h
const int SOL_SOCKET = 1;
const int SO_REUSEADDR = 2;
const int SO_BROADCAST = 6;
const int SO_KEEPALIVE = 9;
const int SO_REUSEPORT = 15;
const int SO_DEBUG = 1; // turn on debugging info recording
const int SO_REUSEADDR = 2; // allow local address reuse
const int SO_TYPE = 3;
const int SO_ERROR = 4;
const int SO_DONTROUTE = 5; // just use interface addresses
const int SO_BROADCAST = 6; // permit sending of broadcast msgs
const int SO_SNDBUF = 7; // Send buffer size
const int SO_RCVBUF = 8; // Recieve buffer size
const int SO_KEEPALIVE = 9; // keep connections alive
const int SO_OOBINLINE = 10; // leave received OOB data in line
const int SO_NO_CHECK = 11;
const int SO_PRIORITY = 12;
const int SO_LINGER = 13; // linger on close if data present (in ticks)
const int SO_BSDCOMPAT = 14;
const int SO_REUSEPORT = 15; // allow local address & port reuse
const int SO_RCVLOWAT = 18;
const int SO_SNDLOWAT = 19;
const int SO_RCVTIMEO = 20; // IMPORTANT Verify before use
const int SO_SNDTIMEO = 21; // IMPORTANT Verify before use
const int SO_BINDTODEVICE = 25;
const int SO_ATTACH_FILTER = 26;
const int SO_DETACH_FILTER = 27;
const int SO_PEERNAME = 28;
const int SO_TIMESTAMP = 29; // IMPORTANT Verify before use timestamp received dgram traffic
const int SO_ACCEPTCONN = 30;
const int SO_PEERSEC = 31;
const int SO_SNDBUFFORCE = 32;
const int SO_RCVBUFFORCE = 33;
const int SO_PASSSEC = 34;
const int SO_MARK = 36;
const int SO_PROTOCOL = 38;
const int SO_DOMAIN = 39;
const int SO_RXQ_OVFL = 40;
const int SO_WIFI_STATUS = 41;
const int SO_PEEK_OFF = 42;
const int SO_NOFCS = 43;
const int SO_LOCK_FILTER = 44;
const int SO_SELECT_ERR_QUEUE = 45;
const int SO_BUSY_POLL = 46;
const int SO_MAX_PACING_RATE = 47;
const int SO_BPF_EXTENSIONS = 48;
const int SO_INCOMING_CPU = 49;
const int SO_ATTACH_BPF = 50;
const int SO_ATTACH_REUSEPORT_CBPF = 51;
const int SO_ATTACH_REUSEPORT_EBPF = 52;
const int SO_CNX_ADVICE = 53;
const int SO_MEMINFO = 55;
const int SO_INCOMING_NAPI_ID = 56;
const int SO_COOKIE = 57;
const int SO_PEERGROUPS = 59;
const int SO_ZEROCOPY = 60;
const int SO_TXTIME = 61;
const int SO_BINDTOIFINDEX = 62;
const int SO_DETACH_REUSEPORT_BPF = 68;
const int SO_PREFER_BUSY_POLL = 69;
const int SO_BUSY_POLL_BUDGET = 70;
const int SO_NETNS_COOKIE = 71;
const int SO_BUF_LOCK = 72;
const int SO_RESERVE_MEM = 73;
const int SO_TXREHASH = 74;
const int SO_RCVMARK = 75;
const int SO_PASSPIDFD = 76;
const int SO_PEERPIDFD = 77;

View File

@@ -6,13 +6,34 @@ const int F_SETFL = 4;
def NativeSocket = distinct inline Fd;
extern fn CInt connect(NativeSocket socket, SockAddrPtr address, Socklen_t address_len);
extern fn NativeSocket socket(CInt af, CInt type, CInt protocol) @extern("socket");
extern fn NativeSocket socket(AIFamily af, AISockType type, AIProtocol protocol) @extern("socket");
extern fn int fcntl(NativeSocket socket, int cmd, ...) @extern("fcntl");
extern fn CInt bind(NativeSocket socket, SockAddrPtr address, Socklen_t address_len) @extern("bind");
extern fn CInt listen(NativeSocket socket, CInt backlog) @extern("listen");
extern fn NativeSocket accept(NativeSocket socket, SockAddrPtr address, Socklen_t* address_len) @extern("accept");
fn anyfault socket_error()
{
switch (libc::errno())
{
case errno::EACCES: return IoError.NO_PERMISSION;
case errno::EADDRINUSE: return NetError.ADDRESS_IN_USE;
case errno::EALREADY: return NetError.CONNECTION_ALREADY_IN_PROGRESS;
case errno::EBADF: return NetError.BAD_SOCKET_DESCRIPTOR;
case errno::ECONNREFUSED: return NetError.CONNECTION_REFUSED;
case errno::EISCONN: return NetError.ALREADY_CONNECTED;
case errno::ENETUNREACH: return NetError.NETWORK_UNREACHABLE;
case errno::ENOTSOCK: return NetError.NOT_A_SOCKET;
case errno::EINTR: return IoError.INTERRUPTED;
case errno::EWOULDBLOCK: return IoError.WOULD_BLOCK;
case errno::EOPNOTSUPP: return NetError.OPERATION_NOT_SUPPORTED_ON_SOCKET;
case errno::ETIMEDOUT: return NetError.CONNECTION_TIMED_OUT;
default: return IoError.GENERAL_ERROR;
}
}
macro void! NativeSocket.close(self)
{
if (libc::close(self))

View File

@@ -1,35 +1,74 @@
module std::net::os @if(env::WIN32);
import std::os::win32;
import libc;
const int PLATFORM_AF_IPX = 6;
const int PLATFORM_AF_APPLETALK = 16;
const int PLATFORM_AF_NETBIOS = 17;
const int PLATFORM_AF_IRDA = 26;
const int PLATFORM_AF_BTH = 32;
const AIFamily PLATFORM_AF_IPX = 6;
const AIFamily PLATFORM_AF_APPLETALK = 16;
const AIFamily PLATFORM_AF_NETBIOS = 17;
const AIFamily PLATFORM_AF_INET6 = 23;
const AIFamily PLATFORM_AF_IRDA = 26;
const AIFamily PLATFORM_AF_BTH = 32;
def NativeSocket = distinct uptr;
extern fn int wsa_startup(int, void*) @extern("WSAStartup");
extern fn int ioctlsocket(NativeSocket, long cmd, ulong *argp);
extern fn int closesocket(NativeSocket);
extern fn NativeSocket socket(int af, int type, int protocol);
extern fn WSAError closesocket(NativeSocket);
extern fn NativeSocket socket(AIFamily af, AISockType type, AIProtocol protocol);
extern fn int connect(NativeSocket, SockAddrPtr address, Socklen_t address_len);
extern fn int bind(NativeSocket, SockAddrPtr address, Socklen_t address_len);
extern fn int listen(NativeSocket, int backlog);
extern fn NativeSocket accept(NativeSocket, SockAddrPtr address, Socklen_t* address_len);
macro NativeSocket.close(self)
macro void! NativeSocket.close(self)
{
if (int err = closesocket(self))
{
if (err == WSAENOTSOCK) return NetError.INVALID_SOCKET?;
return NetError.GENERAL_ERROR?;
}
WSAError error = closesocket(self);
if (error) return convert_error(error)?;
}
const int WSAENOTSOCK = 10038;
// https://github.com/wine-mirror/wine/blob/master/include/winsock.h
const int SOL_SOCKET = 0xffff;
const int SO_REUSEADDR = 0x0004;
const int SO_KEEPALIVE = 0x0008;
const int SO_BROADCAST = 0x0200;
const int SOL_SOCKET = 0xffff;
const int SO_DEBUG = 0x0001;
const int SO_ACCEPTCONN = 0x0002;
const int SO_REUSEADDR = 0x0004;
const int SO_KEEPALIVE = 0x0008;
const int SO_DONTROUTE = 0x0010;
const int SO_BROADCAST = 0x0020;
const int SO_USELOOPBACK = 0x0040;
const int SO_LINGER = 0x0080;
const int SO_OOBINLINE = 0x0100;
const int SO_SNDBUF = 0x1001;
const int SO_RCVBUF = 0x1002;
const int SO_SNDLOWAT = 0x1003;
const int SO_RCVLOWAT = 0x1004;
const int SO_SNDTIMEO = 0x1005;
const int SO_RCVTIMEO = 0x1006;
const int SO_ERROR = 0x1007;
const int SO_TYPE = 0x1008;
fn anyfault convert_error(WSAError error)
{
switch (error)
{
case wsa::NOTINITIALISED: return NetError.SOCKETS_NOT_INITIALIZED;
case wsa::ENETDOWN: return NetError.NETWORK_UNREACHABLE;
case wsa::INVALID_HANDLE: return NetError.BAD_SOCKET_DESCRIPTOR;
case wsa::EACCESS: return IoError.NO_PERMISSION;
case wsa::EINPROGRESS: return NetError.STILL_PROCESSING_CALLBACK;
case wsa::EADDRINUSE: return NetError.ADDRESS_IN_USE;
case wsa::EALREADY: return NetError.CONNECTION_ALREADY_IN_PROGRESS;
case wsa::EBADF: return NetError.BAD_SOCKET_DESCRIPTOR;
case wsa::EINTR: return IoError.INTERRUPTED;
case wsa::EWOULDBLOCK: return IoError.WOULD_BLOCK;
case wsa::ECONNREFUSED: return NetError.CONNECTION_REFUSED;
case wsa::EISCONN: return NetError.ALREADY_CONNECTED;
case wsa::ENETUNREACH: return NetError.NETWORK_UNREACHABLE;
case wsa::ENOTSOCK: return NetError.NOT_A_SOCKET;
case wsa::EOPNOTSUPP: return NetError.OPERATION_NOT_SUPPORTED_ON_SOCKET;
case wsa::ETIMEDOUT: return NetError.CONNECTION_TIMED_OUT;
default: return IoError.GENERAL_ERROR;
}
}
fn anyfault socket_error()
{
return convert_error(win32_WSAGetLastError());
}

View File

@@ -1,9 +0,0 @@
module std::net;
import std::io;
import libc;
const int SOCK_STREAM = 1; // Stream
const int SOCK_DGRAM = 2; // Datagram
const int SOCK_RAW = 3; // Raw
const int SOCK_RDM = 4; // Reliably delivered
const int SOCK_SEQPACKET = 5; // Sequential packet

View File

@@ -2,14 +2,38 @@ module std::net @if(os::SUPPORTS_INET);
import std::io;
import libc;
enum Network : char (int domain, int type)
enum Network : char (AIFamily domain, AISockType type)
{
TCP (os::AF_INET, SOCK_STREAM),
TCP6 (os::AF_INET6, SOCK_STREAM),
UDP (os::AF_INET, SOCK_DGRAM),
UDP6 (os::AF_INET6, SOCK_DGRAM),
TCP (os::AF_INET, os::SOCK_STREAM),
TCP6 (os::AF_INET6, os::SOCK_STREAM),
UDP (os::AF_INET, os::SOCK_DGRAM),
UDP6 (os::AF_INET6, os::SOCK_DGRAM),
}
struct Socket
{
NativeSocket sock;
Socklen_t ai_addrlen;
// TODO proper way to get the size of sockaddr_storage
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms740504(v=vs.85)
char[128] ai_addr_storage;
}
fn Socket! _connect(AddrInfo* addrinfo, SocketOption[] options)
{
@loop_over_ai(addrinfo; NativeSocket sockfd, AddrInfo* ai)
{
apply_sockoptions(sockfd, options)!;
int errcode = os::connect(sockfd, ai.ai_addr, ai.ai_addrlen);
// Keep the first successful connection.
if (!errcode) return network_socket(sockfd, ai);
};
return os::socket_error()?;
}
fn Socket! Network.connect(&self, String host, String port, SocketOption... options)
{
@network_loop_over_ai(self, host, port; NativeSocket sockfd, AddrInfo* ai)
@@ -19,20 +43,7 @@ fn Socket! Network.connect(&self, String host, String port, SocketOption... opti
// Keep the first successful connection.
if (errcode == 0) return network_socket(sockfd, ai);
}!;
switch (libc::errno())
{
case errno::EACCES: return IoError.NO_PERMISSION?;
case errno::EADDRINUSE: return NetError.ADDRESS_IN_USE?;
case errno::EALREADY: return NetError.CONNECTION_ALREADY_IN_PROGRESS?;
case errno::EBADF: return NetError.BAD_SOCKET_DESCRIPTOR?;
case errno::ECONNREFUSED: return NetError.CONNECTION_REFUSED?;
case errno::EISCONN: return NetError.ALREADY_CONNECTED?;
case errno::ENETUNREACH: return NetError.NETWORK_UNREACHABLE?;
case errno::ENOTSOCK: return NetError.NOT_A_SOCKET?;
case errno::EOPNOTSUPP: return NetError.OPERATION_NOT_SUPPORTED_ON_SOCKET?;
case errno::ETIMEDOUT: return NetError.CONNECTION_TIMED_OUT?;
}
return NetError.CONNECT_FAILED?;
return os::socket_error()?;
}
fn Socket! Network.listen(&self, String host, String port, int backlog, SocketOption... options)
@@ -48,14 +59,7 @@ fn Socket! Network.listen(&self, String host, String port, int backlog, SocketOp
if (errcode == 0) return network_socket(sockfd, ai);
}
}!;
switch (libc::errno())
{
case errno::EADDRINUSE: return NetError.ADDRESS_IN_USE?;
case errno::EBADF: return NetError.BAD_SOCKET_DESCRIPTOR?;
case errno::ENOTSOCK: return NetError.NOT_A_SOCKET?;
case errno::EOPNOTSUPP: return NetError.OPERATION_NOT_SUPPORTED_ON_SOCKET?;
}
return NetError.LISTEN_FAILED?;
return os::socket_error()?;
}
fn AddrInfo*! Network.addrinfo(&self, String host, String port) @private
@@ -69,10 +73,23 @@ fn AddrInfo*! Network.addrinfo(&self, String host, String port) @private
return ai;
}
macro apply_sockoptions(sockfd, options) @private
macro apply_sockoptions(sockfd, options)
{
Socket sock = { .sock = sockfd };
foreach (o : options) sock.set_option(o)!;
foreach (o : options) sock.set_option(o, true)!;
}
macro void @loop_over_ai(AddrInfo* ai; @body(NativeSocket fd, AddrInfo* ai))
{
while (ai)
{
NativeSocket sockfd = os::socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol);
if (sockfd > 0)
{
@body(sockfd, ai);
}
ai = ai.ai_next;
}
}
macro @network_loop_over_ai(network, host, port; @body(fd, ai)) @private
@@ -91,7 +108,7 @@ macro @network_loop_over_ai(network, host, port; @body(fd, ai)) @private
}
}
macro Socket network_socket(fd, ai) @private
macro Socket network_socket(fd, ai)
{
Socket sock = { .sock = fd, .ai_addrlen = ai.ai_addrlen };
assert(sock.ai_addr_storage.len >= ai.ai_addrlen, "storage %d < addrlen %d", sock.ai_addr_storage.len, ai.ai_addrlen);
@@ -99,28 +116,17 @@ macro Socket network_socket(fd, ai) @private
return sock;
}
enum SocketOption : char (CInt value) @if(!env::WIN32)
{
REUSEADDR (os::SO_REUSEADDR),
REUSEPORT (os::SO_REUSEPORT),
KEEPALIVE (os::SO_KEEPALIVE),
BROADCAST (os::SO_BROADCAST),
}
enum SocketOption : char (CInt value) @if(env::WIN32)
enum SocketOption : char (CInt value)
{
REUSEADDR (os::SO_REUSEADDR),
REUSEPORT (os::SO_REUSEPORT) @if(!env::WIN32),
KEEPALIVE (os::SO_KEEPALIVE),
BROADCAST (os::SO_BROADCAST),
OOBINLINE (os::SO_OOBINLINE),
DONTROUTE (os::SO_DONTROUTE),
}
struct Socket
{
NativeSocket sock;
Socklen_t ai_addrlen;
// TODO proper way to get the size of sockaddr_storage
// https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms740504(v=vs.85)
char[128] ai_addr_storage;
}
fn Stream Socket.as_stream(&self)
{
@@ -133,18 +139,37 @@ StreamInterface socketstream_interface = {
.close_fn = fn(s) => ((Socket*)s.data).close(),
};
fn void! Socket.set_option(&self, SocketOption option)
fn bool! Socket.get_broadcast(&self) => self.get_option(BROADCAST);
fn bool! Socket.get_keepalive(&self) => self.get_option(KEEPALIVE);
fn bool! Socket.get_reuseaddr(&self) => self.get_option(REUSEADDR);
fn bool! Socket.get_dontroute(&self) => self.get_option(DONTROUTE);
fn bool! Socket.get_oobinline(&self) => self.get_option(OOBINLINE);
fn void! Socket.set_broadcast(&self, bool value) => self.set_option(BROADCAST, value);
fn void! Socket.set_keepalive(&self, bool value) => self.set_option(KEEPALIVE, value);
fn void! Socket.set_reuseaddr(&self, bool value) => self.set_option(REUSEADDR, value);
fn void! Socket.set_dontroute(&self, bool value) => self.set_option(DONTROUTE, value);
fn void! Socket.set_oobinline(&self, bool value) => self.set_option(OOBINLINE, value);
fn void! Socket.set_option(&self, SocketOption option, bool value)
{
CInt flag = 1;
CInt flag = (CInt)value;
int errcode = os::setsockopt(self.sock, os::SOL_SOCKET, option.value, &flag, CInt.sizeof);
if (errcode != 0) return NetError.SOCKOPT_FAILED?;
}
fn void! Socket.unset_option(&self, SocketOption option)
macro void! @set_option_value(NativeSocket sock, CInt option, value)
{
CInt flag = 0;
var val = value;
if (os::setsockopt(sock, os::SOL_SOCKET, option, &val, $sizeof(val))) return NetError.SOCKOPT_FAILED?;
}
fn bool! Socket.get_option(&self, SocketOption option)
{
CInt flag;
int errcode = os::setsockopt(self.sock, os::SOL_SOCKET, option.value, &flag, CInt.sizeof);
if (errcode != 0) return NetError.SOCKOPT_FAILED?;
return (bool)flag;
}
fn usz! Socket.read(&self, char[] bytes)

45
lib/std/net/tcp.c3 Normal file
View File

@@ -0,0 +1,45 @@
module std::net::tcp @if(os::SUPPORTS_INET);
import libc;
def TcpSocket = distinct inline Socket;
def TcpServerSocket = distinct inline Socket;
fn TcpSocket! connect(String host, uint port, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_STREAM)!;
defer os::freeaddrinfo(ai);
return connect_to(ai, ...options);
}
fn TcpSocket! connect_to(AddrInfo* ai, SocketOption... options)
{
return (TcpSocket)net::_connect(ai, options);
}
fn TcpServerSocket! listen(String host, uint port, uint backlog, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_STREAM)!;
defer os::freeaddrinfo(ai);
return listen_to(ai, backlog, ...options);
}
fn TcpSocket! accept(TcpServerSocket* server_socket)
{
TcpSocket socket;
socket.sock = os::accept(server_socket.sock, (SockAddrPtr)&socket.ai_addr_storage, &socket.ai_addrlen);
if (socket.sock < 0) return NetError.ACCEPT_FAILED?;
return socket;
}
fn TcpServerSocket! listen_to(AddrInfo* ai, uint backlog, SocketOption... options)
{
net::@loop_over_ai(ai; NativeSocket sockfd, AddrInfo* ai_candidate)
{
net::apply_sockoptions(sockfd, options)!;
bool err = os::bind(sockfd, ai_candidate.ai_addr, ai_candidate.ai_addrlen) || os::listen(sockfd, backlog);
if (!err) return (TcpServerSocket)net::network_socket(sockfd, ai_candidate);
};
return os::socket_error()?;
}

15
lib/std/net/udp.c3 Normal file
View File

@@ -0,0 +1,15 @@
module std::net::udp @if(os::SUPPORTS_INET);
def UdpSocket = distinct inline Socket;
fn UdpSocket! connect(String host, uint port, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_DGRAM)!;
defer os::freeaddrinfo(ai);
return connect_to(ai, ...options);
}
fn UdpSocket! connect_to(AddrInfo* ai, SocketOption... options)
{
return (UdpSocket)net::_connect(ai, options);
}

View File

@@ -2,30 +2,105 @@ module std::os::win32 @if(env::WIN32);
def WSAError = distinct int;
extern fn WSAError win32_WSAGetLastError() @extern("WSAGetLastError");
extern fn void win32_WSASetLastError(WSAError error) @extern("WSASetLastError");
extern fn WSAError win32_WSAGetLastError() @extern("WSAGetLastError") @builtin;
extern fn void win32_WSASetLastError(WSAError error) @extern("WSASetLastError") @builtin;
extern fn CInt win32_WSAStartup(Win32_WORD, void*) @extern("WSAStartup") @builtin;
module std::os::win32::wsa @if(env::WIN32);
const WSAError INVALID_HANDLE = 6;
const WSAError NOT_ENOUGHT_MEMORY = 8;
const WSAError INVALID_PARAMETER = 87;
const WSAError OPERATION_ABORTED = 995;
const WSAError IO_INCOMPLETE = 996;
const WSAError IO_PENDING = 997;
const WSAError EINTR = 10004;
const WSAError EBADF = 10009;
const WSAError ACCESS = 10013;
const WSAError EFAULT = 10014;
const WSAError EINVAL = 10022;
const WSAError EMFILE = 10024;
const WSAError EWOULDBLOCK = 10035;
const WSAError EINPROGRESS = 10036;
const WSAError EALREADY = 10037;
const WSAError ENOTSOCK = 10038;
const WSAError EDESTADDRREQ = 10039;
const WSAError EMSGSIZE = 10040;
const WSAError EPROTOTYPE = 10041;
const WSAError ENOPROTOOPT = 10042;
const WSAError EPROTONOSUPPORT = 10043;
const WSAError ESOCKTNOSUPPORT = 10044;
const WSAError NO_ERROR = 0;
const WSAError INVALID_HANDLE = 6;
const WSAError NOT_ENOUGH_MEMORY = 8;
const WSAError INVALID_PARAMETER = 87;
const WSAError OPERATION_ABORTED = 995;
const WSAError IO_INCOMPLETE = 996;
const WSAError IO_PENDING = 997;
const WSAError EINTR = 10004;
const WSAError EBADF = 10009;
const WSAError EACCESS = 10013;
const WSAError EFAULT = 10014;
const WSAError EINVAL = 10022;
const WSAError EMFILE = 10024;
const WSAError EWOULDBLOCK = 10035;
const WSAError EINPROGRESS = 10036;
const WSAError EALREADY = 10037;
const WSAError ENOTSOCK = 10038;
const WSAError EDESTADDRREQ = 10039;
const WSAError EMSGSIZE = 10040;
const WSAError EPROTOTYPE = 10041;
const WSAError ENOPROTOOPT = 10042;
const WSAError EPROTONOSUPPORT = 10043;
const WSAError ESOCKTNOSUPPORT = 10044;
const WSAError EOPNOTSUPP = 10045;
const WSAError EPFNOSUPPORT = 10046;
const WSAError EAFNOSUPPORT = 10047;
const WSAError EADDRINUSE = 10048;
const WSAError EADDRNOTAVAIL = 10049;
const WSAError ENETDOWN = 10050;
const WSAError ENETUNREACH = 10051;
const WSAError ENETRESET = 10052;
const WSAError ECONNABORTED = 10053;
const WSAError ECONNRESET = 10054;
const WSAError ENOBUFS = 10055;
const WSAError EISCONN = 10056;
const WSAError ENOTCONN = 10057;
const WSAError ESHUTDOWN = 10058;
const WSAError ETOOMANYREFS = 10059;
const WSAError ETIMEDOUT = 10060;
const WSAError ECONNREFUSED = 10061;
const WSAError ELOOP = 10062;
const WSAError ENAMETOOLONG = 10063;
const WSAError EHOSTDOWN = 10064;
const WSAError EHOSTUNREACH = 10065;
const WSAError ENOTEMPTY = 10066;
const WSAError EPROCLIM = 10067;
const WSAError EUSERS = 10068;
const WSAError EDQUOT = 10069;
const WSAError ESTALE = 10070;
const WSAError EREMOTE = 10071;
const WSAError SYSNOTREADY = 10091;
const WSAError VERNOTSUPPORTED = 10092;
const WSAError NOTINITIALISED = 10093;
const WSAError EDISCON = 10101;
const WSAError ENOMORE = 10102;
const WSAError ECANCELLED = 10103;
const WSAError EINVALIDPROCTABLE = 10104;
const WSAError EINVALIDPROVIDER = 10105;
const WSAError EPROVIDERFAILEDINIT = 10106;
const WSAError SYSCALLFAILURE = 10107;
const WSAError SERVICE_NOT_FOUND = 10108;
const WSAError TYPE_NOT_FOUND = 10109;
const WSAError E_NO_MORE = 10110;
const WSAError E_CANCELLED = 10111;
const WSAError REFUSED = 10112;
const WSAError HOST_NOT_FOUND = 11001;
const WSAError TRY_AGAIN = 11002;
const WSAError NO_RECOVERY = 11003;
const WSAError NO_DATA = 11004;
const WSAError QOS_RECEIVERS = 11005;
const WSAError QOS_SENDERS = 11006;
const WSAError QOS_NO_SENDERS = 11007;
const WSAError QOS_NO_RECEIVERS = 11008;
const WSAError QOS_REQUEST_CONFIRMED = 11009;
const WSAError QOS_ADMISSION_FAILURE = 11010;
const WSAError QOS_POLICY_FAILURE = 11011;
const WSAError QOS_BAD_STYLE = 11012;
const WSAError QOS_BAD_OBJECT = 11013;
const WSAError QOS_TRAFFIC_CTRL_ERROR = 11014;
const WSAError QOS_GENERIC_ERROR = 11015;
const WSAError QOS_ESERVICETYPE = 11016;
const WSAError QOS_EFLOWSPEC = 11017;
const WSAError QOS_EPROVSPECBUF = 11018;
const WSAError QOS_EFILTERSTYLE = 11019;
const WSAError QOS_EFILTERTYPE = 11020;
const WSAError QOS_EFILTERCOUNT = 11021;
const WSAError QOS_EOBJLENGTH = 11022;
const WSAError QOS_EFLOWCOUNT = 11023;
const WSAError QOS_EUNKOWNPSOBJ = 11024;
const WSAError QOS_EPOLICYOBJ = 11025;
const WSAError QOS_EFLOWDESC = 11026;
const WSAError QOS_EPSFLOWSPEC = 11027;
const WSAError QOS_EPSFILTERSPEC = 11028;
const WSAError QOS_ESDMODEOBJ = 11029;
const WSAError QOS_ESHAPERATEOBJ = 11030;
const WSAError QOS_RESERVED_PETYPE = 11031;

View File

@@ -164,7 +164,7 @@ fn double DateTime.diff_sec(self, DateTime from)
{
return (double)self.time.diff_us(from.time) / (double)time::MICROSECONDS_PER_SECOND;
}
fn TimeDuration DateTime.diff_us(self, DateTime from)
fn Duration DateTime.diff_us(self, DateTime from)
{
return self.time.diff_us(from.time);
}

View File

@@ -1,15 +1,15 @@
module std::time;
def Time = distinct long @inline;
def TimeDuration = distinct long @inline;
def Duration = distinct long @inline;
def Clock = distinct ulong @inline;
def NanoDuration = distinct long @inline;
const TimeDuration MICROSECONDS_PER_SECOND = 1_000_000;
const TimeDuration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60;
const TimeDuration MICROSECONDS_PER_HOUR = MICROSECONDS_PER_MINUTE * 60;
const TimeDuration MICROSECONDS_PER_DAY = MICROSECONDS_PER_HOUR * 24;
const TimeDuration MICROSECONDS_PER_WEEK = MICROSECONDS_PER_DAY * 7;
const Duration MICROSECONDS_PER_SECOND = 1_000_000;
const Duration MICROSECONDS_PER_MINUTE = MICROSECONDS_PER_SECOND * 60;
const Duration MICROSECONDS_PER_HOUR = MICROSECONDS_PER_MINUTE * 60;
const Duration MICROSECONDS_PER_DAY = MICROSECONDS_PER_HOUR * 24;
const Duration MICROSECONDS_PER_WEEK = MICROSECONDS_PER_DAY * 7;
struct DateTime
{
@@ -74,7 +74,7 @@ fn Time Time.add_hours(time, long hours) => time + (Time)(hours * (long)MICROSEC
fn Time Time.add_days(time, long days) => time + (Time)(days * (long)MICROSECONDS_PER_DAY);
fn Time Time.add_weeks(time, long weeks) => time + (Time)(weeks * (long)MICROSECONDS_PER_WEEK);
fn double Time.to_seconds(time) => (long)time / (double)MICROSECONDS_PER_SECOND;
fn TimeDuration Time.diff_us(time, Time other) => (TimeDuration)(time - other);
fn Duration Time.diff_us(time, Time other) => (Duration)(time - other);
fn double Time.diff_sec(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_SECOND;
fn double Time.diff_min(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_MINUTE;
fn double Time.diff_hour(time, Time other) => (long)time.diff_us(other) / (double)MICROSECONDS_PER_HOUR;
@@ -83,8 +83,8 @@ fn double Time.diff_weeks(time, Time other) => (long)time.diff_us(other) / (doub
fn double NanoDuration.to_sec(nd) => (double)nd / 1_000_000_000.0;
fn long NanoDuration.to_ms(nd) => (long)nd / 1_000_000;
fn TimeDuration NanoDuration.to_duration(nd) => (TimeDuration)nd / 1_000;
fn NanoDuration TimeDuration.to_nano(td) => (NanoDuration)td * 1_000;
fn Duration NanoDuration.to_duration(nd) => (Duration)nd / 1_000;
fn NanoDuration Duration.to_nano(td) => (NanoDuration)td * 1_000;
fn void! NanoDuration.to_format(&self, Formatter* formatter) @dynamic
{