Removal of old Network, added nonblocking set and async connect.

This commit is contained in:
Christoffer Lerno
2023-09-02 17:39:47 +02:00
parent e56313a204
commit a6cff5c2a5
9 changed files with 211 additions and 223 deletions

View File

@@ -1,104 +0,0 @@
module std::net;
const IPPPOTO_IP = 0;
const IPPROTO_ICMP = 1;
const IPPROTO_IGMP = 2;
const IPPROTO_IPV4 = 4;
const IPPROTO_TCP = 6;
const IPPROTO_ST = 7;
const IPPROTO_EGP = 8;
const IPPROTO_PIGP = 9;
const IPPROTO_RCCMON = 10;
const IPPROTO_NVPII = 11;
const IPPROTO_PUP = 12;
const IPPROTO_ARGUS = 13;
const IPPROTO_EMCON = 14;
const IPPROTO_XNET = 15;
const IPPROTO_CHAOS = 16;
const IPPROTO_UDP = 17;
const IPPROTO_MUX = 18;
const IPPROTO_MEAS = 19;
const IPPROTO_HMP = 20;
const IPPROTO_PRM = 21;
const IPPROTO_IDP = 22;
const IPPROTO_TRUNK1 = 23;
const IPPROTO_TRUNK2 = 24;
const IPPROTO_LEAF1 = 25;
const IPPROTO_LEAF2 = 26;
const IPPROTO_RDP = 27;
const IPPROTO_IRTP = 28;
const IPPROTO_TP = 29;
const IPPROTO_BLT = 30;
const IPPROTO_NSP = 31;
const IPPROTO_INP = 32;
const IPPROTO_SEP = 33;
const IPPROTO_3PC = 34;
const IPPROTO_IDPR = 35;
const IPPROTO_XTP = 36;
const IPPROTO_DDP = 37;
const IPPROTO_CMTP = 38;
const IPPROTO_TPXX = 39;
const IPPROTO_IL = 40;
const IPPROTO_IPV6 = 41;
const IPPROTO_SDRP = 42;
const IPPROTO_ROUTING = 43;
const IPPROTO_FRAGMENT = 44;
const IPPROTO_IDRP = 45;
const IPPROTO_RSVP = 46;
const IPPROTO_GRE = 47;
const IPPROTO_MHRP = 48;
const IPPROTO_BHA = 49;
const IPPROTO_ESP = 50;
const IPPROTO_AH = 51;
const IPPROTO_INLSP = 52;
const IPPROTO_SWIPE = 53;
const IPPROTO_NHRP = 54;
const IPPROTO_ICMPV6 = 58;
const IPPROTO_NONE = 59;
const IPPROTO_DSTOPTS = 60;
const IPPROTO_AHIP = 61;
const IPPROTO_CFTP = 62;
const IPPROTO_HELLO = 63;
const IPPROTO_SATEXPAK = 64;
const IPPROTO_KRYPTOLAN = 65;
const IPPROTO_RVD = 66;
const IPPROTO_IPPC = 67;
const IPPROTO_ADFS = 68;
const IPPROTO_SATMON = 69;
const IPPROTO_VISA = 70;
const IPPROTO_IPCV = 71;
const IPPROTO_CPNX = 72;
const IPPROTO_CPHB = 73;
const IPPROTO_WSN = 74;
const IPPROTO_PVP = 75;
const IPPROTO_BRSATMON = 76;
const IPPROTO_ND = 77;
const IPPROTO_WBMON = 78;
const IPPROTO_WBEXPAK = 79;
const IPPROTO_EON = 80;
const IPPROTO_VMTP = 81;
const IPPROTO_SVMTP = 82;
const IPPROTO_VINES = 83;
const IPPROTO_TTP = 84;
const IPPROTO_IGP = 85;
const IPPROTO_DGP = 86;
const IPPROTO_TCF = 87;
const IPPROTO_IGRP = 88;
const IPPROTO_OSPFIGP = 89;
const IPPROTO_SRPC = 90;
const IPPROTO_LARP = 91;
const IPPROTO_MTP = 92;
const IPPROTO_AX25 = 93;
const IPPROTO_IPEIP = 94;
const IPPROTO_MICP = 95;
const IPPROTO_SCCSP = 96;
const IPPROTO_ETHERIP = 97;
const IPPROTO_ENCAP = 98;
const IPPROTO_APES = 99;
const IPPROTO_GMTP = 100;
const IPPROTO_PIM = 103;
const IPPROTO_IPCOMP = 108;
const IPPROTO_PGM = 113;
const IPPROTO_SCTP = 132;
const IPPROTO_DIVERT = 254;
const IPPROTO_RAW = 255;

