


## socket-guts.pkg
# Compiled by:
# src/lib/std/src/standard-core.sublibstipulate
package int = int_guts; # int_guts is from src/lib/std/src/bind-int-32.pkg package wg = winix_guts; # winix_guts is from src/lib/std/src/posix/winix-guts.pkg package ci = mythryl_callable_c_library_interface; # mythryl_callable_c_library_interface is from src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg package w8a = rw_vector_of_one_byte_unts; # rw_vector_of_one_byte_unts is from src/lib/std/src/rw-vector-of-one-byte-unts.pkg package w8v = vector_of_one_byte_unts; # vector_of_one_byte_unts is from src/lib/std/src/vector-of-one-byte-unts.pkg package ps = pre_socket; # pre_socket is from src/lib/std/src/socket/pre-socket.pkgherein
package socket_guts
: (weak) Socket # Socket is from src/lib/std/src/socket/socket.api {
fun socket_fn fun_name
=
ci::find_c_function { lib_name => "socket", fun_name }; # socket is in src/c/lib/socket/cfun-list.h
Wy8Vector = w8v::Vector;
Wy8Array = w8a::Rw_Vector;
# The system's representation of a socket:
#
Socket_Fd
=
ps::Socket_Fd;
# Import the various socket related types:
#
include pre_socket;
# Bind socket C functions
#
fun netdb_fun fun_name
=
ci::find_c_function { lib_name => "socket", fun_name };
# dummyAddr = ADDRESS (w8v::from_list[])
# Address families
#
package af {
include af; # af is from src/lib/std/src/socket/pre-socket.pkg # via above 'include pre_socket'.
my list_addr_families: Void -> List( ci::System_Constant )
=
socket_fn "listAddrFamilies";
fun list ()
=
list::map
(fn arg = (#2 arg, ADDRESS_FAMILY arg))
(list_addr_families ());
fun to_string (ADDRESS_FAMILY (_, name))
=
name;
fun from_string name
=
case (ci::find_system_constant (name, list_addr_families ()))
#
THE af => THE (ADDRESS_FAMILY af);
NULL => NULL;
esac;
};
# Socket types:
#
package socket {
include pre_socket;
Socket_Type
=
ps::socket::Socket_Type;
my list_socket_types: Void -> List( ci::System_Constant )
=
socket_fn "listSockTypes"; # listSockTypes def in src/c/lib/socket/list-socket-types.c
# socket is from src/lib/std/src/socket/pre-socket.pkg stream = socket::SOCKET_TYPE (ci::bind_system_constant ("STREAM", list_socket_types ()));
datagram = socket::SOCKET_TYPE (ci::bind_system_constant ("DGRAM", list_socket_types ()));
fun list ()
=
list::map
(fn arg = (#2 arg, socket::SOCKET_TYPE arg))
(list_socket_types ());
fun to_string (socket::SOCKET_TYPE(_, name))
=
name;
fun from_string name
=
case (ci::find_system_constant (name, list_socket_types ()))
#
THE ty => THE (socket::SOCKET_TYPE ty);
NULL => NULL;
esac;
};
# Socket control operations:
#
package control {
#
stipulate
#
fun the_else control_fn (ps::SOCKET { file_descriptor, ... } )
=
control_fn( file_descriptor, NULL );
fun set_opt control_fn (ps::SOCKET { file_descriptor, ... }, value)
=
ignore (control_fn (file_descriptor, THE value));
my ctl_debug: (Socket_Fd, Null_Or(Bool)) -> Bool = socket_fn "get_or_set_socket_debug_option"; # "get_or_set_socket_debug_option" def in src/c/lib/socket/get-or-set-socket-debug-option.c
my ctl_reuseaddr: (Socket_Fd, Null_Or(Bool)) -> Bool = socket_fn "get_or_set_socket_reuseaddr_option"; # "get_or_set_socket_reuseaddr_option" def in src/c/lib/socket/get-or-set-socket-reuseaddr-option.c
my ctl_keepalive: (Socket_Fd, Null_Or(Bool)) -> Bool = socket_fn "get_or_set_socket_keepalive_option"; # "get_or_set_socket_keepalive_option" def in src/c/lib/socket/get-or-set-socket-keepalive-option.c
my ctl_dontroute: (Socket_Fd, Null_Or(Bool)) -> Bool = socket_fn "get_or_set_socket_dontroute_option"; # "get_or_set_socket_dontroute_option" def in src/c/lib/socket/get-or-set-socket-dontroute-option.c
my ctl_broadcast: (Socket_Fd, Null_Or(Bool)) -> Bool = socket_fn "get_or_set_socket_broadcast_option"; # "get_or_set_socket_broadcast_option" def in src/c/lib/socket/get-or-set-socket-broadcast-option.c
my ctl_oobinline: (Socket_Fd, Null_Or(Bool)) -> Bool = socket_fn "get_or_set_socket_oobinline_option"; # "get_or_set_socket_oobinline_option" def in src/c/lib/socket/get-or-set-socket-oobinline-option.c
my ctl_sndbuf: (Socket_Fd, Null_Or(Int )) -> Int = socket_fn "get_or_set_socket_sndbuf_option"; # "get_or_set_socket_sndbuf_option" def in src/c/lib/socket/get-or-set-socket-sndbuf-option.c
my ctl_rcvbuf: (Socket_Fd, Null_Or(Int )) -> Int = socket_fn "get_or_set_socket_rcvbuf_option"; # "get_or_set_socket_rcvbuf_option" def in src/c/lib/socket/get-or-set-socket-rcvbuf-option.c
my ctl_linger:
(Socket_Fd, Null_Or( Null_Or(Int) )) -> Null_Or(Int) = socket_fn "get_or_set_socket_linger_option"; # "get_or_set_socket_linger_option" def in src/c/lib/socket/get-or-set-socket-linger-option.c
herein
# Get/set socket options
fun get_debug x = the_else ctl_debug x;
fun set_debug x = set_opt ctl_debug x;
fun get_reuseaddr x = the_else ctl_reuseaddr x;
fun set_reuseaddr x = set_opt ctl_reuseaddr x;
fun get_keepalive x = the_else ctl_keepalive x;
fun set_keepalive x = set_opt ctl_keepalive x;
fun get_dontroute x = the_else ctl_dontroute x;
fun set_dontroute x = set_opt ctl_dontroute x;
fun get_linger socket
=
case (the_else ctl_linger socket)
#
THE t => THE (time_guts::from_seconds (int::to_multiword_int t));
NULL => NULL;
esac;
# NOTE: Should probably do some
# range checking on the argument: XXX BUGGO FIXME
fun set_linger (socket, THE t)
=>
set_opt ctl_linger (socket, THE (int::from_multiword_int (time_guts::to_seconds t)));
set_linger (socket, NULL)
=>
set_opt ctl_linger (socket, NULL);
end;
fun get_broadcast x = the_else ctl_broadcast x;
fun set_broadcast x = set_opt ctl_broadcast x;
fun get_oobinline x = the_else ctl_oobinline x;
fun set_oobinline x = set_opt ctl_oobinline x;
fun get_sndbuf x = the_else ctl_sndbuf x;
# NOTE: Should probably do some
# range checking on the argument: XXX BUGGO FIXME
fun set_sndbuf x = set_opt ctl_sndbuf x;
fun get_rcvbuf x = the_else ctl_rcvbuf x;
# NOTE: Should probably do some
# range checking on the argument: XXX BUGGO FIXME
fun set_rcvbuf x
=
set_opt ctl_rcvbuf x;
stipulate
my get_type' : Socket_Fd -> ci::System_Constant
=
socket_fn "getTYPE"; # getTYPE def in src/c/lib/socket/getTYPE.c
my get_error' : Socket_Fd -> Bool
=
socket_fn "getERROR"; # getERROR def in src/c/lib/socket/getERROR.c
herein
fun get_type (SOCKET { file_descriptor, ... } )
=
ps::socket::SOCKET_TYPE (get_type' file_descriptor);
fun get_error (SOCKET { file_descriptor, ... } )
=
get_error' file_descriptor;
end;
stipulate
my get_peer_name' : Socket_Fd -> Internet_Address
=
socket_fn "getPeerName"; # getPeerName def in src/c/lib/socket/getpeername.c
my get_sock_name' : Socket_Fd -> Internet_Address
=
socket_fn "getSockName"; # getSockName def in src/c/lib/socket/getsockname.c
fun get_name f (SOCKET { file_descriptor, ... } )
=
ADDRESS (f file_descriptor);
herein
fun get_peer_name socket = get_name get_peer_name' socket;
fun get_sock_name socket = get_name get_sock_name' socket;
end;
stipulate
my get_nread' : Socket_Fd -> Int
=
socket_fn "getNREAD"; # getNREAD def in src/c/lib/socket/getNREAD.c
my get_atmark' : Socket_Fd -> Bool
=
socket_fn "getATMARK"; # getATMARK def in src/c/lib/socket/getATMARK.c
herein
fun get_nread (SOCKET { file_descriptor, ... } ) = get_nread' file_descriptor;
fun get_atmark (SOCKET { file_descriptor, ... } ) = get_atmark' file_descriptor;
end;
end; # stipulate
}; # package control
my set_nbio': (Socket_Fd, Bool) -> Void # "nbio" == "non-blocking I/O"
=
socket_fn "setNBIO"; # setNBIO def in src/c/lib/socket/setNBIO.c
# fun setNBIO (SOCKET fd, flag) = setNBIO'(fd, flag)
# Extract a blocking file descriptor; # "nbr" == "nonblocking ref"
# implicitly set socket to # "nb" == "nonblocking"
# blocking mode if necessary: # "fd" == "file descriptor"
#
fun to_blocking_fd (SOCKET { file_descriptor, nonblocking => nbr as REF nonblocking } )
=
if nonblocking
#
set_nbio' (file_descriptor, FALSE);
nbr := FALSE;
file_descriptor;
else
file_descriptor;
fi;
# Same for non-blocking:
#
fun to_nonblocking_fd (SOCKET { file_descriptor, nonblocking => nbr as REF nonblocking } )
=
{ if (not nonblocking)
#
set_nbio' (file_descriptor, TRUE);
nbr := TRUE;
fi;
file_descriptor;
};
# nonblocking_socket_junk is from src/lib/std/src/socket/nonblocking-socket-junk.pkg # These two fns wrap an "f(x)" evaluation, # "nb" is "nonblocking":
# while trapping some exceptions:
#
wrap_nb_o = nonblocking_socket_junk::wrap_nb_o; # Traps EWOULDBLOCK/EINPROGRESS/EAGAIN and returns NULL.
wrap_nb_b = nonblocking_socket_junk::wrap_nb_b; # Traps EWOULDBLOCK/EINPROGRESS/EAGAIN and returns FALSE.
fun sock_b file_descriptor = SOCKET { file_descriptor, nonblocking => REF FALSE };
fun sock_nb file_descriptor = SOCKET { file_descriptor, nonblocking => REF TRUE };
# Socket address operations:
#
fun same_address (ADDRESS a1, ADDRESS a2)
=
(a1 == a2);
stipulate
my get_address_family: Internet_Address -> Raw_Address_Family
=
socket_fn "getAddrFamily"; # getAddrFamily def in src/c/lib/socket/getaddrfamily.c
herein
fun family_of_address (ADDRESS a)
=
af::ADDRESS_FAMILY (get_address_family a);
end;
# Socket management:
#
stipulate
my accept' : Int -> (Int, Internet_Address) = socket_fn "accept"; # accept def in src/c/lib/socket/accept.c
my bind' : (Int, Internet_Address) -> Void = socket_fn "bind"; # bind def in src/c/lib/socket/bind.c
my connect' : (Int, Internet_Address) -> Void = socket_fn "connect"; # connect def in src/c/lib/socket/connect.c
my listen' : (Int, Int) -> Void = socket_fn "listen"; # listen def in src/c/lib/socket/listen.c
my close' : Int -> Void = socket_fn "close"; # close def in src/c/lib/socket/close.c
herein
fun bind (SOCKET { file_descriptor, ... }, ADDRESS address)
=
bind' (file_descriptor, address);
fun listen (SOCKET { file_descriptor, ... }, back_log)
=
listen' (file_descriptor, back_log); # Should do some range checking on back_log XXX BUGGO FIXME
stipulate
fun accept0 (socket, coerce_blocking_status) s
=
{ my (new_fd, address)
=
accept' (coerce_blocking_status s);
( socket new_fd,
ADDRESS address
);
};
herein
fun accept s
=
accept0 (sock_b, to_blocking_fd) s;
fun accept_nonblocking s
=
wrap_nb_o (accept0 (sock_nb, to_nonblocking_fd)) s;
end;
stipulate
fun connect0 coerce_blocking_status (s, ADDRESS address)
=
connect' (coerce_blocking_status s, address);
herein
fun connect arg
=
connect0 to_blocking_fd arg;
fun connect_nonblocking arg
=
wrap_nb_b (connect0 to_nonblocking_fd) arg;
end;
fun close (SOCKET { file_descriptor, ... } )
=
close' file_descriptor;
end; # stipulate
stipulate
my shutdown' : (Int, Int) -> Void
=
socket_fn "shutdown"; # shutdown def in src/c/lib/socket/shutdown.c
fun how NO_RECVS => 0;
how NO_SENDS => 1;
how NO_RECVS_OR_SENDS => 2;
end;
herein
fun shutdown (SOCKET { file_descriptor, ... }, mode)
=
shutdown' (file_descriptor, how mode);
end;
# nonblocking_socket_junk is from src/lib/std/src/socket/nonblocking-socket-junk.pkg fun io_descriptor (SOCKET { file_descriptor, ... } )
=
nonblocking_socket_junk::make_io_descriptor file_descriptor;
fun make_wait_request { socket, readable, writable, oobdable }
=
{ io_descriptor => io_descriptor socket, readable, writable, oobdable };
# For now we implement 'wait_for_io_opportunity' in terms of 'poll':
#
# The C side of 'poll' is in
# src/c/lib/posix-os/poll.c
# The Mythryl side is in
# src/lib/std/src/winix/winix-io.api # src/lib/std/src/posix/winix-io.pkg #
# For an alternate convenience wrapper see:
# src/lib/src/when.api # src/lib/src/when.pkg #
socket_descriptor
=
io_descriptor;
fun same_descriptor (d1, d2)
=
wg::io::compare (d1, d2) == EQUAL;
fun wait_for_io_opportunity { readable, writable, oobdable, timeout }
=
split3 (reverse result_list, [], [], [])
where
fun is_readable d
=
{ io_descriptor => d,
readable => TRUE,
writable => FALSE,
oobdable => FALSE
};
fun is_writable d
=
{ io_descriptor => d,
readable => FALSE,
writable => TRUE,
oobdable => FALSE
};
fun is_oobdable d
=
{ io_descriptor => d,
readable => FALSE,
writable => TRUE,
oobdable => FALSE
};
wait_requests
=
map is_readable readable
@
map is_writable writable
@
map is_oobdable oobdable;
result_list
=
wg::io::wait_for_io_opportunity { wait_requests, timeout };
fun split3 ([], readable, writable, oobdable)
=>
{ readable, writable, oobdable };
split3 ((i: wg::io::Wait_Result) ! is, readable, writable, oobdable)
=>
{ readable = i.readable ?? i.io_descriptor ! readable :: readable;
writable = i.writable ?? i.io_descriptor ! writable :: writable;
oobdable = i.oobdable ?? i.io_descriptor ! oobdable :: oobdable;
split3 (is, readable, writable, oobdable);
};
end;
end;
select = wait_for_io_opportunity;
#
# Deprecated synonym, mainly so that unix folks
# looking for 'select' in the function index
# will be led here.
vbuf = vector_slice_of_one_byte_unts::base;
abuf = rw_vector_slice_of_one_byte_unts::base;
# Default flags
#
default_don't_route = FALSE;
default_oob = FALSE;
default_peek = FALSE;
# Socket output operations
#
stipulate
my send_v: (Int, Wy8Vector, Int, Int, Bool, Bool) -> Int = socket_fn "sendBuf"; # "sendBuf" is in src/c/lib/socket/sendbuf.c
my send_a: (Int, Wy8Array, Int, Int, Bool, Bool) -> Int = socket_fn "sendBuf";
herein
fun send_vec0 coerce_blocking_status (s, buffer)
=
{ fd = coerce_blocking_status s;
my (vec, i, len)
=
vbuf buffer;
if (len > 0)
send_v
( fd,
vec,
i,
len,
default_don't_route,
default_oob
);
else
0;
fi;
};
fun send_vector arg
=
send_vec0 to_blocking_fd arg;
fun send_vector_nonblocking arg
=
wrap_nb_o (send_vec0 to_nonblocking_fd) arg;
fun send_vector'0 coerce_blocking_status (socket, buffer, { don't_route, oob } )
=
{ fd = coerce_blocking_status socket;
my (vec, i, len)
=
vbuf buffer;
if (len > 0) send_v (fd, vec, i, len, don't_route, oob);
else 0;
fi;
};
fun send_vector' arg
=
send_vector'0 to_blocking_fd arg;
fun send_vector_nonblocking' arg
=
wrap_nb_o (send_vector'0 to_nonblocking_fd) arg;
fun send_arr0 coerce_blocking_status (socket, buffer)
=
{ fd = coerce_blocking_status socket;
my (arr, i, len) = abuf buffer;
if (len > 0) send_a (fd, arr, i, len, default_don't_route, default_oob);
else 0;
fi;
};
fun send_rw_vector arg
=
send_arr0 to_blocking_fd arg;
fun send_rw_vector_nonblocking arg
=
wrap_nb_o (send_arr0 to_nonblocking_fd) arg;
fun send_rw_vector'0 coerce_blocking_status (socket, buffer, { don't_route, oob } )
=
{ fd = coerce_blocking_status socket;
my (arr, i, len)
=
abuf buffer;
if (len > 0) send_a (fd, arr, i, len, don't_route, oob);
else 0;
fi;
};
fun send_rw_vector' arg
=
send_rw_vector'0 to_blocking_fd arg;
fun send_rw_vector_nonblocking' arg
=
wrap_nb_o (send_rw_vector'0 to_nonblocking_fd) arg;
end; # stipulate
stipulate
my send_to_v: (Int, Wy8Vector, Int, Int, Bool, Bool, Internet_Address) -> Int = socket_fn "sendBufTo"; # sendBufTo is in src/c/lib/socket/sendbufto.c
my send_to_a: (Int, Wy8Array, Int, Int, Bool, Bool, Internet_Address) -> Int = socket_fn "sendBufTo";
herein
fun send_vec_to0 coerce_blocking_status (socket, ADDRESS address, buffer)
=
{ fd = coerce_blocking_status socket;
my (vec, i, len)
=
vbuf buffer;
if (len > 0) send_to_v (fd, vec, i, len, default_don't_route, default_oob, address);
else 0;
fi;
();
};
fun send_vector_to arg
=
send_vec_to0 to_blocking_fd arg;
fun send_vector_to_nonblocking arg
=
wrap_nb_b (send_vec_to0 to_nonblocking_fd) arg;
fun send_vector_to'0 coerce_blocking_status (socket, ADDRESS address, buffer, { don't_route, oob } )
=
{ fd = coerce_blocking_status socket;
my (vec, i, len)
=
vbuf buffer;
if (len > 0) send_to_v (fd, vec, i, len, don't_route, oob, address);
else 0;
fi;
();
};
fun send_vector_to' arg
=
send_vector_to'0 to_blocking_fd arg;
fun send_vector_to_nonblocking' arg
=
wrap_nb_b (send_vector_to'0 to_nonblocking_fd) arg;
fun send_arr_to0 coerce_blocking_status (socket, ADDRESS address, buffer)
=
{ fd = coerce_blocking_status socket;
my (arr, i, len)
=
abuf buffer;
if (len > 0) send_to_a (fd, arr, i, len, default_don't_route, default_oob, address);
else 0;
fi;
();
};
fun send_rw_vector_to arg
=
send_arr_to0 to_blocking_fd arg;
fun send_rw_vector_to_nonblocking arg
=
wrap_nb_b (send_arr_to0 to_nonblocking_fd) arg;
fun send_rw_vector_to'0 coerce_blocking_status (socket, ADDRESS address, buffer, { don't_route, oob } )
=
{ fd = coerce_blocking_status socket;
my (arr, i, len)
=
abuf buffer;
if (len > 0) send_to_a (fd, arr, i, len, don't_route, oob, address);
else 0;
fi;
();
};
fun send_rw_vector_to' arg
=
send_rw_vector_to'0 to_blocking_fd arg;
fun send_rw_vector_to_nonblocking' arg
=
wrap_nb_b (send_rw_vector_to'0 to_nonblocking_fd) arg;
end; # stipulate
# Socket input operations
#
stipulate
my recv_v' : (Int, Int, Bool, Bool) -> Wy8Vector
=
socket_fn "recv"; # recv def in src/c/lib/socket/recv.c
fun recv_v _ (_, 0, _, _)
=>
w8v::from_list [];
recv_v coerce_blocking_status (socket, nbytes, peek, oob)
=>
if (nbytes < 0) raise exception SIZE;
else recv_v' (coerce_blocking_status socket, nbytes, peek, oob);
fi;
end;
my recv_a: (Int, Wy8Array, Int, Int, Bool, Bool) -> Int
=
socket_fn "recvBuf"; # recvBuf def in src/c/lib/socket/recvbuf.c
herein
stipulate
fun recv_vec0 coerce_blocking_status (socket, size)
=
recv_v coerce_blocking_status (socket, size, default_peek, default_oob);
herein
# Set socket to blocking if not already blocking
# and read given number of bytes from given socket.
#
# Return resulting bytevector.
#
fun receive_vector arg
=
recv_vec0 to_blocking_fd arg;
# Set socket to nonblocking if not already nonblocking
# and read given number of bytes from given socket.
#
# Return THE result_bytevector.
# If no input was available return NULL.
#
fun receive_vector_nonblocking arg
=
wrap_nb_o (recv_vec0 to_nonblocking_fd) arg;
end;
stipulate
fun receive_vector'0 coerce_blocking_status (socket, size, { peek, oob } )
=
recv_v coerce_blocking_status (socket, size, peek, oob);
herein
# Same as receive_vector above,
# but with explicit PEEK and OOB flags:
#
fun receive_vector' arg
=
receive_vector'0 to_blocking_fd arg;
# Same as receive_vector_nonblokcing above,
# but with explicit PEEK and OOB flags:
#
fun receive_vector_nonblocking' arg
=
wrap_nb_o (receive_vector'0 to_nonblocking_fd) arg;
end;
stipulate
fun recv_arr0 coerce_blocking_status (socket, buffer)
=
{ fd = coerce_blocking_status socket;
my (buf, i, size)
=
abuf buffer;
if (size > 0) recv_a (fd, buf, i, size, default_peek, default_oob);
else 0;
fi;
};
herein
fun receive_rw_vector arg
=
recv_arr0 to_blocking_fd arg;
fun receive_rw_vector_nonblocking arg
=
wrap_nb_o (recv_arr0 to_nonblocking_fd) arg;
end;
stipulate
fun receive_rw_vector'0 coerce_blocking_status (socket, buffer, { peek, oob } )
=
{ fd = coerce_blocking_status socket;
my (buf, i, size)
=
abuf buffer;
if (size > 0) recv_a (fd, buf, i, size, peek, oob);
else 0;
fi;
};
herein
fun receive_rw_vector' arg
=
receive_rw_vector'0 to_blocking_fd arg;
fun receive_rw_vector_nonblocking' arg
=
wrap_nb_o (receive_rw_vector'0 to_nonblocking_fd) arg;
end;
end; # stipulate
stipulate
my recv_from_v' : (Int, Int, Bool, Bool) -> (Wy8Vector, Internet_Address)
=
socket_fn "recvFrom"; # recvFrom def in src/c/lib/socket/recvfrom.c
fun recv_from_v _ (_, 0, _, _)
=>
(w8v::from_list [], (ADDRESS (w8v::from_list [])));
recv_from_v coerce_blocking_status (socket, size, peek, oob)
=>
if (size < 0)
raise exception SIZE;
else
fd = coerce_blocking_status socket;
my (data, address)
=
recv_from_v' (fd, size, peek, oob);
(data, ADDRESS address);
fi;
end;
my recv_from_a: ((Int, Wy8Array, Int, Int, Bool, Bool)) -> ((Int, Internet_Address))
=
socket_fn "recvBufFrom"; # "recvBufFrom" def in src/c/lib/socket/recvbuffrom.c
herein
stipulate
fun recv_vec_from0 coerce_blocking_status (socket, size)
=
recv_from_v coerce_blocking_status (socket, size, default_peek, default_oob);
herein
fun receive_vector_from arg
=
recv_vec_from0 to_blocking_fd arg;
fun receive_vector_from_nonblocking arg
=
wrap_nb_o (recv_vec_from0 to_nonblocking_fd) arg;
end;
stipulate
fun receive_vector_from'0 coerce_blocking_status (socket, size, { peek, oob } )
=
recv_from_v coerce_blocking_status (socket, size, peek, oob);
herein
fun receive_vector_from' arg
=
receive_vector_from'0 to_blocking_fd arg;
fun receive_vector_from_nonblocking' arg
=
wrap_nb_o (receive_vector_from'0 to_nonblocking_fd) arg;
end;
stipulate
fun recv_arr_from0 coerce_blocking_status (socket, asl)
=
{ fd = coerce_blocking_status socket;
my (buf, i, size)
=
abuf asl;
if (size > 0)
my (n, address)
=
recv_from_a (fd, buf, i, size, default_peek, default_oob);
(n, ADDRESS address);
else
(0, ADDRESS (w8v::from_list [] ));
fi;
};
herein
fun receive_rw_vector_from arg
=
recv_arr_from0 to_blocking_fd arg;
fun receive_rw_vector_from_nonblocking arg
=
wrap_nb_o (recv_arr_from0 to_nonblocking_fd) arg;
end;
stipulate
fun receive_rw_vector_from'0 coerce_blocking_status (socket, asl, { peek, oob } )
=
{ fd = coerce_blocking_status socket;
my (buf, i, size)
=
abuf asl;
if (size > 0)
my (n, address)
=
recv_from_a (fd, buf, i, size, peek, oob);
(n, ADDRESS address);
else
(0, (ADDRESS (w8v::from_list [])));
fi;
};
herein
fun receive_rw_vector_from' arg
=
receive_rw_vector_from'0 to_blocking_fd arg;
fun receive_rw_vector_from_nonblocking' arg
=
wrap_nb_o (receive_rw_vector_from'0 to_nonblocking_fd) arg;
end;
end; # stipulate
}; # package socket
end; # stipulate


