Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

support unix-abstract schema #4079

Merged
merged 9 commits into from
Dec 22, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clientconn.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
cc.authority = creds.Info().ServerName
} else if cc.dopts.insecure && cc.dopts.authority != "" {
cc.authority = cc.dopts.authority
} else if strings.HasPrefix(cc.target, "unix:") {
} else if strings.HasPrefix(cc.target, "unix:") || strings.HasPrefix(cc.target, "unix-abstract:") {
cc.authority = "localhost"
} else if strings.HasPrefix(cc.parsedTarget.Endpoint, ":") {
cc.authority = "localhost" + cc.parsedTarget.Endpoint
Expand Down
10 changes: 8 additions & 2 deletions internal/grpcutil/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,15 @@ func split2(s, sep string) (string, string, bool) {
// not parse "unix:[path]" cases. This should be true in cases where a custom
// dialer is present, to prevent a behavior change.
//
// If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
// target}.
// If target is not valid dns/unix/unix-abstract schemas as specified in
// https://github.com/grpc/grpc/blob/master/doc/naming.md,
// it returns {Endpoint: target}.
func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) {
if strings.HasPrefix(target, "unix-abstract:") {
// Handle unix-abstract case, split the target by ":"
scheme, endpoint, _ := split2(target, ":")
return resolver.Target{Scheme: scheme, Endpoint: endpoint}
}
var ok bool
ret.Scheme, ret.Endpoint, ok = split2(target, "://")
if !ok {
Expand Down
10 changes: 10 additions & 0 deletions internal/grpcutil/target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ func TestParseTargetString(t *testing.T) {
{targetStr: "unix:/a/b/c", want: resolver.Target{Scheme: "unix", Authority: "", Endpoint: "/a/b/c"}, wantWithDialer: resolver.Target{Scheme: "", Authority: "", Endpoint: "unix:/a/b/c"}},
{targetStr: "unix:///a/b/c", want: resolver.Target{Scheme: "unix", Authority: "", Endpoint: "/a/b/c"}},

{targetStr: "unix-abstract:a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a/b/c"}},
{targetStr: "unix-abstract:a b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a b"}},
{targetStr: "unix-abstract:a:b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a:b"}},
{targetStr: "unix-abstract:a-b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "a-b"}},
{targetStr: "unix-abstract:/ a///://::!@#$%^&*()b", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "/ a///://::!@#$%^&*()b"}},
{targetStr: "unix-abstract:passthrough:abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "passthrough:abc"}},
{targetStr: "unix-abstract:unix:///abc", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "unix:///abc"}},
{targetStr: "unix-abstract:///a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "///a/b/c"}},
{targetStr: "unix-abstract://authority/a/b/c", want: resolver.Target{Scheme: "unix-abstract", Authority: "", Endpoint: "//authority/a/b/c"}},

{targetStr: "passthrough:///unix:///a/b/c", want: resolver.Target{Scheme: "passthrough", Authority: "", Endpoint: "unix:///a/b/c"}},
} {
got := ParseTarget(test.targetStr, false)
Expand Down
23 changes: 16 additions & 7 deletions internal/resolver/unix/unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,28 @@ import (
"google.golang.org/grpc/resolver"
)

const scheme = "unix"
const unixScheme = "unix"
const unixAbstractScheme = "unix-abstract"

type builder struct{}
type builder struct {
scheme string
}

func (*builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
if target.Authority != "" {
return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.Authority)
}
cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(resolver.Address{Addr: target.Endpoint}, "unix")}})
addr := resolver.Address{Addr: target.Endpoint}
if b.scheme == unixAbstractScheme {
// prepend "\x00" to address for unix-abstract
addr.Addr = "\x00" + addr.Addr
}
cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}})
return &nopResolver{}, nil
}

func (*builder) Scheme() string {
return scheme
func (b *builder) Scheme() string {
return b.scheme
}

type nopResolver struct {
Expand All @@ -50,5 +58,6 @@ func (*nopResolver) ResolveNow(resolver.ResolveNowOptions) {}
func (*nopResolver) Close() {}

func init() {
resolver.Register(&builder{})
resolver.Register(&builder{scheme: unixScheme})
resolver.Register(&builder{scheme: unixAbstractScheme})
}
2 changes: 1 addition & 1 deletion internal/transport/http2_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error
address := addr.Addr
networkType, ok := networktype.Get(addr)
if fn != nil {
if networkType == "unix" {
if networkType == "unix" && !strings.HasPrefix(address, "\x00") {
// For backward compatibility, if the user dialed "unix:///path",
// the passthrough resolver would be used and the user's custom
// dialer would see "unix:///path". Since the unix resolver is used
Expand Down
18 changes: 15 additions & 3 deletions test/authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"net"
"os"
"strings"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -53,8 +54,10 @@ func authorityChecker(ctx context.Context, expectedAuthority string) (*testpb.Em
}

func runUnixTest(t *testing.T, address, target, expectedAuthority string, dialer func(context.Context, string) (net.Conn, error)) {
if err := os.RemoveAll(address); err != nil {
t.Fatalf("Error removing socket file %v: %v\n", address, err)
if !strings.HasPrefix(target, "unix-abstract:") {
if err := os.RemoveAll(address); err != nil {
t.Fatalf("Error removing socket file %v: %v\n", address, err)
}
}
ss := &stubServer{
emptyCall: func(ctx context.Context, _ *testpb.Empty) (*testpb.Empty, error) {
Expand Down Expand Up @@ -114,6 +117,13 @@ var authorityTests = []authorityTest{
authority: "unix:///tmp/sock.sock",
dialTargetWant: "unix:///tmp/sock.sock",
},
{
name: "UnixAbstract",
address: "\x00abc efg",
target: "unix-abstract:abc efg",
authority: "localhost",
dialTargetWant: "\x00abc efg",
},
}

// TestUnix does end to end tests with the various supported unix target
Expand All @@ -139,7 +149,9 @@ func (s) TestUnixCustomDialer(t *testing.T) {
if address != test.dialTargetWant {
return nil, fmt.Errorf("expected target %v in custom dialer, instead got %v", test.dialTargetWant, address)
}
address = address[len("unix:"):]
if !strings.HasPrefix(test.target, "unix-abstract:") {
address = address[len("unix:"):]
}
return (&net.Dialer{}).DialContext(ctx, "unix", address)
}
runUnixTest(t, test.address, test.target, test.authority, dialer)
Expand Down