mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
net: move unix socket code to net.unix and skip net/unix/unix_test.v … (#8681)
This commit is contained in:
parent
f8db44bb15
commit
9b4f2edbfa
@ -52,7 +52,7 @@ const (
|
||||
'vlib/net/tcp_simple_client_server_test.v',
|
||||
'vlib/net/tcp_test.v',
|
||||
'vlib/net/udp_test.v',
|
||||
'vlib/net/unix_test.v',
|
||||
'vlib/net/unix/unix_test.v',
|
||||
'vlib/orm/orm_test.v',
|
||||
'vlib/os/os_test.v',
|
||||
'vlib/dl/dl_test.v',
|
||||
@ -189,6 +189,7 @@ const (
|
||||
'vlib/orm/orm_test.v',
|
||||
'vlib/v/tests/orm_sub_struct_test.v',
|
||||
'vlib/net/websocket/ws_test.v',
|
||||
'vlib/net/unix/unix_test.v',
|
||||
'vlib/x/websocket/websocket_test.v',
|
||||
'vlib/vweb/tests/vweb_test.v',
|
||||
]
|
||||
|
@ -16,7 +16,6 @@ pub enum SocketType {
|
||||
// SocketFamily are the available address families
|
||||
pub enum SocketFamily {
|
||||
inet = C.AF_INET
|
||||
unix = C.AF_UNIX
|
||||
}
|
||||
|
||||
struct C.in_addr {
|
||||
|
@ -6,10 +6,10 @@ import time
|
||||
fn shutdown(handle int) ? {
|
||||
$if windows {
|
||||
C.shutdown(handle, C.SD_BOTH)
|
||||
socket_error(C.closesocket(handle))?
|
||||
socket_error(C.closesocket(handle)) ?
|
||||
} $else {
|
||||
C.shutdown(handle, C.SHUT_RDWR)
|
||||
socket_error(C.close(handle))?
|
||||
socket_error(C.close(handle)) ?
|
||||
}
|
||||
|
||||
return none
|
||||
@ -34,19 +34,19 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
|
||||
// infinite timeout is signaled by passing null as the timeout to
|
||||
// select
|
||||
if timeout == infinite_timeout {
|
||||
if timeout == net.infinite_timeout {
|
||||
timeval_timeout = &C.timeval(0)
|
||||
}
|
||||
|
||||
match test {
|
||||
.read {
|
||||
socket_error(C.@select(handle+1, &set, C.NULL, C.NULL, timeval_timeout))?
|
||||
socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout)) ?
|
||||
}
|
||||
.write {
|
||||
socket_error(C.@select(handle+1, C.NULL, &set, C.NULL, timeval_timeout))?
|
||||
socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout)) ?
|
||||
}
|
||||
.except {
|
||||
socket_error(C.@select(handle+1, C.NULL, C.NULL, &set, timeval_timeout))?
|
||||
socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout)) ?
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,18 +54,14 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
}
|
||||
|
||||
// wait_for_common wraps the common wait code
|
||||
fn wait_for_common(
|
||||
handle int,
|
||||
deadline time.Time,
|
||||
timeout time.Duration,
|
||||
test Select) ? {
|
||||
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
|
||||
if deadline.unix == 0 {
|
||||
// only accept infinite_timeout as a valid
|
||||
// negative timeout - it is handled in @select however
|
||||
if timeout < 0 && timeout != infinite_timeout {
|
||||
if timeout < 0 && timeout != net.infinite_timeout {
|
||||
return err_timed_out
|
||||
}
|
||||
ready := @select(handle, test, timeout)?
|
||||
ready := @select(handle, test, timeout) ?
|
||||
if ready {
|
||||
return none
|
||||
}
|
||||
@ -80,7 +76,7 @@ fn wait_for_common(
|
||||
return err_timed_out
|
||||
}
|
||||
|
||||
ready := @select(handle, test, d_timeout)?
|
||||
ready := @select(handle, test, d_timeout) ?
|
||||
if ready {
|
||||
return none
|
||||
}
|
||||
@ -88,25 +84,21 @@ fn wait_for_common(
|
||||
}
|
||||
|
||||
// wait_for_write waits for a write io operation to be available
|
||||
fn wait_for_write(
|
||||
handle int,
|
||||
deadline time.Time,
|
||||
timeout time.Duration) ? {
|
||||
fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
return wait_for_common(handle, deadline, timeout, .write)
|
||||
}
|
||||
|
||||
// wait_for_read waits for a read io operation to be available
|
||||
fn wait_for_read(
|
||||
handle int,
|
||||
deadline time.Time,
|
||||
timeout time.Duration) ? {
|
||||
fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
return wait_for_common(handle, deadline, timeout, .read)
|
||||
}
|
||||
|
||||
// no_deadline should be given to functions when no deadline is wanted (i.e. all functions
|
||||
// return instantly)
|
||||
const (
|
||||
no_deadline = time.Time{unix: 0}
|
||||
no_deadline = time.Time{
|
||||
unix: 0
|
||||
}
|
||||
)
|
||||
|
||||
// no_timeout should be given to functions when no timeout is wanted (i.e. all functions
|
||||
|
@ -6,16 +6,18 @@ const (
|
||||
|
||||
// Well defined errors that are returned from socket functions
|
||||
pub const (
|
||||
err_new_socket_failed = error_with_code('net: new_socket failed to create socket', errors_base+1)
|
||||
err_option_not_settable = error_with_code('net: set_option_xxx option not settable', errors_base+2)
|
||||
err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type', errors_base+3)
|
||||
err_port_out_of_range = error_with_code('', errors_base+5)
|
||||
err_no_udp_remote = error_with_code('', errors_base+6)
|
||||
err_connect_failed = error_with_code('net: connect failed', errors_base+7)
|
||||
err_connect_timed_out = error_with_code('net: connect timed out', errors_base+8)
|
||||
|
||||
err_timed_out = error_with_code('net: op timed out', errors_base+9)
|
||||
err_timed_out_code = errors_base+9
|
||||
err_new_socket_failed = error_with_code('net: new_socket failed to create socket',
|
||||
errors_base + 1)
|
||||
err_option_not_settable = error_with_code('net: set_option_xxx option not settable',
|
||||
errors_base + 2)
|
||||
err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type',
|
||||
errors_base + 3)
|
||||
err_port_out_of_range = error_with_code('', errors_base + 5)
|
||||
err_no_udp_remote = error_with_code('', errors_base + 6)
|
||||
err_connect_failed = error_with_code('net: connect failed', errors_base + 7)
|
||||
err_connect_timed_out = error_with_code('net: connect timed out', errors_base + 8)
|
||||
err_timed_out = error_with_code('net: op timed out', errors_base + 9)
|
||||
err_timed_out_code = errors_base + 9
|
||||
)
|
||||
|
||||
pub fn socket_error(potential_code int) ?int {
|
||||
@ -23,10 +25,10 @@ pub fn socket_error(potential_code int) ?int {
|
||||
if potential_code < 0 {
|
||||
last_error_int := C.WSAGetLastError()
|
||||
last_error := wsa_error(last_error_int)
|
||||
return error_with_code('net: socket error: ($last_error_int) $last_error', int(last_error))
|
||||
return error_with_code('net: socket error: ($last_error_int) $last_error',
|
||||
int(last_error))
|
||||
}
|
||||
}
|
||||
$else {
|
||||
} $else {
|
||||
if potential_code < 0 {
|
||||
last_error := error_code()
|
||||
return error_with_code('net: socket error: $last_error', last_error)
|
||||
@ -40,8 +42,7 @@ pub fn wrap_error(error_code int) ? {
|
||||
$if windows {
|
||||
enum_error := wsa_error(error_code)
|
||||
return error_with_code('net: socket error: $enum_error', error_code)
|
||||
}
|
||||
$else {
|
||||
} $else {
|
||||
if error_code == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -1,280 +0,0 @@
|
||||
module net
|
||||
|
||||
import time
|
||||
import os
|
||||
|
||||
fn C.SUN_LEN(C.sockaddr_un) int
|
||||
|
||||
fn C.strncpy(charptr, charptr, int)
|
||||
|
||||
struct UnixSocket {
|
||||
pub:
|
||||
handle int
|
||||
mut:
|
||||
path string
|
||||
}
|
||||
|
||||
struct UnixConn {
|
||||
pub mut:
|
||||
sock UnixSocket
|
||||
mut:
|
||||
write_deadline time.Time
|
||||
read_deadline time.Time
|
||||
read_timeout time.Duration
|
||||
write_timeout time.Duration
|
||||
}
|
||||
|
||||
struct UnixListener {
|
||||
pub mut:
|
||||
sock UnixSocket
|
||||
mut:
|
||||
accept_timeout time.Duration
|
||||
accept_deadline time.Time
|
||||
}
|
||||
|
||||
fn new_unix_socket() ?UnixSocket {
|
||||
sockfd := socket_error(C.socket(SocketFamily.unix, SocketType.tcp, 0)) ?
|
||||
mut s := UnixSocket{
|
||||
handle: sockfd
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
fn (mut s UnixSocket) close() ? {
|
||||
os.rm(s.path) ?
|
||||
return shutdown(s.handle)
|
||||
}
|
||||
|
||||
fn (mut s UnixSocket) @select(test Select, timeout time.Duration) ?bool {
|
||||
return @select(s.handle, test, timeout)
|
||||
}
|
||||
|
||||
fn (mut s UnixSocket) connect(a string) ? {
|
||||
if a.len >= 108 {
|
||||
return error('Socket path too long! Max length: 107 chars.')
|
||||
}
|
||||
mut addr := C.sockaddr_un{}
|
||||
unsafe { C.memset(&addr, 0, sizeof(C.sockaddr_un)) }
|
||||
addr.sun_family = int(SocketFamily.unix)
|
||||
C.strncpy(addr.sun_path, a.str, 108)
|
||||
size := C.SUN_LEN(&addr)
|
||||
sockaddr := unsafe { &C.sockaddr(&addr) }
|
||||
res := C.connect(s.handle, sockaddr, size)
|
||||
// if res != 1 {
|
||||
// return none
|
||||
//}
|
||||
if res == 0 {
|
||||
return none
|
||||
}
|
||||
_ := error_code()
|
||||
write_result := s.@select(.write, connect_timeout) ?
|
||||
if write_result {
|
||||
// succeeded
|
||||
return none
|
||||
}
|
||||
except_result := s.@select(.except, connect_timeout) ?
|
||||
if except_result {
|
||||
return err_connect_failed
|
||||
}
|
||||
// otherwise we timed out
|
||||
return err_connect_timed_out
|
||||
}
|
||||
|
||||
pub fn listen_unix(sock string) ?&UnixListener {
|
||||
if sock.len >= 108 {
|
||||
return error('Socket path too long! Max length: 107 chars.')
|
||||
}
|
||||
mut s := new_unix_socket() ?
|
||||
s.path = sock
|
||||
mut addr := C.sockaddr_un{}
|
||||
unsafe { C.memset(&addr, 0, sizeof(C.sockaddr_un)) }
|
||||
addr.sun_family = int(SocketFamily.unix)
|
||||
C.strncpy(addr.sun_path, sock.str, 108)
|
||||
size := C.SUN_LEN(&addr)
|
||||
sockaddr := unsafe { &C.sockaddr(&addr) }
|
||||
socket_error(C.bind(s.handle, sockaddr, size)) ?
|
||||
socket_error(C.listen(s.handle, 128)) ?
|
||||
return &UnixListener{
|
||||
sock: s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_unix(path string) ?&UnixConn {
|
||||
mut s := new_unix_socket() ?
|
||||
s.connect(path) ?
|
||||
return &UnixConn{
|
||||
sock: s
|
||||
read_timeout: tcp_default_read_timeout
|
||||
write_timeout: tcp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut l UnixListener) accept() ?&UnixConn {
|
||||
mut new_handle := C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle <= 0 {
|
||||
l.wait_for_accept() ?
|
||||
new_handle = C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle == -1 || new_handle == 0 {
|
||||
return none
|
||||
}
|
||||
}
|
||||
new_sock := UnixSocket{
|
||||
handle: new_handle
|
||||
}
|
||||
return &UnixConn{
|
||||
sock: new_sock
|
||||
read_timeout: tcp_default_read_timeout
|
||||
write_timeout: tcp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &UnixListener) accept_deadline() ?time.Time {
|
||||
if c.accept_deadline.unix != 0 {
|
||||
return c.accept_deadline
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c UnixListener) set_accept_deadline(deadline time.Time) {
|
||||
c.accept_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (c &UnixListener) accept_timeout() time.Duration {
|
||||
return c.accept_timeout
|
||||
}
|
||||
|
||||
pub fn (mut c UnixListener) set_accept_timeout(t time.Duration) {
|
||||
c.accept_timeout = t
|
||||
}
|
||||
|
||||
pub fn (mut c UnixListener) wait_for_accept() ? {
|
||||
return wait_for_read(c.sock.handle, c.accept_deadline, c.accept_timeout)
|
||||
}
|
||||
|
||||
pub fn (mut c UnixListener) close() ? {
|
||||
c.sock.close() ?
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) close() ? {
|
||||
c.sock.close() ?
|
||||
return none
|
||||
}
|
||||
|
||||
// write_ptr blocks and attempts to write all data
|
||||
pub fn (mut c UnixConn) write_ptr(b byteptr, len int) ? {
|
||||
$if trace_tcp ? {
|
||||
eprintln(
|
||||
'>>> UnixConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||
unsafe { b.vstring_with_len(len) })
|
||||
}
|
||||
unsafe {
|
||||
mut ptr_base := byteptr(b)
|
||||
mut total_sent := 0
|
||||
for total_sent < len {
|
||||
ptr := ptr_base + total_sent
|
||||
remaining := len - total_sent
|
||||
mut sent := C.send(c.sock.handle, ptr, remaining, msg_nosignal)
|
||||
if sent < 0 {
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_write() ?
|
||||
continue
|
||||
} else {
|
||||
wrap_error(code) ?
|
||||
}
|
||||
}
|
||||
total_sent += sent
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
// write blocks and attempts to write all data
|
||||
pub fn (mut c UnixConn) write(bytes []byte) ? {
|
||||
return c.write_ptr(bytes.data, bytes.len)
|
||||
}
|
||||
|
||||
// write_str blocks and attempts to write all data
|
||||
pub fn (mut c UnixConn) write_str(s string) ? {
|
||||
return c.write_ptr(s.str, s.len)
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) read_ptr(buf_ptr byteptr, len int) ?int {
|
||||
mut res := wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ?
|
||||
$if trace_tcp ? {
|
||||
eprintln('<<< UnixConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
if res > 0 {
|
||||
return res
|
||||
}
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_read() ?
|
||||
res = wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ?
|
||||
$if trace_tcp ? {
|
||||
eprintln('<<< UnixConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
return socket_error(res)
|
||||
} else {
|
||||
wrap_error(code) ?
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) read(mut buf []byte) ?int {
|
||||
return c.read_ptr(buf.data, buf.len)
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) read_deadline() ?time.Time {
|
||||
if c.read_deadline.unix == 0 {
|
||||
return c.read_deadline
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) set_read_deadline(deadline time.Time) {
|
||||
c.read_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) write_deadline() ?time.Time {
|
||||
if c.write_deadline.unix == 0 {
|
||||
return c.write_deadline
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) set_write_deadline(deadline time.Time) {
|
||||
c.write_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (c &UnixConn) read_timeout() time.Duration {
|
||||
return c.read_timeout
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) set_read_timeout(t time.Duration) {
|
||||
c.read_timeout = t
|
||||
}
|
||||
|
||||
pub fn (c &UnixConn) write_timeout() time.Duration {
|
||||
return c.write_timeout
|
||||
}
|
||||
|
||||
pub fn (mut c UnixConn) set_write_timeout(t time.Duration) {
|
||||
c.write_timeout = t
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c UnixConn) wait_for_read() ? {
|
||||
return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c UnixConn) wait_for_write() ? {
|
||||
return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout)
|
||||
}
|
||||
|
||||
pub fn (c UnixConn) str() string {
|
||||
s := c.sock.str().replace('\n', ' ').replace(' ', ' ')
|
||||
return 'UnixConn{ write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $s }'
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
module net
|
||||
|
||||
// needed for unix domain sockets support
|
||||
#include <afunix.h>
|
||||
// is not included in CI rn
|
||||
// #include <afunix.h>
|
||||
|
||||
// WsaError is all of the socket errors that WSA provides from WSAGetLastError
|
||||
pub enum WsaError {
|
||||
@ -13,7 +14,6 @@ pub enum WsaError {
|
||||
// A blocking operation was interrupted by a call to WSACancelBlockingCall.
|
||||
//
|
||||
wsaeintr = 10004
|
||||
|
||||
//
|
||||
// MessageId: WSAEBADF
|
||||
//
|
||||
@ -22,7 +22,6 @@ pub enum WsaError {
|
||||
// The file handle supplied is not valid.
|
||||
//
|
||||
wsaebadf = 10009
|
||||
|
||||
//
|
||||
// MessageId: WSAEACCES
|
||||
//
|
||||
@ -31,7 +30,6 @@ pub enum WsaError {
|
||||
// An attempt was made to access a socket in a way forbidden by its access permissions.
|
||||
//
|
||||
wsaeacces = 10013
|
||||
|
||||
//
|
||||
// MessageId: WSAEFAULT
|
||||
//
|
||||
@ -40,7 +38,6 @@ pub enum WsaError {
|
||||
// The system detected an invalid pointer address in attempting to use a pointer argument in a call.
|
||||
//
|
||||
wsaefault = 10014
|
||||
|
||||
//
|
||||
// MessageId: WSAEINVAL
|
||||
//
|
||||
@ -49,7 +46,6 @@ pub enum WsaError {
|
||||
// An invalid argument was supplied.
|
||||
//
|
||||
wsaeinval = 10022
|
||||
|
||||
//
|
||||
// MessageId: WSAEMFILE
|
||||
//
|
||||
@ -58,7 +54,6 @@ pub enum WsaError {
|
||||
// Too many open sockets.
|
||||
//
|
||||
wsaemfile = 10024
|
||||
|
||||
//
|
||||
// MessageId: WSAEWOULDBLOCK
|
||||
//
|
||||
@ -67,7 +62,6 @@ pub enum WsaError {
|
||||
// A non-blocking socket operation could not be completed immediately.
|
||||
//
|
||||
wsaewouldblock = 10035
|
||||
|
||||
//
|
||||
// MessageId: WSAEINPROGRESS
|
||||
//
|
||||
@ -76,7 +70,6 @@ pub enum WsaError {
|
||||
// A blocking operation is currently executing.
|
||||
//
|
||||
wsaeinprogress = 10036
|
||||
|
||||
//
|
||||
// MessageId: WSAEALREADY
|
||||
//
|
||||
@ -85,7 +78,6 @@ pub enum WsaError {
|
||||
// An operation was attempted on a non-blocking socket that already had an operation in progress.
|
||||
//
|
||||
wsaealready = 10037
|
||||
|
||||
//
|
||||
// MessageId: WSAENOTSOCK
|
||||
//
|
||||
@ -94,7 +86,6 @@ pub enum WsaError {
|
||||
// An operation was attempted on something that is not a socket.
|
||||
//
|
||||
wsaenotsock = 10038
|
||||
|
||||
//
|
||||
// MessageId: WSAEDESTADDRREQ
|
||||
//
|
||||
@ -103,7 +94,6 @@ pub enum WsaError {
|
||||
// A required address was omitted from an operation on a socket.
|
||||
//
|
||||
wsaedestaddrreq = 10039
|
||||
|
||||
//
|
||||
// MessageId: WSAEMSGSIZE
|
||||
//
|
||||
@ -112,7 +102,6 @@ pub enum WsaError {
|
||||
// A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself.
|
||||
//
|
||||
wsaemsgsize = 10040
|
||||
|
||||
//
|
||||
// MessageId: WSAEPROTOTYPE
|
||||
//
|
||||
@ -121,7 +110,6 @@ pub enum WsaError {
|
||||
// A protocol was specified in the socket function call that does not support the semantics of the socket type requested.
|
||||
//
|
||||
wsaeprototype = 10041
|
||||
|
||||
//
|
||||
// MessageId: WSAENOPROTOOPT
|
||||
//
|
||||
@ -130,7 +118,6 @@ pub enum WsaError {
|
||||
// An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call.
|
||||
//
|
||||
wsaenoprotoopt = 10042
|
||||
|
||||
//
|
||||
// MessageId: WSAEPROTONOSUPPORT
|
||||
//
|
||||
@ -139,7 +126,6 @@ pub enum WsaError {
|
||||
// The requested protocol has not been configured into the system, or no implementation for it exists.
|
||||
//
|
||||
wsaeprotonosupport = 10043
|
||||
|
||||
//
|
||||
// MessageId: WSAESOCKTNOSUPPORT
|
||||
//
|
||||
@ -148,7 +134,6 @@ pub enum WsaError {
|
||||
// The support for the specified socket type does not exist in this address family.
|
||||
//
|
||||
wsaesocktnosupport = 10044
|
||||
|
||||
//
|
||||
// MessageId: WSAEOPNOTSUPP
|
||||
//
|
||||
@ -157,7 +142,6 @@ pub enum WsaError {
|
||||
// The attempted operation is not supported for the type of object referenced.
|
||||
//
|
||||
wsaeopnotsupp = 10045
|
||||
|
||||
//
|
||||
// MessageId: WSAEPFNOSUPPORT
|
||||
//
|
||||
@ -166,7 +150,6 @@ pub enum WsaError {
|
||||
// The protocol family has not been configured into the system or no implementation for it exists.
|
||||
//
|
||||
wsaepfnosupport = 10046
|
||||
|
||||
//
|
||||
// MessageId: WSAEAFNOSUPPORT
|
||||
//
|
||||
@ -175,7 +158,6 @@ pub enum WsaError {
|
||||
// An address incompatible with the requested protocol was used.
|
||||
//
|
||||
wsaeafnosupport = 10047
|
||||
|
||||
//
|
||||
// MessageId: WSAEADDRINUSE
|
||||
//
|
||||
@ -184,7 +166,6 @@ pub enum WsaError {
|
||||
// Only one usage of each socket address (protocol/network address/port) is normally permitted.
|
||||
//
|
||||
wsaeaddrinuse = 10048
|
||||
|
||||
//
|
||||
// MessageId: WSAEADDRNOTAVAIL
|
||||
//
|
||||
@ -193,7 +174,6 @@ pub enum WsaError {
|
||||
// The requested address is not valid in its context.
|
||||
//
|
||||
wsaeaddrnotavail = 10049
|
||||
|
||||
//
|
||||
// MessageId: WSAENETDOWN
|
||||
//
|
||||
@ -202,7 +182,6 @@ pub enum WsaError {
|
||||
// A socket operation encountered a dead network.
|
||||
//
|
||||
wsaenetdown = 10050
|
||||
|
||||
//
|
||||
// MessageId: WSAENETUNREACH
|
||||
//
|
||||
@ -211,7 +190,6 @@ pub enum WsaError {
|
||||
// A socket operation was attempted to an unreachable network.
|
||||
//
|
||||
wsaenetunreach = 10051
|
||||
|
||||
//
|
||||
// MessageId: WSAENETRESET
|
||||
//
|
||||
@ -220,7 +198,6 @@ pub enum WsaError {
|
||||
// The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress.
|
||||
//
|
||||
wsaenetreset = 10052
|
||||
|
||||
//
|
||||
// MessageId: WSAECONNABORTED
|
||||
//
|
||||
@ -229,7 +206,6 @@ pub enum WsaError {
|
||||
// An established connection was aborted by the software in your host machine.
|
||||
//
|
||||
wsaeconnaborted = 10053
|
||||
|
||||
//
|
||||
// MessageId: WSAECONNRESET
|
||||
//
|
||||
@ -238,7 +214,6 @@ pub enum WsaError {
|
||||
// An existing connection was forcibly closed by the remote host.
|
||||
//
|
||||
wsaeconnreset = 10054
|
||||
|
||||
//
|
||||
// MessageId: WSAENOBUFS
|
||||
//
|
||||
@ -247,7 +222,6 @@ pub enum WsaError {
|
||||
// An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
|
||||
//
|
||||
wsaenobufs = 10055
|
||||
|
||||
//
|
||||
// MessageId: WSAEISCONN
|
||||
//
|
||||
@ -256,7 +230,6 @@ pub enum WsaError {
|
||||
// A connect request was made on an already connected socket.
|
||||
//
|
||||
wsaeisconn = 10056
|
||||
|
||||
//
|
||||
// MessageId: WSAENOTCONN
|
||||
//
|
||||
@ -265,7 +238,6 @@ pub enum WsaError {
|
||||
// A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.
|
||||
//
|
||||
wsaenotconn = 10057
|
||||
|
||||
//
|
||||
// MessageId: WSAESHUTDOWN
|
||||
//
|
||||
@ -274,7 +246,6 @@ pub enum WsaError {
|
||||
// A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call.
|
||||
//
|
||||
wsaeshutdown = 10058
|
||||
|
||||
//
|
||||
// MessageId: WSAETOOMANYREFS
|
||||
//
|
||||
@ -283,7 +254,6 @@ pub enum WsaError {
|
||||
// Too many references to some kernel object.
|
||||
//
|
||||
wsaetoomanyrefs = 10059
|
||||
|
||||
//
|
||||
// MessageId: WSAETIMEDOUT
|
||||
//
|
||||
@ -292,7 +262,6 @@ pub enum WsaError {
|
||||
// A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
|
||||
//
|
||||
wsaetimedout = 10060
|
||||
|
||||
//
|
||||
// MessageId: WSAECONNREFUSED
|
||||
//
|
||||
@ -301,7 +270,6 @@ pub enum WsaError {
|
||||
// No connection could be made because the target machine actively refused it.
|
||||
//
|
||||
wsaeconnrefused = 10061
|
||||
|
||||
//
|
||||
// MessageId: WSAELOOP
|
||||
//
|
||||
@ -310,7 +278,6 @@ pub enum WsaError {
|
||||
// Cannot translate name.
|
||||
//
|
||||
wsaeloop = 10062
|
||||
|
||||
//
|
||||
// MessageId: WSAENAMETOOLONG
|
||||
//
|
||||
@ -319,7 +286,6 @@ pub enum WsaError {
|
||||
// Name component or name was too long.
|
||||
//
|
||||
wsaenametoolong = 10063
|
||||
|
||||
//
|
||||
// MessageId: WSAEHOSTDOWN
|
||||
//
|
||||
@ -328,7 +294,6 @@ pub enum WsaError {
|
||||
// A socket operation failed because the destination host was down.
|
||||
//
|
||||
wsaehostdown = 10064
|
||||
|
||||
//
|
||||
// MessageId: WSAEHOSTUNREACH
|
||||
//
|
||||
@ -337,7 +302,6 @@ pub enum WsaError {
|
||||
// A socket operation was attempted to an unreachable host.
|
||||
//
|
||||
wsaehostunreach = 10065
|
||||
|
||||
//
|
||||
// MessageId: WSAENOTEMPTY
|
||||
//
|
||||
@ -346,7 +310,6 @@ pub enum WsaError {
|
||||
// Cannot remove a directory that is not empty.
|
||||
//
|
||||
wsaenotempty = 10066
|
||||
|
||||
//
|
||||
// MessageId: WSAEPROCLIM
|
||||
//
|
||||
@ -355,7 +318,6 @@ pub enum WsaError {
|
||||
// A Windows Sockets implementation may have a limit on the number of applications that may use it simultaneously.
|
||||
//
|
||||
wsaeproclim = 10067
|
||||
|
||||
//
|
||||
// MessageId: WSAEUSERS
|
||||
//
|
||||
@ -364,7 +326,6 @@ pub enum WsaError {
|
||||
// Ran out of quota.
|
||||
//
|
||||
wsaeusers = 10068
|
||||
|
||||
//
|
||||
// MessageId: WSAEDQUOT
|
||||
//
|
||||
@ -373,7 +334,6 @@ pub enum WsaError {
|
||||
// Ran out of disk quota.
|
||||
//
|
||||
wsaedquot = 10069
|
||||
|
||||
//
|
||||
// MessageId: WSAESTALE
|
||||
//
|
||||
@ -382,7 +342,6 @@ pub enum WsaError {
|
||||
// File handle reference is no longer available.
|
||||
//
|
||||
wsaestale = 10070
|
||||
|
||||
//
|
||||
// MessageId: WSAEREMOTE
|
||||
//
|
||||
@ -391,7 +350,6 @@ pub enum WsaError {
|
||||
// Item is not available locally.
|
||||
//
|
||||
wsaeremote = 10071
|
||||
|
||||
//
|
||||
// MessageId: WSASYSNOTREADY
|
||||
//
|
||||
@ -400,7 +358,6 @@ pub enum WsaError {
|
||||
// WSAStartup cannot function at this time because the underlying system it uses to provide network services is currently unavailable.
|
||||
//
|
||||
wsasysnotready = 10091
|
||||
|
||||
//
|
||||
// MessageId: WSAVERNOTSUPPORTED
|
||||
//
|
||||
@ -409,7 +366,6 @@ pub enum WsaError {
|
||||
// The Windows Sockets version requested is not supported.
|
||||
//
|
||||
wsavernotsupported = 10092
|
||||
|
||||
//
|
||||
// MessageId: WSANOTINITIALISED
|
||||
//
|
||||
@ -418,7 +374,6 @@ pub enum WsaError {
|
||||
// Either the application has not called WSAStartup, or WSAStartup failed.
|
||||
//
|
||||
wsanotinitialised = 10093
|
||||
|
||||
//
|
||||
// MessageId: WSAEDISCON
|
||||
//
|
||||
@ -427,7 +382,6 @@ pub enum WsaError {
|
||||
// Returned by WSARecv or WSARecvFrom to indicate the remote party has initiated a graceful shutdown sequence.
|
||||
//
|
||||
wsaediscon = 10101
|
||||
|
||||
//
|
||||
// MessageId: WSAENOMORE
|
||||
//
|
||||
@ -436,7 +390,6 @@ pub enum WsaError {
|
||||
// No more results can be returned by WSALookupServiceNext.
|
||||
//
|
||||
wsaenomore = 10102
|
||||
|
||||
//
|
||||
// MessageId: WSAECANCELLED
|
||||
//
|
||||
@ -445,7 +398,6 @@ pub enum WsaError {
|
||||
// A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled.
|
||||
//
|
||||
wsaecancelled = 10103
|
||||
|
||||
//
|
||||
// MessageId: WSAEINVALIDPROCTABLE
|
||||
//
|
||||
@ -454,7 +406,6 @@ pub enum WsaError {
|
||||
// The procedure call table is invalid.
|
||||
//
|
||||
wsaeinvalidproctable = 10104
|
||||
|
||||
//
|
||||
// MessageId: WSAEINVALIDPROVIDER
|
||||
//
|
||||
@ -463,7 +414,6 @@ pub enum WsaError {
|
||||
// The requested service provider is invalid.
|
||||
//
|
||||
wsaeinvalidprovider = 10105
|
||||
|
||||
//
|
||||
// MessageId: WSAEPROVIDERFAILEDINIT
|
||||
//
|
||||
@ -472,7 +422,6 @@ pub enum WsaError {
|
||||
// The requested service provider could not be loaded or initialized.
|
||||
//
|
||||
wsaeproviderfailedinit = 10106
|
||||
|
||||
//
|
||||
// MessageId: WSASYSCALLFAILURE
|
||||
//
|
||||
@ -481,7 +430,6 @@ pub enum WsaError {
|
||||
// A system call has failed.
|
||||
//
|
||||
wsasyscallfailure = 10107
|
||||
|
||||
//
|
||||
// MessageId: WSASERVICE_NOT_FOUND
|
||||
//
|
||||
@ -490,7 +438,6 @@ pub enum WsaError {
|
||||
// No such service is known. The service cannot be found in the specified name space.
|
||||
//
|
||||
wsaservice_not_found = 10108
|
||||
|
||||
//
|
||||
// MessageId: WSATYPE_NOT_FOUND
|
||||
//
|
||||
@ -499,7 +446,6 @@ pub enum WsaError {
|
||||
// The specified class was not found.
|
||||
//
|
||||
wsatype_not_found = 10109
|
||||
|
||||
//
|
||||
// MessageId: WSA_E_NO_MORE
|
||||
//
|
||||
@ -508,7 +454,6 @@ pub enum WsaError {
|
||||
// No more results can be returned by WSALookupServiceNext.
|
||||
//
|
||||
wsa_e_no_more = 10110
|
||||
|
||||
//
|
||||
// MessageId: WSA_E_CANCELLED
|
||||
//
|
||||
@ -517,7 +462,6 @@ pub enum WsaError {
|
||||
// A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled.
|
||||
//
|
||||
wsa_e_cancelled = 10111
|
||||
|
||||
//
|
||||
// MessageId: WSAEREFUSED
|
||||
//
|
||||
@ -526,7 +470,6 @@ pub enum WsaError {
|
||||
// A database query failed because it was actively refused.
|
||||
//
|
||||
wsaerefused = 10112
|
||||
|
||||
//
|
||||
// MessageId: WSAHOST_NOT_FOUND
|
||||
//
|
||||
@ -535,7 +478,6 @@ pub enum WsaError {
|
||||
// No such host is known.
|
||||
//
|
||||
wsahost_not_found = 11001
|
||||
|
||||
//
|
||||
// MessageId: WSATRY_AGAIN
|
||||
//
|
||||
@ -544,7 +486,6 @@ pub enum WsaError {
|
||||
// This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server.
|
||||
//
|
||||
wsatry_again = 11002
|
||||
|
||||
//
|
||||
// MessageId: WSANO_RECOVERY
|
||||
//
|
||||
@ -553,7 +494,6 @@ pub enum WsaError {
|
||||
// A non-recoverable error occurred during a database lookup.
|
||||
//
|
||||
wsano_recovery = 11003
|
||||
|
||||
//
|
||||
// MessageId: WSANO_DATA
|
||||
//
|
||||
@ -562,7 +502,6 @@ pub enum WsaError {
|
||||
// The requested name is valid, but no data of the requested type was found.
|
||||
//
|
||||
wsano_data = 11004
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_RECEIVERS
|
||||
//
|
||||
@ -571,7 +510,6 @@ pub enum WsaError {
|
||||
// At least one reserve has arrived.
|
||||
//
|
||||
wsa_qos_receivers = 11005
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_SENDERS
|
||||
//
|
||||
@ -580,7 +518,6 @@ pub enum WsaError {
|
||||
// At least one path has arrived.
|
||||
//
|
||||
wsa_qos_senders = 11006
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_NO_SENDERS
|
||||
//
|
||||
@ -589,7 +526,6 @@ pub enum WsaError {
|
||||
// There are no senders.
|
||||
//
|
||||
wsa_qos_no_senders = 11007
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_NO_RECEIVERS
|
||||
//
|
||||
@ -598,7 +534,6 @@ pub enum WsaError {
|
||||
// There are no receivers.
|
||||
//
|
||||
wsa_qos_no_receivers = 11008
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_REQUEST_CONFIRMED
|
||||
//
|
||||
@ -607,7 +542,6 @@ pub enum WsaError {
|
||||
// Reserve has been confirmed.
|
||||
//
|
||||
wsa_qos_request_confirmed = 11009
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_ADMISSION_FAILURE
|
||||
//
|
||||
@ -616,7 +550,6 @@ pub enum WsaError {
|
||||
// Error due to lack of resources.
|
||||
//
|
||||
wsa_qos_admission_failure = 11010
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_POLICY_FAILURE
|
||||
//
|
||||
@ -625,7 +558,6 @@ pub enum WsaError {
|
||||
// Rejected for administrative reasons - bad credentials.
|
||||
//
|
||||
wsa_qos_policy_failure = 11011
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_BAD_STYLE
|
||||
//
|
||||
@ -634,7 +566,6 @@ pub enum WsaError {
|
||||
// Unknown or conflicting style.
|
||||
//
|
||||
wsa_qos_bad_style = 11012
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_BAD_OBJECT
|
||||
//
|
||||
@ -643,7 +574,6 @@ pub enum WsaError {
|
||||
// Problem with some part of the filterspec or providerspecific buffer in general.
|
||||
//
|
||||
wsa_qos_bad_object = 11013
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_TRAFFIC_CTRL_ERROR
|
||||
//
|
||||
@ -652,7 +582,6 @@ pub enum WsaError {
|
||||
// Problem with some part of the flowspec.
|
||||
//
|
||||
wsa_qos_traffic_ctrl_error = 11014
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_GENERIC_ERROR
|
||||
//
|
||||
@ -661,7 +590,6 @@ pub enum WsaError {
|
||||
// General QOS error.
|
||||
//
|
||||
wsa_qos_generic_error = 11015
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_ESERVICETYPE
|
||||
//
|
||||
@ -670,7 +598,6 @@ pub enum WsaError {
|
||||
// An invalid or unrecognized service type was found in the flowspec.
|
||||
//
|
||||
wsa_qos_eservicetype = 11016
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EFLOWSPEC
|
||||
//
|
||||
@ -679,7 +606,6 @@ pub enum WsaError {
|
||||
// An invalid or inconsistent flowspec was found in the QOS structure.
|
||||
//
|
||||
wsa_qos_eflowspec = 11017
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EPROVSPECBUF
|
||||
//
|
||||
@ -688,7 +614,6 @@ pub enum WsaError {
|
||||
// Invalid QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_eprovspecbuf = 11018
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EFILTERSTYLE
|
||||
//
|
||||
@ -697,7 +622,6 @@ pub enum WsaError {
|
||||
// An invalid QOS filter style was used.
|
||||
//
|
||||
wsa_qos_efilterstyle = 11019
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EFILTERTYPE
|
||||
//
|
||||
@ -706,7 +630,6 @@ pub enum WsaError {
|
||||
// An invalid QOS filter type was used.
|
||||
//
|
||||
wsa_qos_efiltertype = 11020
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EFILTERCOUNT
|
||||
//
|
||||
@ -715,7 +638,6 @@ pub enum WsaError {
|
||||
// An incorrect number of QOS FILTERSPECs were specified in the FLOWDESCRIPTOR.
|
||||
//
|
||||
wsa_qos_efiltercount = 11021
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EOBJLENGTH
|
||||
//
|
||||
@ -724,7 +646,6 @@ pub enum WsaError {
|
||||
// An object with an invalid ObjectLength field was specified in the QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_eobjlength = 11022
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EFLOWCOUNT
|
||||
//
|
||||
@ -733,7 +654,6 @@ pub enum WsaError {
|
||||
// An incorrect number of flow descriptors was specified in the QOS structure.
|
||||
//
|
||||
wsa_qos_eflowcount = 11023
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EUNKOWNPSOBJ
|
||||
//
|
||||
@ -742,7 +662,6 @@ pub enum WsaError {
|
||||
// An unrecognized object was found in the QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_eunkownpsobj = 11024
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EPOLICYOBJ
|
||||
//
|
||||
@ -751,7 +670,6 @@ pub enum WsaError {
|
||||
// An invalid policy object was found in the QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_epolicyobj = 11025
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EFLOWDESC
|
||||
//
|
||||
@ -760,7 +678,6 @@ pub enum WsaError {
|
||||
// An invalid QOS flow descriptor was found in the flow descriptor list.
|
||||
//
|
||||
wsa_qos_eflowdesc = 11026
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EPSFLOWSPEC
|
||||
//
|
||||
@ -769,7 +686,6 @@ pub enum WsaError {
|
||||
// An invalid or inconsistent flowspec was found in the QOS provider specific buffer.
|
||||
//
|
||||
wsa_qos_epsflowspec = 11027
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_EPSFILTERSPEC
|
||||
//
|
||||
@ -778,7 +694,6 @@ pub enum WsaError {
|
||||
// An invalid FILTERSPEC was found in the QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_epsfilterspec = 11028
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_ESDMODEOBJ
|
||||
//
|
||||
@ -787,7 +702,6 @@ pub enum WsaError {
|
||||
// An invalid shape discard mode object was found in the QOS provider specific buffer.
|
||||
//
|
||||
wsa_qos_esdmodeobj = 11029
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_ESHAPERATEOBJ
|
||||
//
|
||||
@ -796,7 +710,6 @@ pub enum WsaError {
|
||||
// An invalid shaping rate object was found in the QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_eshaperateobj = 11030
|
||||
|
||||
//
|
||||
// MessageId: WSA_QOS_RESERVED_PETYPE
|
||||
//
|
||||
@ -805,7 +718,6 @@ pub enum WsaError {
|
||||
// A reserved policy element was found in the QOS provider-specific buffer.
|
||||
//
|
||||
wsa_qos_reserved_petype = 11031
|
||||
|
||||
//
|
||||
// MessageId: WSA_SECURE_HOST_NOT_FOUND
|
||||
//
|
||||
@ -814,7 +726,6 @@ pub enum WsaError {
|
||||
// No such host is known securely.
|
||||
//
|
||||
wsa_secure_host_not_found = 11032
|
||||
|
||||
//
|
||||
// MessageId: WSA_IPSEC_NAME_POLICY_ERROR
|
||||
//
|
||||
@ -841,9 +752,9 @@ const (
|
||||
|
||||
// Constants that windows needs
|
||||
const (
|
||||
fionbio = C.FIONBIO
|
||||
fionbio = C.FIONBIO
|
||||
msg_nosignal = 0
|
||||
wsa_v22 = 0x202 // C.MAKEWORD(2, 2)
|
||||
wsa_v22 = 0x202 // C.MAKEWORD(2, 2)
|
||||
)
|
||||
|
||||
// Error code returns the last socket error
|
||||
@ -853,18 +764,18 @@ fn error_code() int {
|
||||
|
||||
struct C.WSAData {
|
||||
mut:
|
||||
wVersion u16
|
||||
wHighVersion u16
|
||||
szDescription [257]byte
|
||||
wVersion u16
|
||||
wHighVersion u16
|
||||
szDescription [257]byte
|
||||
szSystemStatus [129]byte
|
||||
iMaxSockets u16
|
||||
iMaxUdpDg u16
|
||||
lpVendorInfo byteptr
|
||||
iMaxSockets u16
|
||||
iMaxUdpDg u16
|
||||
lpVendorInfo byteptr
|
||||
}
|
||||
|
||||
fn init() {
|
||||
mut wsadata := C.WSAData{}
|
||||
res := C.WSAStartup(wsa_v22, &wsadata)
|
||||
res := C.WSAStartup(net.wsa_v22, &wsadata)
|
||||
if res != 0 {
|
||||
panic('socket: WSAStartup failed')
|
||||
}
|
||||
|
97
vlib/net/unix/aasocket.c.v
Normal file
97
vlib/net/unix/aasocket.c.v
Normal file
@ -0,0 +1,97 @@
|
||||
module unix
|
||||
|
||||
// Select represents a select operation
|
||||
enum Select {
|
||||
read
|
||||
write
|
||||
except
|
||||
}
|
||||
|
||||
// SocketType are the available sockets
|
||||
enum SocketType {
|
||||
dgram = C.SOCK_DGRAM
|
||||
stream = C.SOCK_STREAM
|
||||
seqpacket = C.SOCK_SEQPACKET
|
||||
}
|
||||
|
||||
struct C.sockaddr {
|
||||
sa_family u16
|
||||
}
|
||||
|
||||
struct C.sockaddr_un {
|
||||
mut:
|
||||
sun_family int
|
||||
sun_path charptr
|
||||
}
|
||||
|
||||
struct C.addrinfo {
|
||||
mut:
|
||||
ai_family int
|
||||
ai_socktype int
|
||||
ai_flags int
|
||||
ai_protocol int
|
||||
ai_addrlen int
|
||||
ai_addr voidptr
|
||||
ai_canonname voidptr
|
||||
ai_next voidptr
|
||||
}
|
||||
|
||||
struct C.sockaddr_storage {
|
||||
}
|
||||
|
||||
fn C.socket() int
|
||||
|
||||
fn C.setsockopt() int
|
||||
|
||||
fn C.htonl() int
|
||||
|
||||
fn C.htons() int
|
||||
|
||||
fn C.bind() int
|
||||
|
||||
fn C.listen() int
|
||||
|
||||
fn C.accept() int
|
||||
|
||||
fn C.getaddrinfo() int
|
||||
|
||||
fn C.connect() int
|
||||
|
||||
fn C.send() int
|
||||
|
||||
fn C.sendto() int
|
||||
|
||||
fn C.recv() int
|
||||
|
||||
fn C.recvfrom() int
|
||||
|
||||
fn C.shutdown() int
|
||||
|
||||
fn C.ntohs() int
|
||||
|
||||
fn C.getpeername() int
|
||||
|
||||
fn C.inet_ntop(af int, src voidptr, dst charptr, dst_size int) charptr
|
||||
|
||||
fn C.WSAAddressToStringA() int
|
||||
|
||||
fn C.getsockname() int
|
||||
|
||||
// defined in builtin
|
||||
// fn C.read() int
|
||||
// fn C.close() int
|
||||
|
||||
fn C.ioctlsocket() int
|
||||
|
||||
fn C.fcntl() int
|
||||
|
||||
fn C.@select() int
|
||||
|
||||
fn C.FD_ZERO()
|
||||
|
||||
fn C.FD_SET()
|
||||
|
||||
fn C.FD_ISSET() bool
|
||||
|
||||
[typedef]
|
||||
struct C.fd_set {}
|
127
vlib/net/unix/common.v
Normal file
127
vlib/net/unix/common.v
Normal file
@ -0,0 +1,127 @@
|
||||
module unix
|
||||
|
||||
import time
|
||||
import net
|
||||
|
||||
fn C.SUN_LEN(C.sockaddr_un) int
|
||||
|
||||
fn C.strncpy(charptr, charptr, int)
|
||||
|
||||
// Shutdown shutsdown a socket and closes it
|
||||
fn shutdown(handle int) ? {
|
||||
$if windows {
|
||||
C.shutdown(handle, C.SD_BOTH)
|
||||
net.socket_error(C.closesocket(handle)) ?
|
||||
} $else {
|
||||
C.shutdown(handle, C.SHUT_RDWR)
|
||||
net.socket_error(C.close(handle)) ?
|
||||
}
|
||||
|
||||
return none
|
||||
}
|
||||
|
||||
// Select waits for an io operation (specified by parameter `test`) to be available
|
||||
fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
set := C.fd_set{}
|
||||
|
||||
C.FD_ZERO(&set)
|
||||
C.FD_SET(handle, &set)
|
||||
|
||||
seconds := timeout.milliseconds() / 1000
|
||||
microseconds := timeout - (seconds * time.second)
|
||||
|
||||
mut tt := C.timeval{
|
||||
tv_sec: u64(seconds)
|
||||
tv_usec: u64(microseconds)
|
||||
}
|
||||
|
||||
mut timeval_timeout := &tt
|
||||
|
||||
// infinite timeout is signaled by passing null as the timeout to
|
||||
// select
|
||||
if timeout == unix.infinite_timeout {
|
||||
timeval_timeout = &C.timeval(0)
|
||||
}
|
||||
|
||||
match test {
|
||||
.read {
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout)) ?
|
||||
}
|
||||
.write {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout)) ?
|
||||
}
|
||||
.except {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout)) ?
|
||||
}
|
||||
}
|
||||
|
||||
return C.FD_ISSET(handle, &set)
|
||||
}
|
||||
|
||||
// wait_for_common wraps the common wait code
|
||||
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
|
||||
if deadline.unix == 0 {
|
||||
// only accept infinite_timeout as a valid
|
||||
// negative timeout - it is handled in @select however
|
||||
if timeout < 0 && timeout != unix.infinite_timeout {
|
||||
return net.err_timed_out
|
||||
}
|
||||
ready := @select(handle, test, timeout) ?
|
||||
if ready {
|
||||
return none
|
||||
}
|
||||
return net.err_timed_out
|
||||
}
|
||||
// Convert the deadline into a timeout
|
||||
// and use that
|
||||
d_timeout := deadline.unix - time.now().unix
|
||||
if d_timeout < 0 {
|
||||
// deadline is in the past so this has already
|
||||
// timed out
|
||||
return net.err_timed_out
|
||||
}
|
||||
|
||||
ready := @select(handle, test, d_timeout) ?
|
||||
if ready {
|
||||
return none
|
||||
}
|
||||
return net.err_timed_out
|
||||
}
|
||||
|
||||
// wait_for_write waits for a write io operation to be available
|
||||
fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
return wait_for_common(handle, deadline, timeout, .write)
|
||||
}
|
||||
|
||||
// wait_for_read waits for a read io operation to be available
|
||||
fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
return wait_for_common(handle, deadline, timeout, .read)
|
||||
}
|
||||
|
||||
// no_deadline should be given to functions when no deadline is wanted (i.e. all functions
|
||||
// return instantly)
|
||||
const (
|
||||
no_deadline = time.Time{
|
||||
unix: 0
|
||||
}
|
||||
)
|
||||
|
||||
// no_timeout should be given to functions when no timeout is wanted (i.e. all functions
|
||||
// return instantly)
|
||||
const (
|
||||
no_timeout = time.Duration(0)
|
||||
)
|
||||
|
||||
// infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions
|
||||
// only ever return with data)
|
||||
const (
|
||||
infinite_timeout = time.Duration(-1)
|
||||
)
|
||||
|
||||
[inline]
|
||||
fn wrap_read_result(result int) ?int {
|
||||
if result != 0 {
|
||||
return result
|
||||
}
|
||||
return none
|
||||
}
|
288
vlib/net/unix/stream_nix.v
Normal file
288
vlib/net/unix/stream_nix.v
Normal file
@ -0,0 +1,288 @@
|
||||
module unix
|
||||
|
||||
import time
|
||||
import os
|
||||
import net
|
||||
|
||||
const (
|
||||
unix_default_read_timeout = 30 * time.second
|
||||
unix_default_write_timeout = 30 * time.second
|
||||
connect_timeout = 5 * time.second
|
||||
msg_nosignal = 0x4000
|
||||
)
|
||||
|
||||
struct StreamSocket {
|
||||
pub:
|
||||
handle int
|
||||
mut:
|
||||
path string
|
||||
}
|
||||
|
||||
struct StreamConn {
|
||||
pub mut:
|
||||
sock StreamSocket
|
||||
mut:
|
||||
write_deadline time.Time
|
||||
read_deadline time.Time
|
||||
read_timeout time.Duration
|
||||
write_timeout time.Duration
|
||||
}
|
||||
|
||||
struct StreamListener {
|
||||
pub mut:
|
||||
sock StreamSocket
|
||||
mut:
|
||||
accept_timeout time.Duration
|
||||
accept_deadline time.Time
|
||||
}
|
||||
|
||||
fn error_code() int {
|
||||
return C.errno
|
||||
}
|
||||
|
||||
fn new_stream_socket() ?StreamSocket {
|
||||
sockfd := net.socket_error(C.socket(C.AF_UNIX, SocketType.stream, 0)) ?
|
||||
mut s := StreamSocket{
|
||||
handle: sockfd
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
fn (mut s StreamSocket) close() ? {
|
||||
os.rm(s.path) ?
|
||||
return shutdown(s.handle)
|
||||
}
|
||||
|
||||
fn (mut s StreamSocket) @select(test Select, timeout time.Duration) ?bool {
|
||||
return @select(s.handle, test, timeout)
|
||||
}
|
||||
|
||||
fn (mut s StreamSocket) connect(a string) ? {
|
||||
if a.len >= 108 {
|
||||
return error('Socket path too long! Max length: 107 chars.')
|
||||
}
|
||||
mut addr := C.sockaddr_un{}
|
||||
unsafe { C.memset(&addr, 0, sizeof(C.sockaddr_un)) }
|
||||
addr.sun_family = C.AF_UNIX
|
||||
C.strncpy(addr.sun_path, a.str, 108)
|
||||
size := C.SUN_LEN(&addr)
|
||||
sockaddr := unsafe { &C.sockaddr(&addr) }
|
||||
res := C.connect(s.handle, sockaddr, size)
|
||||
// if res != 1 {
|
||||
// return none
|
||||
//}
|
||||
if res == 0 {
|
||||
return none
|
||||
}
|
||||
_ := error_code()
|
||||
write_result := s.@select(.write, unix.connect_timeout) ?
|
||||
if write_result {
|
||||
// succeeded
|
||||
return none
|
||||
}
|
||||
except_result := s.@select(.except, unix.connect_timeout) ?
|
||||
if except_result {
|
||||
return net.err_connect_failed
|
||||
}
|
||||
// otherwise we timed out
|
||||
return net.err_connect_timed_out
|
||||
}
|
||||
|
||||
pub fn listen_stream(sock string) ?&StreamListener {
|
||||
if sock.len >= 108 {
|
||||
return error('Socket path too long! Max length: 107 chars.')
|
||||
}
|
||||
mut s := new_stream_socket() ?
|
||||
s.path = sock
|
||||
mut addr := C.sockaddr_un{}
|
||||
unsafe { C.memset(&addr, 0, sizeof(C.sockaddr_un)) }
|
||||
addr.sun_family = C.AF_UNIX
|
||||
C.strncpy(addr.sun_path, sock.str, 108)
|
||||
size := C.SUN_LEN(&addr)
|
||||
sockaddr := unsafe { &C.sockaddr(&addr) }
|
||||
net.socket_error(C.bind(s.handle, sockaddr, size)) ?
|
||||
net.socket_error(C.listen(s.handle, 128)) ?
|
||||
return &StreamListener{
|
||||
sock: s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_stream(path string) ?&StreamConn {
|
||||
mut s := new_stream_socket() ?
|
||||
s.connect(path) ?
|
||||
return &StreamConn{
|
||||
sock: s
|
||||
read_timeout: unix.unix_default_read_timeout
|
||||
write_timeout: unix.unix_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut l StreamListener) accept() ?&StreamConn {
|
||||
mut new_handle := C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle <= 0 {
|
||||
l.wait_for_accept() ?
|
||||
new_handle = C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle == -1 || new_handle == 0 {
|
||||
return none
|
||||
}
|
||||
}
|
||||
new_sock := StreamSocket{
|
||||
handle: new_handle
|
||||
}
|
||||
return &StreamConn{
|
||||
sock: new_sock
|
||||
read_timeout: unix.unix_default_read_timeout
|
||||
write_timeout: unix.unix_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &StreamListener) accept_deadline() ?time.Time {
|
||||
if c.accept_deadline.unix != 0 {
|
||||
return c.accept_deadline
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c StreamListener) set_accept_deadline(deadline time.Time) {
|
||||
c.accept_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (c &StreamListener) accept_timeout() time.Duration {
|
||||
return c.accept_timeout
|
||||
}
|
||||
|
||||
pub fn (mut c StreamListener) set_accept_timeout(t time.Duration) {
|
||||
c.accept_timeout = t
|
||||
}
|
||||
|
||||
pub fn (mut c StreamListener) wait_for_accept() ? {
|
||||
return wait_for_read(c.sock.handle, c.accept_deadline, c.accept_timeout)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamListener) close() ? {
|
||||
c.sock.close() ?
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) close() ? {
|
||||
c.sock.close() ?
|
||||
return none
|
||||
}
|
||||
|
||||
// write_ptr blocks and attempts to write all data
|
||||
pub fn (mut c StreamConn) write_ptr(b byteptr, len int) ? {
|
||||
$if trace_unix ? {
|
||||
eprintln(
|
||||
'>>> StreamConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||
unsafe { b.vstring_with_len(len) })
|
||||
}
|
||||
unsafe {
|
||||
mut ptr_base := byteptr(b)
|
||||
mut total_sent := 0
|
||||
for total_sent < len {
|
||||
ptr := ptr_base + total_sent
|
||||
remaining := len - total_sent
|
||||
mut sent := C.send(c.sock.handle, ptr, remaining, unix.msg_nosignal)
|
||||
if sent < 0 {
|
||||
code := error_code()
|
||||
if code == int(net.error_ewouldblock) {
|
||||
c.wait_for_write() ?
|
||||
continue
|
||||
} else {
|
||||
net.wrap_error(code) ?
|
||||
}
|
||||
}
|
||||
total_sent += sent
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
// write blocks and attempts to write all data
|
||||
pub fn (mut c StreamConn) write(bytes []byte) ? {
|
||||
return c.write_ptr(bytes.data, bytes.len)
|
||||
}
|
||||
|
||||
// write_str blocks and attempts to write all data
|
||||
pub fn (mut c StreamConn) write_str(s string) ? {
|
||||
return c.write_ptr(s.str, s.len)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) read_ptr(buf_ptr byteptr, len int) ?int {
|
||||
mut res := wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ?
|
||||
$if trace_unix ? {
|
||||
eprintln('<<< StreamConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
if res > 0 {
|
||||
return res
|
||||
}
|
||||
code := error_code()
|
||||
if code == int(net.error_ewouldblock) {
|
||||
c.wait_for_read() ?
|
||||
res = wrap_read_result(C.recv(c.sock.handle, buf_ptr, len, 0)) ?
|
||||
$if trace_unix ? {
|
||||
eprintln('<<< StreamConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
return net.socket_error(res)
|
||||
} else {
|
||||
net.wrap_error(code) ?
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) read(mut buf []byte) ?int {
|
||||
return c.read_ptr(buf.data, buf.len)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) read_deadline() ?time.Time {
|
||||
if c.read_deadline.unix == 0 {
|
||||
return c.read_deadline
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) set_read_deadline(deadline time.Time) {
|
||||
c.read_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) write_deadline() ?time.Time {
|
||||
if c.write_deadline.unix == 0 {
|
||||
return c.write_deadline
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) set_write_deadline(deadline time.Time) {
|
||||
c.write_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (c &StreamConn) read_timeout() time.Duration {
|
||||
return c.read_timeout
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) set_read_timeout(t time.Duration) {
|
||||
c.read_timeout = t
|
||||
}
|
||||
|
||||
pub fn (c &StreamConn) write_timeout() time.Duration {
|
||||
return c.write_timeout
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) set_write_timeout(t time.Duration) {
|
||||
c.write_timeout = t
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c StreamConn) wait_for_read() ? {
|
||||
return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c StreamConn) wait_for_write() ? {
|
||||
return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout)
|
||||
}
|
||||
|
||||
pub fn (c StreamConn) str() string {
|
||||
s := c.sock.str().replace('\n', ' ').replace(' ', ' ')
|
||||
return 'StreamConn{ write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $s }'
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import net
|
||||
import net.unix
|
||||
|
||||
const (
|
||||
test_port = 'test'
|
||||
)
|
||||
|
||||
fn handle_conn(mut c net.UnixConn) {
|
||||
fn handle_conn(mut c unix.StreamConn) {
|
||||
for {
|
||||
mut buf := []byte{len: 100, init: 0}
|
||||
read := c.read(mut buf) or {
|
||||
@ -18,7 +18,7 @@ fn handle_conn(mut c net.UnixConn) {
|
||||
}
|
||||
}
|
||||
|
||||
fn echo_server(mut l net.UnixListener) ? {
|
||||
fn echo_server(mut l unix.StreamListener) ? {
|
||||
for {
|
||||
mut new_conn := l.accept() or { continue }
|
||||
go handle_conn(mut new_conn)
|
||||
@ -27,7 +27,7 @@ fn echo_server(mut l net.UnixListener) ? {
|
||||
}
|
||||
|
||||
fn echo() ? {
|
||||
mut c := net.connect_unix('test') ?
|
||||
mut c := unix.connect_stream('test') ?
|
||||
defer {
|
||||
c.close() or { }
|
||||
}
|
||||
@ -44,7 +44,7 @@ fn echo() ? {
|
||||
}
|
||||
|
||||
fn test_tcp() {
|
||||
mut l := net.listen_unix(test_port) or { panic(err) }
|
||||
mut l := unix.listen_stream(test_port) or { panic(err) }
|
||||
go echo_server(mut l)
|
||||
echo() or { panic(err) }
|
||||
l.close() or { }
|
Loading…
Reference in New Issue
Block a user