View File

@@ -63,3 +63,106 @@ 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;
const IPPPOTO_IP = 0;
const IPPROTO_ICMP = 1;
const IPPROTO_IGMP = 2;
const IPPROTO_IPV4 = 4;
const IPPROTO_TCP = 6;
const IPPROTO_ST = 7;
const IPPROTO_EGP = 8;
const IPPROTO_PIGP = 9;
const IPPROTO_RCCMON = 10;
const IPPROTO_NVPII = 11;
const IPPROTO_PUP = 12;
const IPPROTO_ARGUS = 13;
const IPPROTO_EMCON = 14;
const IPPROTO_XNET = 15;
const IPPROTO_CHAOS = 16;
const IPPROTO_UDP = 17;
const IPPROTO_MUX = 18;
const IPPROTO_MEAS = 19;
const IPPROTO_HMP = 20;
const IPPROTO_PRM = 21;
const IPPROTO_IDP = 22;
const IPPROTO_TRUNK1 = 23;
const IPPROTO_TRUNK2 = 24;
const IPPROTO_LEAF1 = 25;
const IPPROTO_LEAF2 = 26;
const IPPROTO_RDP = 27;
const IPPROTO_IRTP = 28;
const IPPROTO_TP = 29;
const IPPROTO_BLT = 30;
const IPPROTO_NSP = 31;
const IPPROTO_INP = 32;
const IPPROTO_SEP = 33;
const IPPROTO_3PC = 34;
const IPPROTO_IDPR = 35;
const IPPROTO_XTP = 36;
const IPPROTO_DDP = 37;
const IPPROTO_CMTP = 38;
const IPPROTO_TPXX = 39;
const IPPROTO_IL = 40;
const IPPROTO_IPV6 = 41;
const IPPROTO_SDRP = 42;
const IPPROTO_ROUTING = 43;
const IPPROTO_FRAGMENT = 44;
const IPPROTO_IDRP = 45;
const IPPROTO_RSVP = 46;
const IPPROTO_GRE = 47;
const IPPROTO_MHRP = 48;
const IPPROTO_BHA = 49;
const IPPROTO_ESP = 50;
const IPPROTO_AH = 51;
const IPPROTO_INLSP = 52;
const IPPROTO_SWIPE = 53;
const IPPROTO_NHRP = 54;
const IPPROTO_ICMPV6 = 58;
const IPPROTO_NONE = 59;
const IPPROTO_DSTOPTS = 60;
const IPPROTO_AHIP = 61;
const IPPROTO_CFTP = 62;
const IPPROTO_HELLO = 63;
const IPPROTO_SATEXPAK = 64;
const IPPROTO_KRYPTOLAN = 65;
const IPPROTO_RVD = 66;
const IPPROTO_IPPC = 67;
const IPPROTO_ADFS = 68;
const IPPROTO_SATMON = 69;
const IPPROTO_VISA = 70;
const IPPROTO_IPCV = 71;
const IPPROTO_CPNX = 72;
const IPPROTO_CPHB = 73;
const IPPROTO_WSN = 74;
const IPPROTO_PVP = 75;
const IPPROTO_BRSATMON = 76;
const IPPROTO_ND = 77;
const IPPROTO_WBMON = 78;
const IPPROTO_WBEXPAK = 79;
const IPPROTO_EON = 80;
const IPPROTO_VMTP = 81;
const IPPROTO_SVMTP = 82;
const IPPROTO_VINES = 83;
const IPPROTO_TTP = 84;
const IPPROTO_IGP = 85;
const IPPROTO_DGP = 86;
const IPPROTO_TCF = 87;
const IPPROTO_IGRP = 88;
const IPPROTO_OSPFIGP = 89;
const IPPROTO_SRPC = 90;
const IPPROTO_LARP = 91;
const IPPROTO_MTP = 92;
const IPPROTO_AX25 = 93;
const IPPROTO_IPEIP = 94;
const IPPROTO_MICP = 95;
const IPPROTO_SCCSP = 96;
const IPPROTO_ETHERIP = 97;
const IPPROTO_ENCAP = 98;
const IPPROTO_APES = 99;
const IPPROTO_GMTP = 100;
const IPPROTO_PIM = 103;
const IPPROTO_IPCOMP = 108;
const IPPROTO_PGM = 113;
const IPPROTO_SCTP = 132;
const IPPROTO_DIVERT = 254;
const IPPROTO_RAW = 255;

