github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/sock/sock.go (about) 1 package sock 2 3 import ( 4 "fmt" 5 "net" 6 7 "github.com/wasilibs/wazerox/experimental/sys" 8 ) 9 10 // TCPSock is a pseudo-file representing a TCP socket. 11 type TCPSock interface { 12 sys.File 13 14 Accept() (TCPConn, sys.Errno) 15 } 16 17 // TCPConn is a pseudo-file representing a TCP connection. 18 type TCPConn interface { 19 sys.File 20 21 // Recvfrom only supports the flag sysfs.MSG_PEEK 22 // TODO: document this like sys.File with known sys.Errno 23 Recvfrom(p []byte, flags int) (n int, errno sys.Errno) 24 25 // TODO: document this like sys.File with known sys.Errno 26 Shutdown(how int) sys.Errno 27 } 28 29 // ConfigKey is a context.Context Value key. Its associated value should be a Config. 30 type ConfigKey struct{} 31 32 // Config is an internal struct meant to implement 33 // the interface in experimental/sock/Config. 34 type Config struct { 35 // TCPAddresses is a slice of the configured host:port pairs. 36 TCPAddresses []TCPAddress 37 } 38 39 // TCPAddress is a host:port pair to pre-open. 40 type TCPAddress struct { 41 // Host is the host name for this listener. 42 Host string 43 // Port is the port number for this listener. 44 Port int 45 } 46 47 // WithTCPListener implements the method of the same name in experimental/sock/Config. 48 // 49 // However, to avoid cyclic dependencies, this is returning the *Config in this scope. 50 // The interface is implemented in experimental/sock/Config via delegation. 51 func (c *Config) WithTCPListener(host string, port int) *Config { 52 ret := c.clone() 53 ret.TCPAddresses = append(ret.TCPAddresses, TCPAddress{host, port}) 54 return &ret 55 } 56 57 // Makes a deep copy of this sockConfig. 58 func (c *Config) clone() Config { 59 ret := *c 60 ret.TCPAddresses = make([]TCPAddress, 0, len(c.TCPAddresses)) 61 ret.TCPAddresses = append(ret.TCPAddresses, c.TCPAddresses...) 62 return ret 63 } 64 65 // BuildTCPListeners build listeners from the current configuration. 66 func (c *Config) BuildTCPListeners() (tcpListeners []*net.TCPListener, err error) { 67 for _, tcpAddr := range c.TCPAddresses { 68 var ln net.Listener 69 ln, err = net.Listen("tcp", tcpAddr.String()) 70 if err != nil { 71 break 72 } 73 if tcpln, ok := ln.(*net.TCPListener); ok { 74 tcpListeners = append(tcpListeners, tcpln) 75 } 76 } 77 if err != nil { 78 // An error occurred, cleanup. 79 for _, l := range tcpListeners { 80 _ = l.Close() // Ignore errors, we are already cleaning. 81 } 82 tcpListeners = nil 83 } 84 return 85 } 86 87 func (t TCPAddress) String() string { 88 return fmt.Sprintf("%s:%d", t.Host, t.Port) 89 }