95 lines
2.7 KiB
Go
95 lines
2.7 KiB
Go
package hopp
|
|
|
|
import "net"
|
|
import "errors"
|
|
import "context"
|
|
import "crypto/tls"
|
|
|
|
// Dial opens a connection to a server. 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 Dial(ctx context.Context, network, address string, tlsConf *tls.Config) (Conn, error) {
|
|
switch network {
|
|
case "quic", "quic4", "quic6": return DialQUIC(ctx, network, address, tlsConf)
|
|
case "tls", "tls4", "tls6": return DialTLS(ctx, network, address, tlsConf)
|
|
case "tcp", "tcp4", "tcp6":
|
|
addr, err := net.ResolveTCPAddr(network, address)
|
|
if err != nil { return nil, err }
|
|
return DialTCP(ctx, network, nil, addr)
|
|
case "unix":
|
|
addr, err := net.ResolveUnixAddr(network, address)
|
|
if err != nil { return nil, err }
|
|
return DialUnix(ctx, network, addr)
|
|
default: return nil, ErrUnknownNetwork
|
|
}
|
|
}
|
|
|
|
// DialQUIC opens a connection to a server over QUIC.
|
|
func DialQUIC(ctx context.Context, network, address string, tlsConf *tls.Config) (Conn, error) {
|
|
return nil, errors.New("quic is not yet implemented")
|
|
}
|
|
|
|
// DialTLS opens a connection to a server over TLS.
|
|
func DialTLS(ctx context.Context, network, address string, tlsConf *tls.Config) (Conn, error) {
|
|
network, err := tlsNetworkToTCPNetwork(network)
|
|
if err != nil { return nil, err }
|
|
conn, err := tls.Dial(network, address, tlsConf)
|
|
if err != nil { return nil, err }
|
|
return AdaptA(conn, ClientSide), nil
|
|
}
|
|
|
|
// DialTCP opens a connection to a server over TCP.
|
|
func DialTCP(ctx context.Context, network string, laddr, raddr *net.TCPAddr) (Conn, error) {
|
|
conn, err := net.DialTCP(network, laddr, raddr)
|
|
if err != nil { return nil, err }
|
|
return AdaptA(conn, ClientSide), nil
|
|
}
|
|
|
|
// DialUnix opens a connection to a server over a Unix domain socket.
|
|
func DialUnix(ctx context.Context, network string, addr *net.UnixAddr) (Conn, error) {
|
|
conn, err := net.DialUnix(network, nil, addr)
|
|
if err != nil { return nil, err }
|
|
return AdaptA(conn, ClientSide), nil
|
|
}
|
|
|
|
func tlsConfig(conf *tls.Config) *tls.Config {
|
|
if conf == nil {
|
|
conf = &tls.Config { }
|
|
} else {
|
|
conf = conf.Clone()
|
|
}
|
|
conf.NextProtos = []string {
|
|
"HOPP/0",
|
|
}
|
|
return conf
|
|
}
|
|
|
|
func quicNetworkToUDPNetwork(network string) (string, error) {
|
|
switch network {
|
|
case "quic4": return "udp4", nil
|
|
case "quic6": return "udp6", nil
|
|
case "quic": return "udp", nil
|
|
default: return "", ErrUnknownNetwork
|
|
}
|
|
}
|
|
|
|
func tlsNetworkToTCPNetwork(network string) (string, error) {
|
|
switch network {
|
|
case "tls4": return "tcp4", nil
|
|
case "tls6": return "tcp6", nil
|
|
case "tls": return "tcp", nil
|
|
default: return "", ErrUnknownNetwork
|
|
}
|
|
}
|