2025-01-19 15:10:02 -07:00
|
|
|
package hopp
|
|
|
|
|
|
|
|
import "net"
|
2025-01-19 17:29:04 -07:00
|
|
|
import "context"
|
|
|
|
import "crypto/tls"
|
|
|
|
import "github.com/quic-go/quic-go"
|
2025-01-19 15:10:02 -07:00
|
|
|
|
2025-01-19 17:29:04 -07:00
|
|
|
// Listener is an object which listens for incoming HOPP connections.
|
2025-01-19 15:10:02 -07:00
|
|
|
type Listener interface {
|
2025-01-19 17:29:04 -07:00
|
|
|
// 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.
|
2025-01-19 15:10:02 -07:00
|
|
|
Addr() net.Addr
|
|
|
|
}
|
2025-01-19 17:29:04 -07:00
|
|
|
|
|
|
|
// Listen listens for incoming HOPP connections. The network must be one of
|
|
|
|
// "quic", "quic4", (IPv4-only) "quic6" (IPv6-only), or "unix".
|
|
|
|
func Listen(network, address string) (Listener, error) {
|
|
|
|
switch network {
|
|
|
|
case "quic", "quic4", "quic6": return ListenQUIC(network, address, nil)
|
|
|
|
case "unix": return ListenUnix(network, address)
|
|
|
|
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)
|
|
|
|
quicConf := quicConfig()
|
|
|
|
udpNetwork, err := quicNetworkToUDPNetwork(network)
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
addr, err := net.ResolveUDPAddr(udpNetwork, address)
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
udpListener, err := net.ListenUDP(udpNetwork, addr)
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
quicListener, err := quic.Listen(udpListener, tlsConf, quicConf)
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
return &listenerQUIC {
|
|
|
|
underlying: quicListener,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListenUnix listens for incoming HOPP connections using a Unix domain socket
|
|
|
|
// as a transport. The network must be "unix".
|
|
|
|
func ListenUnix(network, address string) (Listener, error) {
|
|
|
|
if network != "unix" { return nil, ErrUnknownNetwork }
|
|
|
|
addr, err := net.ResolveUnixAddr(network, address)
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
unixListener, err := net.ListenUnix(network, addr)
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
return &listenerUnix {
|
|
|
|
underlying: unixListener,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type listenerQUIC struct {
|
|
|
|
underlying *quic.Listener
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *listenerQUIC) Accept() (Conn, error) {
|
|
|
|
conn, err := this.underlying.Accept(context.Background())
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
return AdaptB(quicMultiConn { underlying: conn }), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *listenerQUIC) Close() error {
|
|
|
|
return this.underlying.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *listenerQUIC) Addr() net.Addr {
|
|
|
|
return this.underlying.Addr()
|
|
|
|
}
|
|
|
|
|
|
|
|
type listenerUnix struct {
|
|
|
|
underlying *net.UnixListener
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *listenerUnix) Accept() (Conn, error) {
|
|
|
|
conn, err := this.underlying.Accept()
|
|
|
|
if err != nil { return nil, err }
|
|
|
|
return AdaptA(conn, ServerSide), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *listenerUnix) Close() error {
|
|
|
|
return this.underlying.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (this *listenerUnix) Addr() net.Addr {
|
|
|
|
return this.underlying.Addr()
|
|
|
|
}
|