mirror of
https://codeberg.org/superseriousbusiness/gotosocial.git
synced 2024-12-30 12:58:16 +03:00
90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
|
package sock
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net"
|
||
|
|
||
|
"github.com/tetratelabs/wazero/experimental/sys"
|
||
|
)
|
||
|
|
||
|
// TCPSock is a pseudo-file representing a TCP socket.
|
||
|
type TCPSock interface {
|
||
|
sys.File
|
||
|
|
||
|
Accept() (TCPConn, sys.Errno)
|
||
|
}
|
||
|
|
||
|
// TCPConn is a pseudo-file representing a TCP connection.
|
||
|
type TCPConn interface {
|
||
|
sys.File
|
||
|
|
||
|
// Recvfrom only supports the flag sysfs.MSG_PEEK
|
||
|
// TODO: document this like sys.File with known sys.Errno
|
||
|
Recvfrom(p []byte, flags int) (n int, errno sys.Errno)
|
||
|
|
||
|
// TODO: document this like sys.File with known sys.Errno
|
||
|
Shutdown(how int) sys.Errno
|
||
|
}
|
||
|
|
||
|
// ConfigKey is a context.Context Value key. Its associated value should be a Config.
|
||
|
type ConfigKey struct{}
|
||
|
|
||
|
// Config is an internal struct meant to implement
|
||
|
// the interface in experimental/sock/Config.
|
||
|
type Config struct {
|
||
|
// TCPAddresses is a slice of the configured host:port pairs.
|
||
|
TCPAddresses []TCPAddress
|
||
|
}
|
||
|
|
||
|
// TCPAddress is a host:port pair to pre-open.
|
||
|
type TCPAddress struct {
|
||
|
// Host is the host name for this listener.
|
||
|
Host string
|
||
|
// Port is the port number for this listener.
|
||
|
Port int
|
||
|
}
|
||
|
|
||
|
// WithTCPListener implements the method of the same name in experimental/sock/Config.
|
||
|
//
|
||
|
// However, to avoid cyclic dependencies, this is returning the *Config in this scope.
|
||
|
// The interface is implemented in experimental/sock/Config via delegation.
|
||
|
func (c *Config) WithTCPListener(host string, port int) *Config {
|
||
|
ret := c.clone()
|
||
|
ret.TCPAddresses = append(ret.TCPAddresses, TCPAddress{host, port})
|
||
|
return &ret
|
||
|
}
|
||
|
|
||
|
// Makes a deep copy of this sockConfig.
|
||
|
func (c *Config) clone() Config {
|
||
|
ret := *c
|
||
|
ret.TCPAddresses = make([]TCPAddress, 0, len(c.TCPAddresses))
|
||
|
ret.TCPAddresses = append(ret.TCPAddresses, c.TCPAddresses...)
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
// BuildTCPListeners build listeners from the current configuration.
|
||
|
func (c *Config) BuildTCPListeners() (tcpListeners []*net.TCPListener, err error) {
|
||
|
for _, tcpAddr := range c.TCPAddresses {
|
||
|
var ln net.Listener
|
||
|
ln, err = net.Listen("tcp", tcpAddr.String())
|
||
|
if err != nil {
|
||
|
break
|
||
|
}
|
||
|
if tcpln, ok := ln.(*net.TCPListener); ok {
|
||
|
tcpListeners = append(tcpListeners, tcpln)
|
||
|
}
|
||
|
}
|
||
|
if err != nil {
|
||
|
// An error occurred, cleanup.
|
||
|
for _, l := range tcpListeners {
|
||
|
_ = l.Close() // Ignore errors, we are already cleaning.
|
||
|
}
|
||
|
tcpListeners = nil
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (t TCPAddress) String() string {
|
||
|
return fmt.Sprintf("%s:%d", t.Host, t.Port)
|
||
|
}
|