net: move unix socket code to net.unix and skip net/unix/unix_test.v … (#8681)

pull/8673/head^2
bettafish04 2021-02-11 17:51:12 +01:00 committed by GitHub
parent f8db44bb15
commit 9b4f2edbfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 561 additions and 425 deletions

View File

@ -52,7 +52,7 @@ const (
'vlib/net/tcp_simple_client_server_test.v', 'vlib/net/tcp_simple_client_server_test.v',
'vlib/net/tcp_test.v', 'vlib/net/tcp_test.v',
'vlib/net/udp_test.v', 'vlib/net/udp_test.v',
'vlib/net/unix_test.v', 'vlib/net/unix/unix_test.v',
'vlib/orm/orm_test.v', 'vlib/orm/orm_test.v',
'vlib/os/os_test.v', 'vlib/os/os_test.v',
'vlib/dl/dl_test.v', 'vlib/dl/dl_test.v',
@ -189,6 +189,7 @@ const (
'vlib/orm/orm_test.v', 'vlib/orm/orm_test.v',
'vlib/v/tests/orm_sub_struct_test.v', 'vlib/v/tests/orm_sub_struct_test.v',
'vlib/net/websocket/ws_test.v', 'vlib/net/websocket/ws_test.v',
'vlib/net/unix/unix_test.v',
'vlib/x/websocket/websocket_test.v', 'vlib/x/websocket/websocket_test.v',
'vlib/vweb/tests/vweb_test.v', 'vlib/vweb/tests/vweb_test.v',
] ]

View File

@ -16,7 +16,6 @@ pub enum SocketType {
// SocketFamily are the available address families // SocketFamily are the available address families
pub enum SocketFamily { pub enum SocketFamily {
inet = C.AF_INET inet = C.AF_INET
unix = C.AF_UNIX
} }
struct C.in_addr { struct C.in_addr {

View File

@ -6,10 +6,10 @@ import time
fn shutdown(handle int) ? { fn shutdown(handle int) ? {
$if windows { $if windows {
C.shutdown(handle, C.SD_BOTH) C.shutdown(handle, C.SD_BOTH)
socket_error(C.closesocket(handle))? socket_error(C.closesocket(handle)) ?
} $else { } $else {
C.shutdown(handle, C.SHUT_RDWR) C.shutdown(handle, C.SHUT_RDWR)
socket_error(C.close(handle))? socket_error(C.close(handle)) ?
} }
return none 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 // infinite timeout is signaled by passing null as the timeout to
// select // select
if timeout == infinite_timeout { if timeout == net.infinite_timeout {
timeval_timeout = &C.timeval(0) timeval_timeout = &C.timeval(0)
} }
match test { match test {
.read { .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 { .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 { .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 // wait_for_common wraps the common wait code
fn wait_for_common( fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
handle int,
deadline time.Time,
timeout time.Duration,
test Select) ? {
if deadline.unix == 0 { if deadline.unix == 0 {
// only accept infinite_timeout as a valid // only accept infinite_timeout as a valid
// negative timeout - it is handled in @select however // 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 return err_timed_out
} }
ready := @select(handle, test, timeout)? ready := @select(handle, test, timeout) ?
if ready { if ready {
return none return none
} }
@ -80,7 +76,7 @@ fn wait_for_common(
return err_timed_out return err_timed_out
} }
ready := @select(handle, test, d_timeout)? ready := @select(handle, test, d_timeout) ?
if ready { if ready {
return none return none
} }
@ -88,25 +84,21 @@ fn wait_for_common(
} }
// wait_for_write waits for a write io operation to be available // wait_for_write waits for a write io operation to be available
fn wait_for_write( fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ? {
handle int,
deadline time.Time,
timeout time.Duration) ? {
return wait_for_common(handle, deadline, timeout, .write) return wait_for_common(handle, deadline, timeout, .write)
} }
// wait_for_read waits for a read io operation to be available // wait_for_read waits for a read io operation to be available
fn wait_for_read( fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ? {
handle int,
deadline time.Time,
timeout time.Duration) ? {
return wait_for_common(handle, deadline, timeout, .read) return wait_for_common(handle, deadline, timeout, .read)
} }
// no_deadline should be given to functions when no deadline is wanted (i.e. all functions // no_deadline should be given to functions when no deadline is wanted (i.e. all functions
// return instantly) // return instantly)
const ( 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 // no_timeout should be given to functions when no timeout is wanted (i.e. all functions

View File

@ -6,16 +6,18 @@ const (
// Well defined errors that are returned from socket functions // Well defined errors that are returned from socket functions
pub const ( pub const (
err_new_socket_failed = error_with_code('net: new_socket failed to create socket', errors_base+1) err_new_socket_failed = error_with_code('net: new_socket failed to create socket',
err_option_not_settable = error_with_code('net: set_option_xxx option not settable', errors_base+2) errors_base + 1)
err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type', errors_base+3) err_option_not_settable = error_with_code('net: set_option_xxx option not settable',
err_port_out_of_range = error_with_code('', errors_base+5) errors_base + 2)
err_no_udp_remote = error_with_code('', errors_base+6) err_option_wrong_type = error_with_code('net: set_option_xxx option wrong type',
err_connect_failed = error_with_code('net: connect failed', errors_base+7) errors_base + 3)
err_connect_timed_out = error_with_code('net: connect timed out', errors_base+8) err_port_out_of_range = error_with_code('', errors_base + 5)
err_no_udp_remote = error_with_code('', errors_base + 6)
err_timed_out = error_with_code('net: op timed out', errors_base+9) err_connect_failed = error_with_code('net: connect failed', errors_base + 7)
err_timed_out_code = errors_base+9 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 { pub fn socket_error(potential_code int) ?int {
@ -23,10 +25,10 @@ pub fn socket_error(potential_code int) ?int {
if potential_code < 0 { if potential_code < 0 {
last_error_int := C.WSAGetLastError() last_error_int := C.WSAGetLastError()
last_error := wsa_error(last_error_int) 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 { if potential_code < 0 {
last_error := error_code() last_error := error_code()
return error_with_code('net: socket error: $last_error', last_error) return error_with_code('net: socket error: $last_error', last_error)
@ -40,8 +42,7 @@ pub fn wrap_error(error_code int) ? {
$if windows { $if windows {
enum_error := wsa_error(error_code) enum_error := wsa_error(error_code)
return error_with_code('net: socket error: $enum_error', error_code) return error_with_code('net: socket error: $enum_error', error_code)
} } $else {
$else {
if error_code == 0 { if error_code == 0 {
return return
} }

View File

@ -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 }'
}

View File

@ -1,7 +1,8 @@
module net module net
// needed for unix domain sockets support // 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 // WsaError is all of the socket errors that WSA provides from WSAGetLastError
pub enum WsaError { pub enum WsaError {
@ -13,7 +14,6 @@ pub enum WsaError {
// A blocking operation was interrupted by a call to WSACancelBlockingCall. // A blocking operation was interrupted by a call to WSACancelBlockingCall.
// //
wsaeintr = 10004 wsaeintr = 10004
// //
// MessageId: WSAEBADF // MessageId: WSAEBADF
// //
@ -22,7 +22,6 @@ pub enum WsaError {
// The file handle supplied is not valid. // The file handle supplied is not valid.
// //
wsaebadf = 10009 wsaebadf = 10009
// //
// MessageId: WSAEACCES // 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. // An attempt was made to access a socket in a way forbidden by its access permissions.
// //
wsaeacces = 10013 wsaeacces = 10013
// //
// MessageId: WSAEFAULT // 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. // The system detected an invalid pointer address in attempting to use a pointer argument in a call.
// //
wsaefault = 10014 wsaefault = 10014
// //
// MessageId: WSAEINVAL // MessageId: WSAEINVAL
// //
@ -49,7 +46,6 @@ pub enum WsaError {
// An invalid argument was supplied. // An invalid argument was supplied.
// //
wsaeinval = 10022 wsaeinval = 10022
// //
// MessageId: WSAEMFILE // MessageId: WSAEMFILE
// //
@ -58,7 +54,6 @@ pub enum WsaError {
// Too many open sockets. // Too many open sockets.
// //
wsaemfile = 10024 wsaemfile = 10024
// //
// MessageId: WSAEWOULDBLOCK // MessageId: WSAEWOULDBLOCK
// //
@ -67,7 +62,6 @@ pub enum WsaError {
// A non-blocking socket operation could not be completed immediately. // A non-blocking socket operation could not be completed immediately.
// //
wsaewouldblock = 10035 wsaewouldblock = 10035
// //
// MessageId: WSAEINPROGRESS // MessageId: WSAEINPROGRESS
// //
@ -76,7 +70,6 @@ pub enum WsaError {
// A blocking operation is currently executing. // A blocking operation is currently executing.
// //
wsaeinprogress = 10036 wsaeinprogress = 10036
// //
// MessageId: WSAEALREADY // 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. // An operation was attempted on a non-blocking socket that already had an operation in progress.
// //
wsaealready = 10037 wsaealready = 10037
// //
// MessageId: WSAENOTSOCK // MessageId: WSAENOTSOCK
// //
@ -94,7 +86,6 @@ pub enum WsaError {
// An operation was attempted on something that is not a socket. // An operation was attempted on something that is not a socket.
// //
wsaenotsock = 10038 wsaenotsock = 10038
// //
// MessageId: WSAEDESTADDRREQ // MessageId: WSAEDESTADDRREQ
// //
@ -103,7 +94,6 @@ pub enum WsaError {
// A required address was omitted from an operation on a socket. // A required address was omitted from an operation on a socket.
// //
wsaedestaddrreq = 10039 wsaedestaddrreq = 10039
// //
// MessageId: WSAEMSGSIZE // 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. // 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 wsaemsgsize = 10040
// //
// MessageId: WSAEPROTOTYPE // 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. // A protocol was specified in the socket function call that does not support the semantics of the socket type requested.
// //
wsaeprototype = 10041 wsaeprototype = 10041
// //
// MessageId: WSAENOPROTOOPT // 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. // An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call.
// //
wsaenoprotoopt = 10042 wsaenoprotoopt = 10042
// //
// MessageId: WSAEPROTONOSUPPORT // 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. // The requested protocol has not been configured into the system, or no implementation for it exists.
// //
wsaeprotonosupport = 10043 wsaeprotonosupport = 10043
// //
// MessageId: WSAESOCKTNOSUPPORT // MessageId: WSAESOCKTNOSUPPORT
// //
@ -148,7 +134,6 @@ pub enum WsaError {
// The support for the specified socket type does not exist in this address family. // The support for the specified socket type does not exist in this address family.
// //
wsaesocktnosupport = 10044 wsaesocktnosupport = 10044
// //
// MessageId: WSAEOPNOTSUPP // MessageId: WSAEOPNOTSUPP
// //
@ -157,7 +142,6 @@ pub enum WsaError {
// The attempted operation is not supported for the type of object referenced. // The attempted operation is not supported for the type of object referenced.
// //
wsaeopnotsupp = 10045 wsaeopnotsupp = 10045
// //
// MessageId: WSAEPFNOSUPPORT // 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. // The protocol family has not been configured into the system or no implementation for it exists.
// //
wsaepfnosupport = 10046 wsaepfnosupport = 10046
// //
// MessageId: WSAEAFNOSUPPORT // MessageId: WSAEAFNOSUPPORT
// //
@ -175,7 +158,6 @@ pub enum WsaError {
// An address incompatible with the requested protocol was used. // An address incompatible with the requested protocol was used.
// //
wsaeafnosupport = 10047 wsaeafnosupport = 10047
// //
// MessageId: WSAEADDRINUSE // MessageId: WSAEADDRINUSE
// //
@ -184,7 +166,6 @@ pub enum WsaError {
// Only one usage of each socket address (protocol/network address/port) is normally permitted. // Only one usage of each socket address (protocol/network address/port) is normally permitted.
// //
wsaeaddrinuse = 10048 wsaeaddrinuse = 10048
// //
// MessageId: WSAEADDRNOTAVAIL // MessageId: WSAEADDRNOTAVAIL
// //
@ -193,7 +174,6 @@ pub enum WsaError {
// The requested address is not valid in its context. // The requested address is not valid in its context.
// //
wsaeaddrnotavail = 10049 wsaeaddrnotavail = 10049
// //
// MessageId: WSAENETDOWN // MessageId: WSAENETDOWN
// //
@ -202,7 +182,6 @@ pub enum WsaError {
// A socket operation encountered a dead network. // A socket operation encountered a dead network.
// //
wsaenetdown = 10050 wsaenetdown = 10050
// //
// MessageId: WSAENETUNREACH // MessageId: WSAENETUNREACH
// //
@ -211,7 +190,6 @@ pub enum WsaError {
// A socket operation was attempted to an unreachable network. // A socket operation was attempted to an unreachable network.
// //
wsaenetunreach = 10051 wsaenetunreach = 10051
// //
// MessageId: WSAENETRESET // 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. // The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress.
// //
wsaenetreset = 10052 wsaenetreset = 10052
// //
// MessageId: WSAECONNABORTED // MessageId: WSAECONNABORTED
// //
@ -229,7 +206,6 @@ pub enum WsaError {
// An established connection was aborted by the software in your host machine. // An established connection was aborted by the software in your host machine.
// //
wsaeconnaborted = 10053 wsaeconnaborted = 10053
// //
// MessageId: WSAECONNRESET // MessageId: WSAECONNRESET
// //
@ -238,7 +214,6 @@ pub enum WsaError {
// An existing connection was forcibly closed by the remote host. // An existing connection was forcibly closed by the remote host.
// //
wsaeconnreset = 10054 wsaeconnreset = 10054
// //
// MessageId: WSAENOBUFS // 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. // An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
// //
wsaenobufs = 10055 wsaenobufs = 10055
// //
// MessageId: WSAEISCONN // MessageId: WSAEISCONN
// //
@ -256,7 +230,6 @@ pub enum WsaError {
// A connect request was made on an already connected socket. // A connect request was made on an already connected socket.
// //
wsaeisconn = 10056 wsaeisconn = 10056
// //
// MessageId: WSAENOTCONN // 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. // 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 wsaenotconn = 10057
// //
// MessageId: WSAESHUTDOWN // 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. // 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 wsaeshutdown = 10058
// //
// MessageId: WSAETOOMANYREFS // MessageId: WSAETOOMANYREFS
// //
@ -283,7 +254,6 @@ pub enum WsaError {
// Too many references to some kernel object. // Too many references to some kernel object.
// //
wsaetoomanyrefs = 10059 wsaetoomanyrefs = 10059
// //
// MessageId: WSAETIMEDOUT // 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. // 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 wsaetimedout = 10060
// //
// MessageId: WSAECONNREFUSED // MessageId: WSAECONNREFUSED
// //
@ -301,7 +270,6 @@ pub enum WsaError {
// No connection could be made because the target machine actively refused it. // No connection could be made because the target machine actively refused it.
// //
wsaeconnrefused = 10061 wsaeconnrefused = 10061
// //
// MessageId: WSAELOOP // MessageId: WSAELOOP
// //
@ -310,7 +278,6 @@ pub enum WsaError {
// Cannot translate name. // Cannot translate name.
// //
wsaeloop = 10062 wsaeloop = 10062
// //
// MessageId: WSAENAMETOOLONG // MessageId: WSAENAMETOOLONG
// //
@ -319,7 +286,6 @@ pub enum WsaError {
// Name component or name was too long. // Name component or name was too long.
// //
wsaenametoolong = 10063 wsaenametoolong = 10063
// //
// MessageId: WSAEHOSTDOWN // MessageId: WSAEHOSTDOWN
// //
@ -328,7 +294,6 @@ pub enum WsaError {
// A socket operation failed because the destination host was down. // A socket operation failed because the destination host was down.
// //
wsaehostdown = 10064 wsaehostdown = 10064
// //
// MessageId: WSAEHOSTUNREACH // MessageId: WSAEHOSTUNREACH
// //
@ -337,7 +302,6 @@ pub enum WsaError {
// A socket operation was attempted to an unreachable host. // A socket operation was attempted to an unreachable host.
// //
wsaehostunreach = 10065 wsaehostunreach = 10065
// //
// MessageId: WSAENOTEMPTY // MessageId: WSAENOTEMPTY
// //
@ -346,7 +310,6 @@ pub enum WsaError {
// Cannot remove a directory that is not empty. // Cannot remove a directory that is not empty.
// //
wsaenotempty = 10066 wsaenotempty = 10066
// //
// MessageId: WSAEPROCLIM // 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. // A Windows Sockets implementation may have a limit on the number of applications that may use it simultaneously.
// //
wsaeproclim = 10067 wsaeproclim = 10067
// //
// MessageId: WSAEUSERS // MessageId: WSAEUSERS
// //
@ -364,7 +326,6 @@ pub enum WsaError {
// Ran out of quota. // Ran out of quota.
// //
wsaeusers = 10068 wsaeusers = 10068
// //
// MessageId: WSAEDQUOT // MessageId: WSAEDQUOT
// //
@ -373,7 +334,6 @@ pub enum WsaError {
// Ran out of disk quota. // Ran out of disk quota.
// //
wsaedquot = 10069 wsaedquot = 10069
// //
// MessageId: WSAESTALE // MessageId: WSAESTALE
// //
@ -382,7 +342,6 @@ pub enum WsaError {
// File handle reference is no longer available. // File handle reference is no longer available.
// //
wsaestale = 10070 wsaestale = 10070
// //
// MessageId: WSAEREMOTE // MessageId: WSAEREMOTE
// //
@ -391,7 +350,6 @@ pub enum WsaError {
// Item is not available locally. // Item is not available locally.
// //
wsaeremote = 10071 wsaeremote = 10071
// //
// MessageId: WSASYSNOTREADY // 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. // WSAStartup cannot function at this time because the underlying system it uses to provide network services is currently unavailable.
// //
wsasysnotready = 10091 wsasysnotready = 10091
// //
// MessageId: WSAVERNOTSUPPORTED // MessageId: WSAVERNOTSUPPORTED
// //
@ -409,7 +366,6 @@ pub enum WsaError {
// The Windows Sockets version requested is not supported. // The Windows Sockets version requested is not supported.
// //
wsavernotsupported = 10092 wsavernotsupported = 10092
// //
// MessageId: WSANOTINITIALISED // MessageId: WSANOTINITIALISED
// //
@ -418,7 +374,6 @@ pub enum WsaError {
// Either the application has not called WSAStartup, or WSAStartup failed. // Either the application has not called WSAStartup, or WSAStartup failed.
// //
wsanotinitialised = 10093 wsanotinitialised = 10093
// //
// MessageId: WSAEDISCON // 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. // Returned by WSARecv or WSARecvFrom to indicate the remote party has initiated a graceful shutdown sequence.
// //
wsaediscon = 10101 wsaediscon = 10101
// //
// MessageId: WSAENOMORE // MessageId: WSAENOMORE
// //
@ -436,7 +390,6 @@ pub enum WsaError {
// No more results can be returned by WSALookupServiceNext. // No more results can be returned by WSALookupServiceNext.
// //
wsaenomore = 10102 wsaenomore = 10102
// //
// MessageId: WSAECANCELLED // 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. // A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled.
// //
wsaecancelled = 10103 wsaecancelled = 10103
// //
// MessageId: WSAEINVALIDPROCTABLE // MessageId: WSAEINVALIDPROCTABLE
// //
@ -454,7 +406,6 @@ pub enum WsaError {
// The procedure call table is invalid. // The procedure call table is invalid.
// //
wsaeinvalidproctable = 10104 wsaeinvalidproctable = 10104
// //
// MessageId: WSAEINVALIDPROVIDER // MessageId: WSAEINVALIDPROVIDER
// //
@ -463,7 +414,6 @@ pub enum WsaError {
// The requested service provider is invalid. // The requested service provider is invalid.
// //
wsaeinvalidprovider = 10105 wsaeinvalidprovider = 10105
// //
// MessageId: WSAEPROVIDERFAILEDINIT // MessageId: WSAEPROVIDERFAILEDINIT
// //
@ -472,7 +422,6 @@ pub enum WsaError {
// The requested service provider could not be loaded or initialized. // The requested service provider could not be loaded or initialized.
// //
wsaeproviderfailedinit = 10106 wsaeproviderfailedinit = 10106
// //
// MessageId: WSASYSCALLFAILURE // MessageId: WSASYSCALLFAILURE
// //
@ -481,7 +430,6 @@ pub enum WsaError {
// A system call has failed. // A system call has failed.
// //
wsasyscallfailure = 10107 wsasyscallfailure = 10107
// //
// MessageId: WSASERVICE_NOT_FOUND // 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. // No such service is known. The service cannot be found in the specified name space.
// //
wsaservice_not_found = 10108 wsaservice_not_found = 10108
// //
// MessageId: WSATYPE_NOT_FOUND // MessageId: WSATYPE_NOT_FOUND
// //
@ -499,7 +446,6 @@ pub enum WsaError {
// The specified class was not found. // The specified class was not found.
// //
wsatype_not_found = 10109 wsatype_not_found = 10109
// //
// MessageId: WSA_E_NO_MORE // MessageId: WSA_E_NO_MORE
// //
@ -508,7 +454,6 @@ pub enum WsaError {
// No more results can be returned by WSALookupServiceNext. // No more results can be returned by WSALookupServiceNext.
// //
wsa_e_no_more = 10110 wsa_e_no_more = 10110
// //
// MessageId: WSA_E_CANCELLED // 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. // A call to WSALookupServiceEnd was made while this call was still processing. The call has been canceled.
// //
wsa_e_cancelled = 10111 wsa_e_cancelled = 10111
// //
// MessageId: WSAEREFUSED // MessageId: WSAEREFUSED
// //
@ -526,7 +470,6 @@ pub enum WsaError {
// A database query failed because it was actively refused. // A database query failed because it was actively refused.
// //
wsaerefused = 10112 wsaerefused = 10112
// //
// MessageId: WSAHOST_NOT_FOUND // MessageId: WSAHOST_NOT_FOUND
// //
@ -535,7 +478,6 @@ pub enum WsaError {
// No such host is known. // No such host is known.
// //
wsahost_not_found = 11001 wsahost_not_found = 11001
// //
// MessageId: WSATRY_AGAIN // 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. // 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 wsatry_again = 11002
// //
// MessageId: WSANO_RECOVERY // MessageId: WSANO_RECOVERY
// //
@ -553,7 +494,6 @@ pub enum WsaError {
// A non-recoverable error occurred during a database lookup. // A non-recoverable error occurred during a database lookup.
// //
wsano_recovery = 11003 wsano_recovery = 11003
// //
// MessageId: WSANO_DATA // MessageId: WSANO_DATA
// //
@ -562,7 +502,6 @@ pub enum WsaError {
// The requested name is valid, but no data of the requested type was found. // The requested name is valid, but no data of the requested type was found.
// //
wsano_data = 11004 wsano_data = 11004
// //
// MessageId: WSA_QOS_RECEIVERS // MessageId: WSA_QOS_RECEIVERS
// //
@ -571,7 +510,6 @@ pub enum WsaError {
// At least one reserve has arrived. // At least one reserve has arrived.
// //
wsa_qos_receivers = 11005 wsa_qos_receivers = 11005
// //
// MessageId: WSA_QOS_SENDERS // MessageId: WSA_QOS_SENDERS
// //
@ -580,7 +518,6 @@ pub enum WsaError {
// At least one path has arrived. // At least one path has arrived.
// //
wsa_qos_senders = 11006 wsa_qos_senders = 11006
// //
// MessageId: WSA_QOS_NO_SENDERS // MessageId: WSA_QOS_NO_SENDERS
// //
@ -589,7 +526,6 @@ pub enum WsaError {
// There are no senders. // There are no senders.
// //
wsa_qos_no_senders = 11007 wsa_qos_no_senders = 11007
// //
// MessageId: WSA_QOS_NO_RECEIVERS // MessageId: WSA_QOS_NO_RECEIVERS
// //
@ -598,7 +534,6 @@ pub enum WsaError {
// There are no receivers. // There are no receivers.
// //
wsa_qos_no_receivers = 11008 wsa_qos_no_receivers = 11008
// //
// MessageId: WSA_QOS_REQUEST_CONFIRMED // MessageId: WSA_QOS_REQUEST_CONFIRMED
// //
@ -607,7 +542,6 @@ pub enum WsaError {
// Reserve has been confirmed. // Reserve has been confirmed.
// //
wsa_qos_request_confirmed = 11009 wsa_qos_request_confirmed = 11009
// //
// MessageId: WSA_QOS_ADMISSION_FAILURE // MessageId: WSA_QOS_ADMISSION_FAILURE
// //
@ -616,7 +550,6 @@ pub enum WsaError {
// Error due to lack of resources. // Error due to lack of resources.
// //
wsa_qos_admission_failure = 11010 wsa_qos_admission_failure = 11010
// //
// MessageId: WSA_QOS_POLICY_FAILURE // MessageId: WSA_QOS_POLICY_FAILURE
// //
@ -625,7 +558,6 @@ pub enum WsaError {
// Rejected for administrative reasons - bad credentials. // Rejected for administrative reasons - bad credentials.
// //
wsa_qos_policy_failure = 11011 wsa_qos_policy_failure = 11011
// //
// MessageId: WSA_QOS_BAD_STYLE // MessageId: WSA_QOS_BAD_STYLE
// //
@ -634,7 +566,6 @@ pub enum WsaError {
// Unknown or conflicting style. // Unknown or conflicting style.
// //
wsa_qos_bad_style = 11012 wsa_qos_bad_style = 11012
// //
// MessageId: WSA_QOS_BAD_OBJECT // MessageId: WSA_QOS_BAD_OBJECT
// //
@ -643,7 +574,6 @@ pub enum WsaError {
// Problem with some part of the filterspec or providerspecific buffer in general. // Problem with some part of the filterspec or providerspecific buffer in general.
// //
wsa_qos_bad_object = 11013 wsa_qos_bad_object = 11013
// //
// MessageId: WSA_QOS_TRAFFIC_CTRL_ERROR // MessageId: WSA_QOS_TRAFFIC_CTRL_ERROR
// //
@ -652,7 +582,6 @@ pub enum WsaError {
// Problem with some part of the flowspec. // Problem with some part of the flowspec.
// //
wsa_qos_traffic_ctrl_error = 11014 wsa_qos_traffic_ctrl_error = 11014
// //
// MessageId: WSA_QOS_GENERIC_ERROR // MessageId: WSA_QOS_GENERIC_ERROR
// //
@ -661,7 +590,6 @@ pub enum WsaError {
// General QOS error. // General QOS error.
// //
wsa_qos_generic_error = 11015 wsa_qos_generic_error = 11015
// //
// MessageId: WSA_QOS_ESERVICETYPE // MessageId: WSA_QOS_ESERVICETYPE
// //
@ -670,7 +598,6 @@ pub enum WsaError {
// An invalid or unrecognized service type was found in the flowspec. // An invalid or unrecognized service type was found in the flowspec.
// //
wsa_qos_eservicetype = 11016 wsa_qos_eservicetype = 11016
// //
// MessageId: WSA_QOS_EFLOWSPEC // MessageId: WSA_QOS_EFLOWSPEC
// //
@ -679,7 +606,6 @@ pub enum WsaError {
// An invalid or inconsistent flowspec was found in the QOS structure. // An invalid or inconsistent flowspec was found in the QOS structure.
// //
wsa_qos_eflowspec = 11017 wsa_qos_eflowspec = 11017
// //
// MessageId: WSA_QOS_EPROVSPECBUF // MessageId: WSA_QOS_EPROVSPECBUF
// //
@ -688,7 +614,6 @@ pub enum WsaError {
// Invalid QOS provider-specific buffer. // Invalid QOS provider-specific buffer.
// //
wsa_qos_eprovspecbuf = 11018 wsa_qos_eprovspecbuf = 11018
// //
// MessageId: WSA_QOS_EFILTERSTYLE // MessageId: WSA_QOS_EFILTERSTYLE
// //
@ -697,7 +622,6 @@ pub enum WsaError {
// An invalid QOS filter style was used. // An invalid QOS filter style was used.
// //
wsa_qos_efilterstyle = 11019 wsa_qos_efilterstyle = 11019
// //
// MessageId: WSA_QOS_EFILTERTYPE // MessageId: WSA_QOS_EFILTERTYPE
// //
@ -706,7 +630,6 @@ pub enum WsaError {
// An invalid QOS filter type was used. // An invalid QOS filter type was used.
// //
wsa_qos_efiltertype = 11020 wsa_qos_efiltertype = 11020
// //
// MessageId: WSA_QOS_EFILTERCOUNT // MessageId: WSA_QOS_EFILTERCOUNT
// //
@ -715,7 +638,6 @@ pub enum WsaError {
// An incorrect number of QOS FILTERSPECs were specified in the FLOWDESCRIPTOR. // An incorrect number of QOS FILTERSPECs were specified in the FLOWDESCRIPTOR.
// //
wsa_qos_efiltercount = 11021 wsa_qos_efiltercount = 11021
// //
// MessageId: WSA_QOS_EOBJLENGTH // 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. // An object with an invalid ObjectLength field was specified in the QOS provider-specific buffer.
// //
wsa_qos_eobjlength = 11022 wsa_qos_eobjlength = 11022
// //
// MessageId: WSA_QOS_EFLOWCOUNT // MessageId: WSA_QOS_EFLOWCOUNT
// //
@ -733,7 +654,6 @@ pub enum WsaError {
// An incorrect number of flow descriptors was specified in the QOS structure. // An incorrect number of flow descriptors was specified in the QOS structure.
// //
wsa_qos_eflowcount = 11023 wsa_qos_eflowcount = 11023
// //
// MessageId: WSA_QOS_EUNKOWNPSOBJ // MessageId: WSA_QOS_EUNKOWNPSOBJ
// //
@ -742,7 +662,6 @@ pub enum WsaError {
// An unrecognized object was found in the QOS provider-specific buffer. // An unrecognized object was found in the QOS provider-specific buffer.
// //
wsa_qos_eunkownpsobj = 11024 wsa_qos_eunkownpsobj = 11024
// //
// MessageId: WSA_QOS_EPOLICYOBJ // MessageId: WSA_QOS_EPOLICYOBJ
// //
@ -751,7 +670,6 @@ pub enum WsaError {
// An invalid policy object was found in the QOS provider-specific buffer. // An invalid policy object was found in the QOS provider-specific buffer.
// //
wsa_qos_epolicyobj = 11025 wsa_qos_epolicyobj = 11025
// //
// MessageId: WSA_QOS_EFLOWDESC // MessageId: WSA_QOS_EFLOWDESC
// //
@ -760,7 +678,6 @@ pub enum WsaError {
// An invalid QOS flow descriptor was found in the flow descriptor list. // An invalid QOS flow descriptor was found in the flow descriptor list.
// //
wsa_qos_eflowdesc = 11026 wsa_qos_eflowdesc = 11026
// //
// MessageId: WSA_QOS_EPSFLOWSPEC // MessageId: WSA_QOS_EPSFLOWSPEC
// //
@ -769,7 +686,6 @@ pub enum WsaError {
// An invalid or inconsistent flowspec was found in the QOS provider specific buffer. // An invalid or inconsistent flowspec was found in the QOS provider specific buffer.
// //
wsa_qos_epsflowspec = 11027 wsa_qos_epsflowspec = 11027
// //
// MessageId: WSA_QOS_EPSFILTERSPEC // MessageId: WSA_QOS_EPSFILTERSPEC
// //
@ -778,7 +694,6 @@ pub enum WsaError {
// An invalid FILTERSPEC was found in the QOS provider-specific buffer. // An invalid FILTERSPEC was found in the QOS provider-specific buffer.
// //
wsa_qos_epsfilterspec = 11028 wsa_qos_epsfilterspec = 11028
// //
// MessageId: WSA_QOS_ESDMODEOBJ // 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. // An invalid shape discard mode object was found in the QOS provider specific buffer.
// //
wsa_qos_esdmodeobj = 11029 wsa_qos_esdmodeobj = 11029
// //
// MessageId: WSA_QOS_ESHAPERATEOBJ // MessageId: WSA_QOS_ESHAPERATEOBJ
// //
@ -796,7 +710,6 @@ pub enum WsaError {
// An invalid shaping rate object was found in the QOS provider-specific buffer. // An invalid shaping rate object was found in the QOS provider-specific buffer.
// //
wsa_qos_eshaperateobj = 11030 wsa_qos_eshaperateobj = 11030
// //
// MessageId: WSA_QOS_RESERVED_PETYPE // MessageId: WSA_QOS_RESERVED_PETYPE
// //
@ -805,7 +718,6 @@ pub enum WsaError {
// A reserved policy element was found in the QOS provider-specific buffer. // A reserved policy element was found in the QOS provider-specific buffer.
// //
wsa_qos_reserved_petype = 11031 wsa_qos_reserved_petype = 11031
// //
// MessageId: WSA_SECURE_HOST_NOT_FOUND // MessageId: WSA_SECURE_HOST_NOT_FOUND
// //
@ -814,7 +726,6 @@ pub enum WsaError {
// No such host is known securely. // No such host is known securely.
// //
wsa_secure_host_not_found = 11032 wsa_secure_host_not_found = 11032
// //
// MessageId: WSA_IPSEC_NAME_POLICY_ERROR // MessageId: WSA_IPSEC_NAME_POLICY_ERROR
// //
@ -841,9 +752,9 @@ const (
// Constants that windows needs // Constants that windows needs
const ( const (
fionbio = C.FIONBIO fionbio = C.FIONBIO
msg_nosignal = 0 msg_nosignal = 0
wsa_v22 = 0x202 // C.MAKEWORD(2, 2) wsa_v22 = 0x202 // C.MAKEWORD(2, 2)
) )
// Error code returns the last socket error // Error code returns the last socket error
@ -853,18 +764,18 @@ fn error_code() int {
struct C.WSAData { struct C.WSAData {
mut: mut:
wVersion u16 wVersion u16
wHighVersion u16 wHighVersion u16
szDescription [257]byte szDescription [257]byte
szSystemStatus [129]byte szSystemStatus [129]byte
iMaxSockets u16 iMaxSockets u16
iMaxUdpDg u16 iMaxUdpDg u16
lpVendorInfo byteptr lpVendorInfo byteptr
} }
fn init() { fn init() {
mut wsadata := C.WSAData{} mut wsadata := C.WSAData{}
res := C.WSAStartup(wsa_v22, &wsadata) res := C.WSAStartup(net.wsa_v22, &wsadata)
if res != 0 { if res != 0 {
panic('socket: WSAStartup failed') panic('socket: WSAStartup failed')
} }

View 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 {}

View 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
}

View 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 }'
}

View File

@ -1,10 +1,10 @@
import net import net.unix
const ( const (
test_port = 'test' test_port = 'test'
) )
fn handle_conn(mut c net.UnixConn) { fn handle_conn(mut c unix.StreamConn) {
for { for {
mut buf := []byte{len: 100, init: 0} mut buf := []byte{len: 100, init: 0}
read := c.read(mut buf) or { 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 { for {
mut new_conn := l.accept() or { continue } mut new_conn := l.accept() or { continue }
go handle_conn(mut new_conn) go handle_conn(mut new_conn)
@ -27,7 +27,7 @@ fn echo_server(mut l net.UnixListener) ? {
} }
fn echo() ? { fn echo() ? {
mut c := net.connect_unix('test') ? mut c := unix.connect_stream('test') ?
defer { defer {
c.close() or { } c.close() or { }
} }
@ -44,7 +44,7 @@ fn echo() ? {
} }
fn test_tcp() { 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) go echo_server(mut l)
echo() or { panic(err) } echo() or { panic(err) }
l.close() or { } l.close() or { }