package hopp import "net" import "errors" import "crypto/tls" // Listener is an object which listens for incoming HOPP connections. type Listener interface { // Accept waits for and returns the next connection to the listener. Accept() (Conn, error) // Close closes the listener. Any blocked Accept operations will be // unblocked and return errors. Close() error // Addr returns the listener's network address. Addr() net.Addr } // Listen listens for incoming HOPP connections. The network must be one of: // // - "quic" // - "quic4" (IPv4-only) // - "quic6" (IPv6-only) // - "tls" // - "tls4" (IPv4-only) // - "tls6" (IPv6-only) // - "tcp" // - "tcp4" (IPv4-only) // - "tcp6" (IPv6-only) // - "unix" // // For now, QUIC is unsupported. func Listen(network, address string, tlsConf *tls.Config) (Listener, error) { switch network { case "quic", "quic4", "quic6": return ListenQUIC(network, address, tlsConf) case "tls", "tls4", "tls6": return ListenTLS(network, address, tlsConf) case "tcp", "tcp4", "tcp6": addr, err := net.ResolveTCPAddr(network, address) if err != nil { return nil, err } return ListenTCP(network, addr) case "unix": addr, err := net.ResolveUnixAddr(network, address) if err != nil { return nil, err } return ListenUnix(network, addr) default: return nil, ErrUnknownNetwork } } // ListenQUIC listens for incoming HOPP connections using QUIC as a transport. // The network must be one of "quic", "quic4", (IPv4-only) or "quic6" // (IPv6-only). func ListenQUIC(network, address string, tlsConf *tls.Config) (Listener, error) { // tlsConf = tlsConfig(tlsConf) return nil, errors.New("quic is not yet implemented") } // ListenTLS listens for incoming HOPP connections using a TLS socket as a // transport. The network must be "tcp". func ListenTLS(network, address string, tlsConf *tls.Config) (Listener, error) { network, err := tlsNetworkToTCPNetwork(network) if err != nil { return nil, err } listener, err := tls.Listen(network, address, tlsConf) if err != nil { return nil, err } return &netListenerWrapper { underlying: listener, }, nil } // ListenTCP listens for incoming HOPP connections using a TCP socket as a // transport. The network must be "tcp". func ListenTCP(network string, laddr *net.TCPAddr) (Listener, error) { listener, err := net.ListenTCP(network, laddr) if err != nil { return nil, err } return &netListenerWrapper { underlying: listener, }, nil } // ListenUnix listens for incoming HOPP connections using a Unix domain socket // as a transport. The network must be "unix". func ListenUnix(network string, addr *net.UnixAddr) (Listener, error) { listener, err := net.ListenUnix(network, addr) if err != nil { return nil, err } return &netListenerWrapper { underlying: listener, }, nil } type netListenerWrapper struct { underlying net.Listener } func (this *netListenerWrapper) Accept() (Conn, error) { conn, err := this.underlying.Accept() if err != nil { return nil, err } return AdaptA(conn, ServerSide), nil } func (this *netListenerWrapper) Close() error { return this.underlying.Close() } func (this *netListenerWrapper) Addr() net.Addr { return this.underlying.Addr() }