From 6f861b64893291acb010591dc44eb76612648ae1 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 24 Jun 2021 15:25:11 +0300 Subject: [PATCH] [#607] network: Support URI address strings Make Address.FromString method to parse URI addresses and enable TLS for TLS schemes. Signed-off-by: Leonard Lyubich --- pkg/network/address.go | 39 +++++++++++++++++++++++++++++++++++-- pkg/network/address_test.go | 2 ++ pkg/network/tls_test.go | 9 ++++++--- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/pkg/network/address.go b/pkg/network/address.go index 8fe808a20..a1758a497 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -3,6 +3,7 @@ package network import ( "fmt" "net" + "net/url" "strings" "github.com/multiformats/go-multiaddr" @@ -13,6 +14,7 @@ import ( HostAddr strings: "localhost:8080", ":8080", "192.168.0.1:8080" MultiAddr strings: "/dns4/localhost/tcp/8080", "/ip4/192.168.0.1/tcp/8080" IPAddr strings: "192.168.0.1:8080" + URIAddr strings: "127.0.0.1:8080" */ // Address represents the NeoFS node @@ -53,21 +55,54 @@ func (a Address) HostAddr() string { // FromString restores Address from a string representation. // -// Supports MultiAddr and HostAddr strings. +// Supports URIAddr, MultiAddr and HostAddr strings. func (a *Address) FromString(s string) error { var err error a.ma, err = multiaddr.NewMultiaddr(s) if err != nil { - s, err = multiaddrStringFromHostAddr(s) + var u uri + + u.parse(s) + + s, err = multiaddrStringFromHostAddr(u.host) if err == nil { a.ma, err = multiaddr.NewMultiaddr(s) + if err == nil && u.tls { + a.ma = a.ma.Encapsulate(tls) + } } } return err } +type uri struct { + host string + tls bool +} + +const grpcTLSScheme = "grpcs" + +func (u *uri) parse(s string) { + // TODO: code is copy-pasted from client.WithURIAddress function. + // Would be nice to share the code. + uri, err := url.ParseRequestURI(s) + isURI := err == nil + + if isURI && uri.Host != "" { + u.host = uri.Host + } else { + u.host = s + } + + // check if passed string was parsed correctly + // URIs that do not start with a slash after the scheme are interpreted as: + // `scheme:opaque` => if `opaque` is not empty, then it is supposed that URI + // is in `host:port` format + u.tls = isURI && uri.Opaque == "" && uri.Scheme == grpcTLSScheme +} + // multiaddrStringFromHostAddr converts "localhost:8080" to "/dns4/localhost/tcp/8080" func multiaddrStringFromHostAddr(host string) (string, error) { endpoint, port, err := net.SplitHostPort(host) diff --git a/pkg/network/address_test.go b/pkg/network/address_test.go index a293b7ed1..91148a9e3 100644 --- a/pkg/network/address_test.go +++ b/pkg/network/address_test.go @@ -17,6 +17,8 @@ func TestAddressFromString(t *testing.T) { {"example.com:7070", buildMultiaddr("/dns4/example.com/tcp/7070", t)}, {"213.44.87.1:32512", buildMultiaddr("/ip4/213.44.87.1/tcp/32512", t)}, {"[2004:eb1::1]:8080", buildMultiaddr("/ip6/2004:eb1::1/tcp/8080", t)}, + {"grpc://example.com:7070", buildMultiaddr("/dns4/example.com/tcp/7070", t)}, + {grpcTLSScheme + "://example.com:7070", buildMultiaddr("/dns4/example.com/tcp/7070/"+tlsProtocolName, t)}, } var addr Address diff --git a/pkg/network/tls_test.go b/pkg/network/tls_test.go index 541369c7f..c7715b449 100644 --- a/pkg/network/tls_test.go +++ b/pkg/network/tls_test.go @@ -14,12 +14,15 @@ func TestAddress_TLSEnabled(t *testing.T) { {"/dns4/localhost/tcp/8080", false}, {"/dns4/localhost/tcp/8080/tls", true}, {"/tls/dns4/localhost/tcp/8080", true}, + {"grpc://localhost:8080", false}, + {"grpcs://localhost:8080", true}, } + var addr Address + for _, test := range testCases { - addr := Address{ - ma: buildMultiaddr(test.input, t), - } + err := addr.FromString(test.input) + require.NoError(t, err) require.Equal(t, test.wantTLS, addr.TLSEnabled(), test.input) }