View File

@@ -43,10 +43,20 @@ macro void! NativeSocket.close(self)
}
}
macro void! NativeSocket.set_non_blocking(self)
macro void! NativeSocket.set_non_blocking(self, bool non_blocking)
{
int flags = fcntl(self, F_GETFL, 0);
if (fcntl(self, F_SETFL, flags | O_NONBLOCK) == -1)
if (non_blocking)
{
if (flags & O_NONBLOCK) return;
flags |= O_NONBLOCK;
}
else
{
if (!(flags & O_NONBLOCK)) return;
flags &= ~(int)O_NONBLOCK;
}
if (fcntl(self, F_SETFL, flags) == -1)
{
if (libc::errno() == errno::EBADF) return NetError.INVALID_SOCKET?;
return NetError.GENERAL_ERROR?;

View File

@@ -19,6 +19,14 @@ 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);
fn void! NativeSocket.set_non_blocking(self, bool non_blocking)
{
if (ioctlsocket(self, win32::FIONBIO, &&(ulong)non_blocking))
{
return socket_error()?;
}
}
macro void! NativeSocket.close(self)
{
WSAError error = closesocket(self);

View File

@@ -2,16 +2,6 @@ module std::net @if(os::SUPPORTS_INET);
import std::io;
import libc;
enum Network : char (AIFamily domain, AISockType type)
{
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;
@@ -21,64 +11,6 @@ struct Socket
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)
{
apply_sockoptions(sockfd, options)!;
int errcode = os::connect(sockfd, ai.ai_addr, ai.ai_addrlen);
// Keep the first successful connection.
if (errcode == 0) return network_socket(sockfd, ai);
}!;
return os::socket_error()?;
}
fn Socket! Network.listen(&self, String host, String port, int backlog, SocketOption... options)
{
@network_loop_over_ai(self, host, port; NativeSocket sockfd, AddrInfo* ai)
{
apply_sockoptions(sockfd, options)!;
int errcode = os::bind(sockfd, ai.ai_addr, ai.ai_addrlen);
if (errcode == 0)
{
errcode = os::listen(sockfd, backlog);
// Keep the first successful connection.
if (errcode == 0) return network_socket(sockfd, ai);
}
}!;
return os::socket_error()?;
}
fn AddrInfo*! Network.addrinfo(&self, String host, String port) @private
{
ZString zhost = host.zstr_tcopy();
ZString zport = port.zstr_tcopy();
AddrInfo hints = { .ai_family = self.domain, .ai_socktype = self.type };
AddrInfo* ai;
int errcode = os::getaddrinfo(zhost, zport, &hints, &ai);
if (errcode != 0) return NetError.ADDRINFO_FAILED?;
return ai;
}
macro apply_sockoptions(sockfd, options)
{
Socket sock = { .sock = sockfd };
foreach (o : options) sock.set_option(o, true)!;
}
macro void @loop_over_ai(AddrInfo* ai; @body(NativeSocket fd, AddrInfo* ai))
{
while (ai)
@@ -92,22 +24,6 @@ macro void @loop_over_ai(AddrInfo* ai; @body(NativeSocket fd, AddrInfo* ai))
}
}
macro @network_loop_over_ai(network, host, port; @body(fd, ai)) @private
{
AddrInfo* ai = network.addrinfo(host, port)!;
AddrInfo* first = ai;
defer os::freeaddrinfo(first);
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 Socket network_socket(fd, ai)
{
Socket sock = { .sock = fd, .ai_addrlen = ai.ai_addrlen };
@@ -126,8 +42,6 @@ enum SocketOption : char (CInt value)
DONTROUTE (os::SO_DONTROUTE),
}
fn Stream Socket.as_stream(&self)
{
return { .fns = &socketstream_interface, .data = self };
@@ -158,12 +72,6 @@ fn void! Socket.set_option(&self, SocketOption option, bool value)
if (errcode != 0) return NetError.SOCKOPT_FAILED?;
}
macro void! @set_option_value(NativeSocket sock, CInt option, value)
{
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;
@@ -190,26 +98,3 @@ fn void! Socket.close(&self) @inline
{
self.sock.close()!;
}
struct Listener
{
Socket socket;
}
fn void! Listener.init(&self, Network network, String host, String port, int backlog = 10, SocketOption... options)
{
*self = { .socket = network.listen(host, port, backlog, ...options)! };
}
fn Socket! Listener.accept(&self)
{
Socket sock = self.socket;
sock.sock = os::accept(sock.sock, (SockAddrPtr)&sock.ai_addr_storage, &sock.ai_addrlen);
if (sock.sock < 0) return NetError.ACCEPT_FAILED?;
return sock;
}
fn void! Listener.close(&self) @inline
{
self.socket.close()!;
}

View File

@@ -0,0 +1,68 @@
module std::net @if(os::SUPPORTS_INET);
import libc;
macro apply_sockoptions(sockfd, options) @private
{
Socket sock = { .sock = sockfd };
foreach (o : options) sock.set_option(o, true)!;
}
fn Socket! connect_from_addrinfo(AddrInfo* addrinfo, SocketOption[] options) @private
{
@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 bool last_error_is_delayed_connect()
{
$switch
$case env::WIN32:
switch (win32_WSAGetLastError())
{
case wsa::EWOULDBLOCK:
case wsa::EINPROGRESS: return true;
default: return false;
}
$default:
Errno err = libc::errno();
return err == errno::EINPROGRESS || err == errno::EAGAIN || err == errno::EWOULDBLOCK;
$endswitch
}
fn Socket! connect_async_from_addrinfo(AddrInfo* addrinfo, SocketOption[] options) @private
{
@loop_over_ai(addrinfo; NativeSocket sockfd, AddrInfo* ai)
{
apply_sockoptions(sockfd, options)!;
sockfd.set_non_blocking(true)!;
int errcode = os::connect(sockfd, ai.ai_addr, ai.ai_addrlen);
if (!errcode || last_error_is_delayed_connect())
{
// Keep the first successful connection.
return network_socket(sockfd, ai);
}
};
return os::socket_error()?;
}
macro @network_loop_over_ai(network, host, port; @body(fd, ai)) @private
{
AddrInfo* ai = network.addrinfo(host, port)!;
AddrInfo* first = ai;
defer os::freeaddrinfo(first);
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;
}
}

View File

@@ -1,4 +1,5 @@
module std::net::tcp @if(os::SUPPORTS_INET);
import std::net @public;
import libc;
def TcpSocket = distinct inline Socket;
@@ -11,9 +12,21 @@ fn TcpSocket! connect(String host, uint port, SocketOption... options, IpProtoco
return connect_to(ai, ...options);
}
fn TcpSocket! connect_async(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_async_to(ai, ...options);
}
fn TcpSocket! connect_to(AddrInfo* ai, SocketOption... options)
{
return (TcpSocket)net::_connect(ai, options);
return (TcpSocket)net::connect_from_addrinfo(ai, options);
}
fn TcpSocket! connect_async_to(AddrInfo* ai, SocketOption... options)
{
return (TcpSocket)net::connect_async_from_addrinfo(ai, options);
}
fn TcpServerSocket! listen(String host, uint port, uint backlog, SocketOption... options, IpProtocol protocol = UNSPECIFIED)

View File

@@ -1,4 +1,5 @@
module std::net::udp @if(os::SUPPORTS_INET);
import std::net @public;
def UdpSocket = distinct inline Socket;
@@ -11,5 +12,5 @@ fn UdpSocket! connect(String host, uint port, SocketOption... options, IpProtoco
fn UdpSocket! connect_to(AddrInfo* ai, SocketOption... options)
{
return (UdpSocket)net::_connect(ai, options);
return (UdpSocket)net::connect_from_addrinfo(ai, options);
}

View File

@@ -6,6 +6,10 @@ 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;
const int FIONBIO = -2147195266;
const int FIONREAD = 1074030207;
const int SIOCATMARK = 1074033415;
module std::os::win32::wsa @if(env::WIN32);
const WSAError NO_ERROR = 0;