mirror of
https://github.com/linka-cloud/grpc.git
synced 2026-01-08 19:14:03 +00:00
feat(server/client): add windows pipe, pipe peer credentials support
Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package client
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
@@ -19,7 +20,7 @@ type Client interface {
|
||||
}
|
||||
|
||||
func New(opts ...Option) (Client, error) {
|
||||
c := &client{opts: &options{}}
|
||||
c := &client{opts: &options{dialOptions: []grpc.DialOption{grpc.WithContextDialer(dial)}}}
|
||||
for _, o := range opts {
|
||||
o(c.opts)
|
||||
}
|
||||
@@ -78,3 +79,32 @@ func (c *client) Invoke(ctx context.Context, method string, args interface{}, re
|
||||
func (c *client) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
|
||||
return c.cc.NewStream(ctx, desc, method, opts...)
|
||||
}
|
||||
|
||||
func parseDialTarget(target string) (string, 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" {
|
||||
return n, target[m1+1:]
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(target, `\\.\pipe\`) {
|
||||
net = "pipe"
|
||||
return net, target
|
||||
}
|
||||
if m2 >= 0 {
|
||||
t, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return net, target
|
||||
}
|
||||
scheme := t.Scheme
|
||||
addr := t.Host
|
||||
if scheme == "unix" {
|
||||
addr += t.Path
|
||||
}
|
||||
return scheme, addr
|
||||
}
|
||||
return net, target
|
||||
}
|
||||
|
||||
26
client/client_test.go
Normal file
26
client/client_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseDialTarget(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expectedNet string
|
||||
expectedAddr string
|
||||
}{
|
||||
{"tcp://localhost:50051", "tcp", "localhost:50051"},
|
||||
{"localhost:50051", "tcp", "localhost:50051"},
|
||||
{"unix:///tmp/socket", "unix", "/tmp/socket"},
|
||||
{"unix://C:/path/to/socket", "unix", "C:/path/to/socket"},
|
||||
{"unix:path/to/socket", "unix", "path/to/socket"},
|
||||
{`\\.\pipe\example`, "pipe", `\\.\pipe\example`},
|
||||
}
|
||||
for _, test := range tests {
|
||||
net, addr := parseDialTarget(test.input)
|
||||
if net != test.expectedNet || addr != test.expectedAddr {
|
||||
t.Errorf("parseDialTarget(%q) = (%q, %q); want (%q, %q)", test.input, net, addr, test.expectedNet, test.expectedAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
12
client/dialer.go
Normal file
12
client/dialer.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !windows
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
)
|
||||
|
||||
func dial(ctx context.Context, addr string) (net.Conn, error) {
|
||||
network, address := parseDialTarget(addr)
|
||||
return (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
}
|
||||
18
client/dialer_windows.go
Normal file
18
client/dialer_windows.go
Normal file
@@ -0,0 +1,18 @@
|
||||
//go:build windows
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
func dial(ctx context.Context, addr string) (net.Conn, error) {
|
||||
network, address := parseDialTarget(addr)
|
||||
if network == "pipe" {
|
||||
return winio.DialPipeContext(ctx, address)
|
||||
}
|
||||
return (&net.Dialer{}).DialContext(ctx, network, address)
|
||||
}
|
||||
Reference in New Issue
Block a user