class TestCase::Sys::Socket {
use Sys;
use Sys::Socket;
use Sys::Socket::Constant as SOCKET;
use Sys::Socket::Sockaddr;
use Sys::Socket::Sockaddr::In;
use Sys::Socket::Sockaddr::In6;
use Sys::Socket::Addrinfo;
use Sys::Socket::AddrinfoLinkedList;
use Sys::Socket::Sockaddr::Storage;
use Sys::Socket::Sockaddr::Un;
use Sys::Process;
use Sys::IO::Constant as IO;
use Sys::Ioctl::Constant as IOCTL;
use Sys::Socket::Util;
use Sys::Socket::Error::InetInvalidNetworkAddress;
use Fn;
static method htonl : int () {
my $host_int = 20000;
my $net_int = Sys::Socket->htonl($host_int);
my $host_int_again = Sys::Socket->ntohl($net_int);
warn "\n[Test Output]htonl:$host_int -> $net_int -> $host_int_again";
if ($host_int == $net_int) {
return 0;
}
unless ($host_int == $host_int_again) {
return 0;
}
return 1;
}
static method ntohl : int () {
my $net_int = 541982720;
my $host_int = Sys::Socket->ntohl($net_int);
my $net_int_again = Sys::Socket->htonl($host_int);
warn "\n[Test Output]ntohl:$net_int -> $host_int -> $net_int_again";
if ($net_int == $host_int) {
return 0;
}
unless ($net_int == $net_int_again) {
return 0;
}
return 1;
}
static method htons : int () {
{
my $host_short = (short)20000;
my $net_short = Sys::Socket->htons((short)$host_short);
my $host_short_again = Sys::Socket->ntohs((short)$net_short);
warn "\n[Test Output]htons:$host_short -> $net_short -> $host_short_again";
if ($host_short == $net_short) {
return 0;
}
unless ($host_short == $host_short_again) {
return 0;
}
}
{
my $host_short = (short)50000;
my $net_short = Sys::Socket->htons((short)$host_short);
my $host_short_again = Sys::Socket->ntohs((short)$net_short);
warn "\n[Test Output]htons:$host_short -> $net_short -> $host_short_again";
if ($host_short == $net_short) {
return 0;
}
unless ($host_short == $host_short_again) {
return 0;
}
}
return 1;
}
static method ntohs : int () {
{
my $net_short = (short)8270;
my $host_short = Sys::Socket->ntohs((short)$net_short);
my $net_short_again = Sys::Socket->htons((short)$host_short);
warn "\n[Test Output]ntohs:$net_short -> $host_short -> $net_short_again";
if ($net_short == $host_short) {
return 0;
}
unless ($net_short == $net_short_again) {
return 0;
}
}
{
my $net_short = (short)20675;
my $host_short = Sys::Socket->ntohs((short)$net_short);
my $net_short_again = Sys::Socket->htons((short)$host_short);
warn "\n[Test Output]ntohs:$net_short -> $host_short -> $net_short_again";
if ($net_short == $host_short) {
return 0;
}
unless ($net_short == $net_short_again) {
return 0;
}
}
return 1;
}
static method inet_aton : int () {
{
my $in_addr = Sys::Socket::In_addr->new;
my $status = Sys::Socket->inet_aton("127.0.0.1", $in_addr);
unless ($status == 1) {
return 0;
}
}
{
my $in_addr = Sys::Socket::In_addr->new;
my $status = Sys::Socket->inet_aton("0.0.0.0", $in_addr);
unless ($status == 1) {
return 0;
}
unless ($in_addr->s_addr == 0) {
return 0;
}
}
return 1;
}
static method inet_ntoa : int () {
{
my $in_addr = Sys::Socket::In_addr->new;
my $status = Sys::Socket->inet_aton("127.0.0.1", $in_addr);
unless ($status == 1) {
return 0;
}
my $address = Sys::Socket->inet_ntoa($in_addr);
unless ($address eq "127.0.0.1") {
return 0;
}
}
{
my $in_addr = Sys::Socket::Util->inet_aton("127.0.0.1");
my $address = Sys::Socket->inet_ntoa($in_addr);
unless ($address eq "127.0.0.1") {
return 0;
}
}
return 1;
}
static method inet_pton : int () {
{
my $in_addr = Sys::Socket::In_addr->new;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
unless ($status == 1) {
return 0;
}
if ($in_addr->s_addr == 0) {
return 0;
}
}
{
my $in_addr = Sys::Socket::In_addr->new;
$in_addr->set_s_addr(1);
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET, "0.0.0.0", $in_addr);
unless ($status == 1) {
return 0;
}
unless ($in_addr->s_addr == 0) {
return 0;
}
}
{
my $in6_addr = Sys::Socket::In6_addr->new;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET6, "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", $in6_addr);
unless ($status == 1) {
return 0;
}
if ($in6_addr->s6_addr eq "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") {
return 0;
}
}
{
my $in6_addr = Sys::Socket::In6_addr->new;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET6, "::1", $in6_addr);
unless ($status == 1) {
return 0;
}
unless ($in6_addr->s6_addr eq "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1") {
return 0;
}
}
{
my $in6_addr = Sys::Socket::In6_addr->new;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET6, "::0", $in6_addr);
unless ($status == 1) {
return 0;
}
unless ($in6_addr->s6_addr eq "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") {
return 0;
}
}
return 1;
}
static method inet_ntop : int () {
{
my $in_addr = Sys::Socket::In_addr->new;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
unless ($status == 1) {
return 0;
}
my $buffer = (mutable string)new_string_len SOCKET->INET_ADDRSTRLEN;
my $address = Sys::Socket->inet_ntop(SOCKET->AF_INET, $in_addr, $buffer, SOCKET->INET_ADDRSTRLEN);
unless ($address) {
return 0;
}
Fn->shorten_null_char($address);
unless ($address eq "127.0.0.1") {
return 0;
}
}
{
my $in6_addr = Sys::Socket::In6_addr->new;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET6, "abcd:ef01:2345:6789:abcd:ef01:2345:6789", $in6_addr);
unless ($status == 1) {
return 0;
}
my $buffer = (mutable string)new_string_len SOCKET->INET6_ADDRSTRLEN;
my $address = Sys::Socket->inet_ntop(SOCKET->AF_INET6, $in6_addr, $buffer, SOCKET->INET6_ADDRSTRLEN);
unless ($address) {
return 0;
}
Fn->shorten_null_char($address);
unless ($address eq "abcd:ef01:2345:6789:abcd:ef01:2345:6789") {
return 0;
}
}
{
my $in6_addr = Sys::Socket::Util->inet_pton(SOCKET->AF_INET6, "abcd:ef01:2345:6789:abcd:ef01:2345:6789");
my $buffer = (mutable string)new_string_len SOCKET->INET6_ADDRSTRLEN;
my $address = Sys::Socket->inet_ntop(SOCKET->AF_INET6, $in6_addr, $buffer, SOCKET->INET6_ADDRSTRLEN);
unless ($address) {
return 0;
}
Fn->shorten_null_char($address);
unless ($address eq "abcd:ef01:2345:6789:abcd:ef01:2345:6789") {
return 0;
}
}
return 1;
}
static method socket : int () {
# IPv4/TCP
{
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
}
# IPv4/UDP
{
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_DGRAM, 0);
unless ($socket> 0) {
return 0;
}
}
# IPv6/TCP
{
my $socket = Sys::Socket->socket(SOCKET->AF_INET6, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
}
# IPv6/UDP
{
my $socket = Sys::Socket->socket(SOCKET->AF_INET6, SOCKET->SOCK_DGRAM, 0);
unless ($socket> 0) {
return 0;
}
}
# IPv4/TCP
{
my $socket = -1;
Sys->socket(\$socket, SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket > 0) {
return 0;
}
}
return 1;
}
static method sockaddr : int ($port : int) {
# IPv4
{
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
my $status = Sys::Socket->inet_aton("127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
unless ($status == 1) {
return 0;
}
}
# IPv4
{
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
unless ($status == 1) {
return 0;
}
}
# IPv6
{
my $sockaddr = Sys::Socket::Sockaddr::In6->new;
$sockaddr->set_sin6_family((byte)SOCKET->AF_INET6);
$sockaddr->set_sin6_port(Sys::Socket->htons((short)$port));
my $in6_addr = $sockaddr->sin6_addr;
my $status = Sys::Socket->inet_pton(SOCKET->AF_INET6, "::1", $in6_addr);
$sockaddr->set_sin6_addr($in6_addr);
unless ($status == 1) {
return 0;
}
}
return 1;
}
static method connect : int ($port : int) {
# IPv4 address
{
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
my $in_addr = Sys::Socket::Util->inet_aton("127.0.0.1");
my $sockaddr_in = Sys::Socket::Util->sockaddr_in($port, $in_addr);
Sys->connect($socket, $sockaddr_in);
my $status_close = Sys::Socket->close($socket);
unless ($status_close == 0) {
return 0;
}
}
# Exception
{
# AF_INET6 is wrong setting
my $socket = Sys::Socket->socket(SOCKET->AF_INET6, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
my $in_addr = Sys::Socket::Util->inet_aton("127.0.0.1");
my $sockaddr_in = Sys::Socket::Util->sockaddr_in($port, $in_addr);
eval { Sys->connect($socket, $sockaddr_in); }
unless ($@) {
return 0;
}
unless (eval_error_id is_error Error::System) {
return 0;
}
}
return 1;
}
static method connect_ipv6 : int ($port : int) {
# IPv6 address
{
my $socket = Sys::Socket->socket(SOCKET->AF_INET6, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
my $in6_addr = (Sys::Socket::In6_addr)Sys::Socket::Util->inet_pton(SOCKET->AF_INET6, "::1");
my $sockaddr_in6 = Sys::Socket::Util->sockaddr_in6($port, $in6_addr);
Sys->connect($socket, $sockaddr_in6);
my $status_close = Sys::Socket->close($socket);
unless ($status_close == 0) {
return 0;
}
}
return 1;
}
static method close : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $status_connect = Sys::Socket->connect($socket, $sockaddr, $sockaddr->size);
unless ($status_connect == 0) {
return 0;
}
my $status_close = Sys::Socket->close($socket);
unless ($status_close == 0) {
return 0;
}
return 1;
}
static method shutdown : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $status_connect = Sys::Socket->connect($socket, $sockaddr, $sockaddr->size);
unless ($status_connect == 0) {
return 0;
}
Sys->shutdown($socket, SOCKET->SHUT_WR);
my $status_close = Sys::Socket->close($socket);
unless ($status_close == 0) {
return 0;
}
return 1;
}
static method send_and_recv : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $status_connect = Sys::Socket->connect($socket, $sockaddr, $sockaddr->size);
unless ($status_connect == 0) {
Sys::Socket->close($socket);
return 0;
}
{
my $send_buffer = "abcd";
my $send_length = Sys->send($socket, $send_buffer, 0);
unless ($send_length == 4) {
return 0;
}
}
{
my $send_buffer = "ef";
my $send_length = Sys::Socket->send($socket, $send_buffer, length $send_buffer, 0);
unless ($send_length == 2) {
return 0;
}
}
my $status_shutdown = Sys::Socket->shutdown($socket, SOCKET->SHUT_WR);
unless ($status_shutdown == 0) {
return 0;
}
my $recv_string_buffer = StringBuffer->new;
while (1) {
my $recv_buffer = (mutable string)new_string_len 1024;
my $recv_length = Sys->recv($socket, $recv_buffer, length $recv_buffer, 0);
if ($recv_length > 0) {
my $recv_string_part = Fn->substr($recv_buffer, 0, $recv_length);
$recv_string_buffer->push($recv_string_part);
}
else {
last;
}
}
my $recv_string = $recv_string_buffer->to_string;
unless ($recv_string eq "abcdef") {
return 0;
}
return 1;
}
static method sendto_and_recvfrom : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $status_connect = Sys::Socket->connect($socket, $sockaddr, $sockaddr->size);
unless ($status_connect == 0) {
Sys::Socket->close($socket);
return 0;
}
{
my $send_buffer = "abcd";
my $send_length = Sys->sendto($socket, $send_buffer, 0, undef);
unless ($send_length == 4) {
return 0;
}
}
{
my $send_buffer = "ef";
my $send_length = Sys->sendto($socket, $send_buffer, 0, undef, length $send_buffer, 0);
unless ($send_length == 2) {
return 0;
}
}
my $status_shutdown = Sys::Socket->shutdown($socket, SOCKET->SHUT_WR);
unless ($status_shutdown == 0) {
return 0;
}
my $recv_string_buffer = StringBuffer->new;
while (1) {
my $sockaddr_tmp_ref = (Sys::Socket::Sockaddr[])undef;
my $recv_buffer = (mutable string)new_string_len 1024;
my $recv_length = Sys->recvfrom($socket, $recv_buffer, length $recv_buffer, 0, $sockaddr_tmp_ref);
if ($recv_length > 0) {
my $recv_string_part = Fn->substr($recv_buffer, 0, $recv_length);
$recv_string_buffer->push($recv_string_part);
}
else {
last;
}
}
my $recv_string = $recv_string_buffer->to_string;
unless ($recv_string eq "abcdef") {
return 0;
}
return 1;
}
static method bind : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
Sys->setsockopt($socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR, 1);
Sys->bind($socket, $sockaddr);
return 1;
}
static method listen : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
Sys->setsockopt($socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR, 1);
my $status_bind = Sys::Socket->bind($socket, $sockaddr, $sockaddr->size);
unless ($status_bind == 0) {
return 0;
}
Sys->listen($socket, SOCKET->SOMAXCONN);
return 1;
}
# accept
static method run_echo_server : void ($port : int) {
# Socket
my $server_socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
Sys->setsockopt($server_socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR, 1);
Sys::Socket->bind($server_socket, $sockaddr, $sockaddr->size);
Sys::Socket->listen($server_socket, SOCKET->SOMAXCONN);
my $warned = 0;
while (1) {
my $client_socket = -1;
my $peer_address = Sys->accept(\$client_socket, $server_socket);
my $recv_buffer = (mutable string)new_string_len 1024;
my $recv_length = Sys::Socket->recv($client_socket, $recv_buffer, length $recv_buffer, 0);
Sys::Socket->send($client_socket, $recv_buffer, $recv_length, 0);
Sys::Socket->close($client_socket);
}
}
static method getpeername : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
unless ($socket> 0) {
return 0;
}
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $status_connect = Sys::Socket->connect($socket, $sockaddr, $sockaddr->size);
{
my $result_address = Sys::Socket::Sockaddr::In->new;
my $result_address_size = $result_address->size;
my $status_getpeername = Sys::Socket->getpeername($socket, $result_address, \$result_address_size);
unless ($status_getpeername == 0) {
return 0;
}
my $port_got = ((int)Sys::Socket->ntohs((short)$result_address->sin_port)) & 0xFFFF;
unless ($port_got == $port) {
return 0;
}
unless ($result_address->sin_addr->s_addr == $in_addr->s_addr) {
return 0;
}
unless ($result_address->size == $sockaddr->size) {
return 0;
}
}
{
my $result_address = (Sys::Socket::Sockaddr::In)Sys->getpeername($socket);
unless ($result_address->sin_family == SOCKET->AF_INET) {
return 0;
}
unless (Sys::Socket->ntohs((short)$result_address->sin_port) != 0) {
return 0;
}
unless ($result_address->sin_addr->s_addr == $in_addr->s_addr) {
return 0;
}
}
return 1;
}
static method getsockname : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
unless ($socket> 0) {
return 0;
}
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET, "127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $status_connect = Sys::Socket->connect($socket, $sockaddr, $sockaddr->size);
{
my $result_address = Sys::Socket::Sockaddr::In->new;
my $result_address_size = $result_address->size;
my $status_getsockname = Sys::Socket->getsockname($socket, $result_address, \$result_address_size);
unless ($status_getsockname == 0) {
return 0;
}
unless (Sys::Socket->ntohs((short)$result_address->sin_port) != 0) {
return 0;
}
unless ($result_address->sin_addr->s_addr == $in_addr->s_addr) {
return 0;
}
unless ($result_address->size == $sockaddr->size) {
return 0;
}
}
{
my $result_address = (Sys::Socket::Sockaddr::In)Sys->getsockname($socket);
unless ($result_address->sin_family == SOCKET->AF_INET) {
return 0;
}
unless (Sys::Socket->ntohs((short)$result_address->sin_port) != 0) {
return 0;
}
unless ($result_address->sin_addr->s_addr == $in_addr->s_addr) {
return 0;
}
}
return 1;
}
static method socketpair : int () {
{
my $sockets = new int[2];
my $status = Sys::Socket->socketpair(SOCKET->AF_UNIX, SOCKET->SOCK_STREAM, 0, $sockets);
unless ($status == 0) {
return 0;
}
my $sockets0 = $sockets->[0];
Fn->defer([$sockets0 : int] method :void () {
Sys::Socket->close($sockets0);
});
my $sockets1 = $sockets->[1];
Fn->defer([$sockets1 : int] method :void () {
Sys::Socket->close($sockets1);
});
unless ($sockets->[0] > 0) {
return 0;
}
unless ($sockets->[1] > 0) {
return 0;
}
}
{
my $socket1 = -1;
my $socket2 = -1;
Sys->socketpair(\$socket1, \$socket2, SOCKET->AF_UNIX, SOCKET->SOCK_STREAM, 0);
Fn->defer([$socket1 : int] method :void () {
Sys::Socket->close($socket1);
});
Fn->defer([$socket2 : int] method :void () {
Sys::Socket->close($socket2);
});
unless ($socket1 > 0) {
return 0;
}
unless ($socket2 > 0) {
return 0;
}
}
return 1;
}
static method setsockopt_int : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
$in_addr->set_s_addr(Sys::Socket->htonl(SOCKET->INADDR_ANY));
$sockaddr->set_sin_addr($in_addr);
Sys->setsockopt($socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR, 1);
return 1;
}
static method getsockopt_int : int ($port : int) {
# Socket
my $socket = Sys::Socket->socket(SOCKET->AF_INET, SOCKET->SOCK_STREAM, 0);
unless ($socket> 0) {
return 0;
}
Fn->defer([$socket : int] method :void () {
Sys::Socket->close($socket);
});
# IPv4 address
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons((short)$port));
my $in_addr = $sockaddr->sin_addr;
$in_addr->set_s_addr(Sys::Socket->htonl(SOCKET->INADDR_ANY));
$sockaddr->set_sin_addr($in_addr);
{
my $result_packed = Sys->getsockopt($socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR);
my $result_ref = [0];
Fn->memcpy($result_ref, 0, $result_packed, 0, 4);
my $result = $result_ref->[0];
unless ($result == 0) {
return 0;
}
}
{
Sys->setsockopt($socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR, 1);
my $result_packed = Sys->getsockopt($socket, SOCKET->SOL_SOCKET, SOCKET->SO_REUSEADDR);
my $result_ref = [0];
Fn->memcpy($result_ref, 0, $result_packed, 0, 4);
my $result = $result_ref->[0];
if ($result == 0) {
return 0;
}
}
return 1;
}
static method sockaddr_strage : int () {
my $sockaddr = Sys::Socket::Sockaddr::Storage->new;
$sockaddr->set_ss_family(1);
unless ($sockaddr->ss_family == 1) {
return 0;
}
unless ($sockaddr->sa_family == 1) {
return 0;
}
unless ($sockaddr->size > 0) {
return 0;
}
return 1;
}
static method sockaddr_un : int () {
my $sockaddr = Sys::Socket::Sockaddr::Un->new;
$sockaddr->set_sun_family(1);
unless ($sockaddr->sun_family == 1) {
return 0;
}
unless ($sockaddr->sa_family == 1) {
return 0;
}
$sockaddr->set_sun_path("abc");
unless ($sockaddr->sun_path eq "abc") {
return 0;
}
unless ($sockaddr->size > 0) {
return 0;
}
return 1;
}
static method getaddrinfo : int () {
{
my $servname = "localhost";
my $hints = Sys::Socket::Addrinfo->new;
my $res = new Sys::Socket::AddrinfoLinkedList[1];
$hints->set_ai_socktype(SOCKET->SOCK_STREAM);
$hints->set_ai_family(SOCKET->AF_INET);
my $status = Sys::Socket->getaddrinfo($servname, undef, $hints, $res);
unless ($status == 0) {
return 0;
}
my $addrinfos = $res->[0]->to_array;
{
my $addrinfo = $addrinfos->[0];
my $ai_addr = $addrinfo->ai_addr;
my $in_addr : Sys::Socket::In_addr = $ai_addr->(Sys::Socket::Sockaddr::In)->sin_addr;
my $addr_string = Sys::Socket->inet_ntoa($in_addr);
unless ($addr_string eq "127.0.0.1") {
return 0;
}
}
if (@$addrinfos >= 2 ){
my $addrinfo = $addrinfos->[1];
my $ai_addr = $addrinfo->ai_addr;
my $in_addr : Sys::Socket::In_addr = $ai_addr->(Sys::Socket::Sockaddr::In)->sin_addr;
my $addr_string = Sys::Socket->inet_ntoa($in_addr);
unless ($addr_string eq "127.0.0.1") {
return 0;
}
}
}
{
my $servname = "localhost";
my $hints = Sys::Socket::Addrinfo->new;
my $res = new Sys::Socket::AddrinfoLinkedList[1];
$hints->set_ai_socktype(SOCKET->SOCK_STREAM);
$hints->set_ai_family(SOCKET->AF_INET6);
my $status = Sys::Socket->getaddrinfo($servname, undef, $hints, $res);
unless ($status == 0) {
return 0;
}
my $addrinfos = $res->[0]->to_array;
my $addrinfo = $addrinfos->[0];
my $ai_addr = $addrinfo->ai_addr;
my $in_addr : Sys::Socket::In6_addr = $ai_addr->(Sys::Socket::Sockaddr::In6)->sin6_addr;
my $addr_string = (mutable string)new_string_len SOCKET->INET_ADDRSTRLEN;
Sys::Socket->inet_ntop(SOCKET->AF_INET6, $in_addr, $addr_string, SOCKET->INET_ADDRSTRLEN);
Fn->shorten_null_char($addr_string);
unless ($addr_string eq "::1") {
return 0;
}
}
{
my $servname = "http";
my $hints = Sys::Socket::Addrinfo->new;
my $res = new Sys::Socket::AddrinfoLinkedList[1];
$hints->set_ai_socktype(SOCKET->SOCK_STREAM);
$hints->set_ai_family(SOCKET->AF_INET);
my $status = Sys::Socket->getaddrinfo(undef, $servname, $hints, $res);
unless ($status == 0) {
return 0;
}
my $addrinfos = $res->[0]->to_array;
my $addrinfo = $addrinfos->[0];
my $ai_addr = $addrinfo->ai_addr;
my $port_net = $ai_addr->(Sys::Socket::Sockaddr::In)->sin_port;
my $port_host = (int)Sys::Socket->ntohs((short)$port_net);
unless ($port_host == 80) {
return 0;
}
}
return 1;
}
static method getnameinfo : int () {
# IPv4
{
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
my $in_addr = $sockaddr->sin_addr;
Sys::Socket->inet_aton("127.0.0.1", $in_addr);
$sockaddr->set_sin_addr($in_addr);
my $host = (mutable string)new_string_len SOCKET->NI_MAXHOST;
my $status = Sys::Socket->getnameinfo($sockaddr, $sockaddr->size, $host, length $host, undef, 0, 0);
unless ($status == 0) {
return 0;
}
Fn->shorten_null_char($host);
# Generally this is localhost, but if localhost is not defined in /etc/hosts, this is resolved by DNS.
if ($host eq "") {
return 0;
}
}
# IPv6
{
my $sockaddr = Sys::Socket::Sockaddr::In6->new;
$sockaddr->set_sin6_family((byte)SOCKET->AF_INET6);
my $in_addr = $sockaddr->sin6_addr;
Sys::Socket->inet_pton(SOCKET->AF_INET6, "::1", $in_addr);
$sockaddr->set_sin6_addr($in_addr);
my $host = (mutable string)new_string_len SOCKET->NI_MAXHOST;
my $status = Sys::Socket->getnameinfo($sockaddr, $sockaddr->size, $host, length $host, undef, 0, 0);
unless ($status == 0) {
return 0;
}
Fn->shorten_null_char($host);
# Generally this is localhost, but if localhost is not defined in /etc/hosts, this is resolved by DNS.
if ($host eq "") {
return 0;
}
}
# Service
{
my $sockaddr = Sys::Socket::Sockaddr::In->new;
$sockaddr->set_sin_family((byte)SOCKET->AF_INET);
$sockaddr->set_sin_port(Sys::Socket->htons(80));
my $service = (mutable string)new_string_len SOCKET->NI_MAXSERV;
my $status = Sys::Socket->getnameinfo($sockaddr, $sockaddr->size, undef, 0, $service, length $service, 0);
unless ($status == 0) {
return 0;
}
Fn->shorten_null_char($service);
unless ($service eq "http") {
return 0;
}
}
return 1;
}
}