unix.go raw
1 // Package unix is the small slice of Linux socket and poll functionality that
2 // torly's acceptor and fdConn need. It exists so that the relay does not
3 // depend on an external syscall module: the calls are visible, reviewable and
4 // can be adjusted for the targets TinyGo supports.
5 package unix
6
7 import (
8 "syscall"
9 "unsafe"
10 )
11
12 // Constants mirrored from the Linux ABI.
13 const (
14 AF_INET = syscall.AF_INET
15 SOCK_STREAM = syscall.SOCK_STREAM
16 SOCK_NONBLOCK = syscall.SOCK_NONBLOCK
17 SOCK_CLOEXEC = syscall.SOCK_CLOEXEC
18 SOL_SOCKET = syscall.SOL_SOCKET
19 SO_REUSEADDR = syscall.SO_REUSEADDR
20 SHUT_RDWR = syscall.SHUT_RDWR
21 EAGAIN = syscall.EAGAIN
22 EINTR = syscall.EINTR
23 POLLIN = 0x1
24 POLLOUT = 0x4
25 )
26
27 // SockaddrInet4 is an IPv4 socket address.
28 type SockaddrInet4 = syscall.SockaddrInet4
29
30 // Sockaddr is a socket address.
31 type Sockaddr = syscall.Sockaddr
32
33 // PollFd mirrors struct pollfd.
34 type PollFd struct {
35 Fd int32
36 Events int16
37 Revents int16
38 }
39
40 // Socket creates a socket.
41 func Socket(domain, typ, proto int) (int, error) { return syscall.Socket(domain, typ, proto) }
42
43 // Bind binds a socket.
44 func Bind(fd int, sa Sockaddr) error { return syscall.Bind(fd, sa) }
45
46 // Listen marks a socket as accepting connections.
47 func Listen(fd, backlog int) error { return syscall.Listen(fd, backlog) }
48
49 // Accept4 accepts a connection with flags.
50 func Accept4(fd, flags int) (int, Sockaddr, error) { return syscall.Accept4(fd, flags) }
51
52 // Getsockname returns the local address of a socket.
53 func Getsockname(fd int) (Sockaddr, error) { return syscall.Getsockname(fd) }
54
55 // SetsockoptInt sets an integer socket option.
56 func SetsockoptInt(fd, level, opt, value int) error {
57 return syscall.SetsockoptInt(fd, level, opt, value)
58 }
59
60 // SetNonblock sets the non-blocking flag on a descriptor.
61 func SetNonblock(fd int, nonblocking bool) error { return syscall.SetNonblock(fd, nonblocking) }
62
63 // Close closes a descriptor.
64 func Close(fd int) error { return syscall.Close(fd) }
65
66 // Shutdown shuts down one or both directions of a socket.
67 func Shutdown(fd, how int) error { return syscall.Shutdown(fd, how) }
68
69 // Read reads from a descriptor.
70 func Read(fd int, p []byte) (int, error) {
71 n, err := syscall.Read(fd, p)
72 if err != nil {
73 return n, err
74 }
75 return n, nil
76 }
77
78 // Write writes to a descriptor.
79 func Write(fd int, p []byte) (int, error) {
80 n, err := syscall.Write(fd, p)
81 if err != nil {
82 return n, err
83 }
84 return n, nil
85 }
86
87 // Poll waits for events on the given descriptors. timeout is in milliseconds.
88 func Poll(fds []PollFd, timeout int) (int, error) {
89 if len(fds) == 0 {
90 // Nothing to wait for; behave like a zero-timeout poll.
91 return 0, nil
92 }
93 r, _, errno := syscall.Syscall(syscall.SYS_POLL,
94 uintptr(unsafe.Pointer(&fds[0])), uintptr(len(fds)), uintptr(timeout))
95 if errno != 0 {
96 return int(r), errno
97 }
98 return int(r), nil
99 }
100