// Package unix is the small slice of Linux socket and poll functionality that // torly's acceptor and fdConn need. It exists so that the relay does not // depend on an external syscall module: the calls are visible, reviewable and // can be adjusted for the targets TinyGo supports. package unix import ( "syscall" "unsafe" ) // Constants mirrored from the Linux ABI. const ( AF_INET = syscall.AF_INET SOCK_STREAM = syscall.SOCK_STREAM SOCK_NONBLOCK = syscall.SOCK_NONBLOCK SOCK_CLOEXEC = syscall.SOCK_CLOEXEC SOL_SOCKET = syscall.SOL_SOCKET SO_REUSEADDR = syscall.SO_REUSEADDR SHUT_RDWR = syscall.SHUT_RDWR EAGAIN = syscall.EAGAIN EINTR = syscall.EINTR POLLIN = 0x1 POLLOUT = 0x4 ) // SockaddrInet4 is an IPv4 socket address. type SockaddrInet4 = syscall.SockaddrInet4 // Sockaddr is a socket address. type Sockaddr = syscall.Sockaddr // PollFd mirrors struct pollfd. type PollFd struct { Fd int32 Events int16 Revents int16 } // Socket creates a socket. func Socket(domain, typ, proto int) (int, error) { return syscall.Socket(domain, typ, proto) } // Bind binds a socket. func Bind(fd int, sa Sockaddr) error { return syscall.Bind(fd, sa) } // Listen marks a socket as accepting connections. func Listen(fd, backlog int) error { return syscall.Listen(fd, backlog) } // Accept4 accepts a connection with flags. func Accept4(fd, flags int) (int, Sockaddr, error) { return syscall.Accept4(fd, flags) } // Getsockname returns the local address of a socket. func Getsockname(fd int) (Sockaddr, error) { return syscall.Getsockname(fd) } // SetsockoptInt sets an integer socket option. func SetsockoptInt(fd, level, opt, value int) error { return syscall.SetsockoptInt(fd, level, opt, value) } // SetNonblock sets the non-blocking flag on a descriptor. func SetNonblock(fd int, nonblocking bool) error { return syscall.SetNonblock(fd, nonblocking) } // Close closes a descriptor. func Close(fd int) error { return syscall.Close(fd) } // Shutdown shuts down one or both directions of a socket. func Shutdown(fd, how int) error { return syscall.Shutdown(fd, how) } // Read reads from a descriptor. func Read(fd int, p []byte) (int, error) { n, err := syscall.Read(fd, p) if err != nil { return n, err } return n, nil } // Write writes to a descriptor. func Write(fd int, p []byte) (int, error) { n, err := syscall.Write(fd, p) if err != nil { return n, err } return n, nil } // Poll waits for events on the given descriptors. timeout is in milliseconds. func Poll(fds []PollFd, timeout int) (int, error) { if len(fds) == 0 { // Nothing to wait for; behave like a zero-timeout poll. return 0, nil } r, _, errno := syscall.Syscall(syscall.SYS_POLL, uintptr(unsafe.Pointer(&fds[0])), uintptr(len(fds)), uintptr(timeout)) if errno != 0 { return int(r), errno } return int(r), nil }