unix.go raw

   1  /*
   2   *
   3   * Copyright 2020 gRPC authors.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   *
  17   */
  18  
  19  // Package unix implements a resolver for unix targets.
  20  package unix
  21  
  22  import (
  23  	"fmt"
  24  
  25  	"google.golang.org/grpc/internal/transport/networktype"
  26  	"google.golang.org/grpc/resolver"
  27  )
  28  
  29  const unixScheme = "unix"
  30  const unixAbstractScheme = "unix-abstract"
  31  
  32  type builder struct {
  33  	scheme string
  34  }
  35  
  36  func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
  37  	if target.URL.Host != "" {
  38  		return nil, fmt.Errorf("invalid (non-empty) authority: %v", target.URL.Host)
  39  	}
  40  
  41  	// gRPC was parsing the dial target manually before PR #4817, and we
  42  	// switched to using url.Parse() in that PR. To avoid breaking existing
  43  	// resolver implementations we ended up stripping the leading "/" from the
  44  	// endpoint. This obviously does not work for the "unix" scheme. Hence we
  45  	// end up using the parsed URL instead.
  46  	endpoint := target.URL.Path
  47  	if endpoint == "" {
  48  		endpoint = target.URL.Opaque
  49  	}
  50  	addr := resolver.Address{Addr: endpoint}
  51  	if b.scheme == unixAbstractScheme {
  52  		// We can not prepend \0 as c++ gRPC does, as in Golang '@' is used to signify we do
  53  		// not want trailing \0 in address.
  54  		addr.Addr = "@" + addr.Addr
  55  	}
  56  	cc.UpdateState(resolver.State{Addresses: []resolver.Address{networktype.Set(addr, "unix")}})
  57  	return &nopResolver{}, nil
  58  }
  59  
  60  func (b *builder) Scheme() string {
  61  	return b.scheme
  62  }
  63  
  64  func (b *builder) OverrideAuthority(resolver.Target) string {
  65  	return "localhost"
  66  }
  67  
  68  type nopResolver struct {
  69  }
  70  
  71  func (*nopResolver) ResolveNow(resolver.ResolveNowOptions) {}
  72  
  73  func (*nopResolver) Close() {}
  74  
  75  func init() {
  76  	resolver.Register(&builder{scheme: unixScheme})
  77  	resolver.Register(&builder{scheme: unixAbstractScheme})
  78  }
  79