Files
c3c/lib/std/net/socket_private.c3
Christoffer Lerno 9a6d83f526 Updated stream API.
2023-09-03 01:14:15 +02:00

69 lines
1.7 KiB
C

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 new_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 new_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;
}
}