package hopp import "net" import "context" import "crypto/tls" import "github.com/quic-go/quic-go" // Dial opens a connection to a server. The network must be one of "quic", // "quic4", (IPv4-only) "quic6" (IPv6-only), or "unix". For now, "quic4" and // "quic6" don't do anything as the quic-go package doesn't seem to support this // behavior. func Dial(ctx context.Context, network, address string) (Conn, error) { return (Dialer { }).Dial(ctx, network, address) } // Dialer allows for further configuration of the dialing process. type Dialer struct { TLSConfig *tls.Config } // Dial opens a connection to a server. The network must be one of "quic", // "quic4", (IPv4-only) "quic6" (IPv6-only), or "unix". For now, "quic4" and // "quic6" don't do anything as the quic-go package doesn't seem to support this // behavior. func (diale Dialer) Dial(ctx context.Context, network, address string) (Conn, error) { switch network { case "quic", "quic4", "quic6": return diale.dialQUIC(ctx, network, address) case "unix": return diale.dialUnix(ctx, network, address) default: return nil, ErrUnknownNetwork } } func (diale Dialer) dialQUIC(ctx context.Context, network, address string) (Conn, error) { // sorry i fucking lied to you about the network parameter. for all // quic-go's bullshit bloat, it doesnt even support that. not even when // instantiating a transport. go figure :/ conn, err := quic.DialAddr(ctx, address, tlsConfig(diale.TLSConfig), quicConfig()) if err != nil { return nil, err } return AdaptB(quicMultiConn { underlying: conn }), nil } func (diale Dialer) dialUnix(ctx context.Context, network, address string) (Conn, error) { if network != "unix" { return nil, ErrUnknownNetwork } addr, err := net.ResolveUnixAddr(network, address) if err != nil { return nil, err } 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 quicConfig() *quic.Config { return &quic.Config { // TODO: perhaps we might want to put something here // the quic config shouldn't be exported, just set up // automatically. we can't have that strangely built quic-go // package be part of the API, or any third-party packages for // that matter. it must all be abstracted away. } } 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 } }