hopp/dial.go

83 lines
2.8 KiB
Go

package hopp
import "net"
import "context"
import "crypto/tls"
import "github.com/quic-go/quic-go"
// TODO: dial should be super simple like it is now, and there should be a
// "dialer" which the dial function dial configures automaticaly, but the dialer
// should offer much more options when used directlym
// Dial opens a connection to a server. The network must be one of "udp",
// "udp4", "udp6", or "unixgram".
func Dial(ctx context.Context, network, address string) (Conn, error) {
return (Dialer { }).Dial(ctx, network, address)
}
// TODO: export when there are options here
type Dialer struct {
TLSConfig *tls.Config
}
// Dial opens a connection to a server. The network must be one of "quic",
// "quic4", "quic6", 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, diale.tlsConfig(), diale.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 }
// REMEMBER - THIS IS VERY IMPORTANT:
// WHEN YOU INEVITABLY COPY PASTE THIS FOR THE SERVER-SIDE, CHANGE THE
// PARTY CONSTANT TO ServerSide! OTHERWISE THERE WILL BE COLLISIONS!
return AdaptA(conn, ClientSide), nil
}
func (diale Dialer) tlsConfig() *tls.Config {
conf := diale.TLSConfig.Clone()
conf.NextProtos = []string {
"HOPP/0",
}
return conf
}
func (diale Dialer) 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
}
}