80 lines
2.5 KiB
Go
80 lines
2.5 KiB
Go
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".
|
|
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".
|
|
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) {
|
|
udpNetwork, err := quicNetworkToUDPNetwork(network)
|
|
if err != nil { return nil, err }
|
|
addr, err := net.ResolveUDPAddr(udpNetwork, address)
|
|
if err != nil { return nil, err }
|
|
udpConn, err := net.DialUDP(udpNetwork, nil, addr)
|
|
if err != nil { return nil, err }
|
|
conn, err := quic.Dial(ctx, udpConn, addr, 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
|
|
}
|
|
}
|