From 73169184021d88c5027746d96bdb4bfab484db22 Mon Sep 17 00:00:00 2001 From: Sam Batschelet Date: Mon, 9 Apr 2018 14:12:34 -0400 Subject: [PATCH] clientconn: add support for unix network in DialContext. (#1883) --- clientconn.go | 3 ++- rpc_util.go | 35 +++++++++++++++++++++++++++++++++++ rpc_util_test.go | 21 +++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/clientconn.go b/clientconn.go index 53375ed9..513fb3fa 100644 --- a/clientconn.go +++ b/clientconn.go @@ -443,7 +443,8 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * if cc.dopts.copts.Dialer == nil { cc.dopts.copts.Dialer = newProxyDialer( func(ctx context.Context, addr string) (net.Conn, error) { - return dialContext(ctx, "tcp", addr) + network, addr := parseDialTarget(addr) + return dialContext(ctx, network, addr) }, ) } diff --git a/rpc_util.go b/rpc_util.go index c8ece65b..bcdde3e3 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -26,6 +26,7 @@ import ( "io" "io/ioutil" "math" + "net/url" "strings" "sync" "time" @@ -672,6 +673,40 @@ func setCallInfoCodec(c *callInfo) error { return nil } +// parseDialTarget returns the network and address to pass to dialer +func parseDialTarget(target string) (net string, addr string) { + net = "tcp" + + m1 := strings.Index(target, ":") + m2 := strings.Index(target, ":/") + + // handle unix:addr which will fail with url.Parse + if m1 >= 0 && m2 < 0 { + if n := target[0:m1]; n == "unix" { + net = n + addr = target[m1+1:] + return net, addr + } + } + if m2 >= 0 { + t, err := url.Parse(target) + if err != nil { + return net, target + } + scheme := t.Scheme + addr = t.Path + if scheme == "unix" { + net = scheme + if addr == "" { + addr = t.Host + } + return net, addr + } + } + + return net, target +} + // The SupportPackageIsVersion variables are referenced from generated protocol // buffer files to ensure compatibility with the gRPC version used. The latest // support package version is 5. diff --git a/rpc_util_test.go b/rpc_util_test.go index bf933318..770e850c 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -188,6 +188,27 @@ func TestToRPCErr(t *testing.T) { } } +func TestParseDialTarget(t *testing.T) { + for _, test := range []struct { + target, wantNet, wantAddr string + }{ + {"unix:etcd:0", "unix", "etcd:0"}, + {"unix:///tmp/unix-3", "unix", "/tmp/unix-3"}, + {"unix://domain", "unix", "domain"}, + {"unix://etcd:0", "unix", "etcd:0"}, + {"unix:///etcd:0", "unix", "/etcd:0"}, + {"passthrough://unix://domain", "tcp", "passthrough://unix://domain"}, + {"https://google.com:443", "tcp", "https://google.com:443"}, + {"dns:///google.com", "tcp", "dns:///google.com"}, + {"/unix/socket/address", "tcp", "/unix/socket/address"}, + } { + gotNet, gotAddr := parseDialTarget(test.target) + if gotNet != test.wantNet || gotAddr != test.wantAddr { + t.Errorf("parseDialTarget(%q) = %s, %s want %s, %s", test.target, gotNet, gotAddr, test.wantNet, test.wantAddr) + } + } +} + // bmEncode benchmarks encoding a Protocol Buffer message containing mSize // bytes. func bmEncode(b *testing.B, mSize int) {