blocky/service/listener.go

75 lines
1.7 KiB
Go

package service
import (
"context"
"crypto/tls"
"fmt"
"net"
)
// Listener is a net.Listener that provides information about
// what protocol and address it is configured for.
type Listener interface {
fmt.Stringer
net.Listener
// Exposes returns the endpoint for this listener.
//
// It can be used to find service(s) with matching configuration.
Exposes() Endpoint
}
// ListenerInfo can be embedded in structs to help implement Listener.
type ListenerInfo struct {
Endpoint
}
func (i *ListenerInfo) Exposes() Endpoint { return i.Endpoint }
// NetListener implements Listener using an existing net.Listener.
type NetListener struct {
net.Listener
ListenerInfo
}
func NewNetListener(endpoint Endpoint, inner net.Listener) *NetListener {
return &NetListener{
Listener: inner,
ListenerInfo: ListenerInfo{endpoint},
}
}
// TCPListener is a Listener for a TCP socket.
type TCPListener struct{ NetListener }
// ListenTCP creates a new TCPListener.
func ListenTCP(ctx context.Context, endpoint Endpoint) (*TCPListener, error) {
var lc net.ListenConfig
l, err := lc.Listen(ctx, "tcp", endpoint.AddrConf)
if err != nil {
return nil, err // err already has all the info we could add
}
inner := NewNetListener(endpoint, l)
return &TCPListener{*inner}, nil
}
// TLSListener is a Listener using TLS over TCP.
type TLSListener struct{ NetListener }
// ListenTLS creates a new TLSListener.
func ListenTLS(ctx context.Context, endpoint Endpoint, cfg *tls.Config) (*TLSListener, error) {
tcp, err := ListenTCP(ctx, endpoint)
if err != nil {
return nil, err
}
inner := tcp.NetListener
inner.Listener = tls.NewListener(inner.Listener, cfg)
return &TLSListener{inner}, nil
}