netxlite: factor common code for parsing UDPAddr (#730)
This diff has been extracted from c2f7ccab0e
See https://github.com/ooni/probe/issues/2096
This commit is contained in:
parent
2238908afe
commit
6c388d2c61
|
@ -94,6 +94,29 @@ var _ model.QUICDialer = &quicDialerQUICGo{}
|
||||||
// ErrInvalidIP indicates that a string is not a valid IP.
|
// ErrInvalidIP indicates that a string is not a valid IP.
|
||||||
var ErrInvalidIP = errors.New("netxlite: invalid IP")
|
var ErrInvalidIP = errors.New("netxlite: invalid IP")
|
||||||
|
|
||||||
|
// ParseUDPAddr maps the string representation of an UDP endpoint to the
|
||||||
|
// corresponding *net.UDPAddr representation.
|
||||||
|
func ParseUDPAddr(address string) (*net.UDPAddr, error) {
|
||||||
|
addr, port, err := net.SplitHostPort(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ipAddr := net.ParseIP(addr)
|
||||||
|
if ipAddr == nil {
|
||||||
|
return nil, ErrInvalidIP
|
||||||
|
}
|
||||||
|
dport, err := strconv.Atoi(port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
udpAddr := &net.UDPAddr{
|
||||||
|
IP: ipAddr,
|
||||||
|
Port: dport,
|
||||||
|
Zone: "",
|
||||||
|
}
|
||||||
|
return udpAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DialContext implements QUICDialer.DialContext. This function will
|
// DialContext implements QUICDialer.DialContext. This function will
|
||||||
// apply the following TLS defaults:
|
// apply the following TLS defaults:
|
||||||
//
|
//
|
||||||
|
@ -105,24 +128,15 @@ var ErrInvalidIP = errors.New("netxlite: invalid IP")
|
||||||
func (d *quicDialerQUICGo) DialContext(ctx context.Context, network string,
|
func (d *quicDialerQUICGo) DialContext(ctx context.Context, network string,
|
||||||
address string, tlsConfig *tls.Config, quicConfig *quic.Config) (
|
address string, tlsConfig *tls.Config, quicConfig *quic.Config) (
|
||||||
quic.EarlyConnection, error) {
|
quic.EarlyConnection, error) {
|
||||||
onlyhost, onlyport, err := net.SplitHostPort(address)
|
udpAddr, err := ParseUDPAddr(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
port, err := strconv.Atoi(onlyport)
|
pconn, err := d.QUICListener.Listen(&net.UDPAddr{IP: net.IPv4zero, Port: 0, Zone: ""})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ip := net.ParseIP(onlyhost)
|
tlsConfig = d.maybeApplyTLSDefaults(tlsConfig, udpAddr.Port)
|
||||||
if ip == nil {
|
|
||||||
return nil, ErrInvalidIP
|
|
||||||
}
|
|
||||||
pconn, err := d.QUICListener.Listen(&net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
udpAddr := &net.UDPAddr{IP: ip, Port: port, Zone: ""}
|
|
||||||
tlsConfig = d.maybeApplyTLSDefaults(tlsConfig, port)
|
|
||||||
qconn, err := d.dialEarlyContext(
|
qconn, err := d.dialEarlyContext(
|
||||||
ctx, pconn, udpAddr, address, tlsConfig, quicConfig)
|
ctx, pconn, udpAddr, address, tlsConfig, quicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -45,6 +45,54 @@ func TestNewQUICDialer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseUDPAddr(t *testing.T) {
|
||||||
|
t.Run("cannot split host and port", func(t *testing.T) {
|
||||||
|
addr, err := ParseUDPAddr("1.2.3.4")
|
||||||
|
if err == nil || !strings.HasSuffix(err.Error(), "missing port in address") {
|
||||||
|
t.Fatal("unexpected error", err)
|
||||||
|
}
|
||||||
|
if addr != nil {
|
||||||
|
t.Fatal("expected nil addr")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with invalid IP addr", func(t *testing.T) {
|
||||||
|
addr, err := ParseUDPAddr("www.google.com:80")
|
||||||
|
if !errors.Is(err, ErrInvalidIP) {
|
||||||
|
t.Fatal("unexpected error", err)
|
||||||
|
}
|
||||||
|
if addr != nil {
|
||||||
|
t.Fatal("expected nil addr")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with invalid port", func(t *testing.T) {
|
||||||
|
addr, err := ParseUDPAddr("8.8.8.8:www")
|
||||||
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid syntax") {
|
||||||
|
t.Fatal("unexpected error", err)
|
||||||
|
}
|
||||||
|
if addr != nil {
|
||||||
|
t.Fatal("expected nil addr")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("with valid input", func(t *testing.T) {
|
||||||
|
addr, err := ParseUDPAddr("8.8.8.8:80")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if addr.IP.String() != "8.8.8.8" {
|
||||||
|
t.Fatal("invalid IP")
|
||||||
|
}
|
||||||
|
if addr.Port != 80 {
|
||||||
|
t.Fatal("invalid port")
|
||||||
|
}
|
||||||
|
if addr.Zone != "" {
|
||||||
|
t.Fatal("invalid zone")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestQUICDialerQUICGo(t *testing.T) {
|
func TestQUICDialerQUICGo(t *testing.T) {
|
||||||
t.Run("DialContext", func(t *testing.T) {
|
t.Run("DialContext", func(t *testing.T) {
|
||||||
t.Run("cannot split host port", func(t *testing.T) {
|
t.Run("cannot split host port", func(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user