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