hopp/listen.go

96 lines
2.8 KiB
Go
Raw Permalink Normal View History

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()
}