This commit is contained in:
qaq
2025-06-17 12:17:33 +08:00
parent 4a6b2c8e0f
commit 9fa968d07c
648 changed files with 64968 additions and 1621 deletions
+81
View File
@@ -0,0 +1,81 @@
package grpc
import (
"context"
"errors"
"net"
"time"
pb "github.com/go-gost/x/internal/util/grpc/proto"
)
type conn struct {
c pb.GostTunel_TunnelClient
rb []byte
localAddr net.Addr
remoteAddr net.Addr
cancelFunc context.CancelFunc
}
func (c *conn) Read(b []byte) (n int, err error) {
select {
case <-c.c.Context().Done():
err = c.c.Context().Err()
return
default:
}
if len(c.rb) == 0 {
chunk, err := c.c.Recv()
if err != nil {
return 0, err
}
c.rb = chunk.Data
}
n = copy(b, c.rb)
c.rb = c.rb[n:]
return
}
func (c *conn) Write(b []byte) (n int, err error) {
select {
case <-c.c.Context().Done():
err = c.c.Context().Err()
return
default:
}
if err = c.c.Send(&pb.Chunk{
Data: b,
}); err != nil {
return
}
n = len(b)
return
}
func (c *conn) Close() error {
defer c.cancelFunc()
return c.c.CloseSend()
}
func (c *conn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *conn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *conn) SetDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *conn) SetReadDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
func (c *conn) SetWriteDeadline(t time.Time) error {
return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
}
+118
View File
@@ -0,0 +1,118 @@
package grpc
import (
"context"
"net"
"sync"
"github.com/go-gost/core/dialer"
md "github.com/go-gost/core/metadata"
pb "github.com/go-gost/x/internal/util/grpc/proto"
"github.com/go-gost/x/registry"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
)
func init() {
registry.DialerRegistry().Register("grpc", NewDialer)
}
type grpcDialer struct {
clients map[string]pb.GostTunelClientX
clientMutex sync.Mutex
md metadata
options dialer.Options
}
func NewDialer(opts ...dialer.Option) dialer.Dialer {
options := dialer.Options{}
for _, opt := range opts {
opt(&options)
}
return &grpcDialer{
clients: make(map[string]pb.GostTunelClientX),
options: options,
}
}
func (d *grpcDialer) Init(md md.Metadata) (err error) {
return d.parseMetadata(md)
}
// Multiplex implements dialer.Multiplexer interface.
func (d *grpcDialer) Multiplex() bool {
return true
}
func (d *grpcDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) {
d.clientMutex.Lock()
defer d.clientMutex.Unlock()
client, ok := d.clients[addr]
if !ok {
var options dialer.DialOptions
for _, opt := range opts {
opt(&options)
}
host := d.md.host
if host == "" {
host = options.Host
}
if h, _, _ := net.SplitHostPort(host); h != "" {
host = h
}
// d.options.Logger.Infof("grpc dialer, addr %s, host %s/%s", addr, d.md.host, options.Host)
grpcOpts := []grpc.DialOption{
// grpc.WithBlock(),
grpc.WithContextDialer(func(c context.Context, s string) (net.Conn, error) {
return options.Dialer.Dial(c, "tcp", s)
}),
grpc.WithAuthority(host),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoff.DefaultConfig,
MinConnectTimeout: d.md.minConnectTimeout,
}),
}
if !d.md.insecure {
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(credentials.NewTLS(d.options.TLSConfig)))
} else {
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
if d.md.keepalive {
grpcOpts = append(grpcOpts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
Time: d.md.keepaliveTime,
Timeout: d.md.keepaliveTimeout,
PermitWithoutStream: d.md.keepalivePermitWithoutStream,
}))
}
cc, err := grpc.NewClient(addr, grpcOpts...)
if err != nil {
d.options.Logger.Error(err)
return nil, err
}
client = pb.NewGostTunelClientX(cc)
d.clients[addr] = client
}
ctx2, cancel := context.WithCancel(context.Background())
cli, err := client.TunnelX(ctx2, d.md.path)
if err != nil {
cancel()
return nil, err
}
return &conn{
c: cli,
localAddr: &net.TCPAddr{},
remoteAddr: &net.TCPAddr{},
cancelFunc: cancel,
}, nil
}
+43
View File
@@ -0,0 +1,43 @@
package grpc
import (
"time"
mdata "github.com/go-gost/core/metadata"
mdutil "github.com/go-gost/x/metadata/util"
)
type metadata struct {
insecure bool
host string
path string
keepalive bool
keepaliveTime time.Duration
keepaliveTimeout time.Duration
keepalivePermitWithoutStream bool
minConnectTimeout time.Duration
}
func (d *grpcDialer) parseMetadata(md mdata.Metadata) (err error) {
d.md.insecure = mdutil.GetBool(md, "grpc.insecure", "grpcInsecure", "insecure")
d.md.host = mdutil.GetString(md, "grpc.authority", "grpc.host", "host")
d.md.path = mdutil.GetString(md, "grpc.path", "path")
d.md.keepalive = mdutil.GetBool(md, "grpc.keepalive", "keepalive", "keepAlive")
if d.md.keepalive {
d.md.keepaliveTime = mdutil.GetDuration(md, "grpc.keepalive.time", "keepalive.time")
if d.md.keepaliveTime <= 0 {
d.md.keepaliveTime = 30 * time.Second
}
d.md.keepaliveTimeout = mdutil.GetDuration(md, "grpc.keepalive.timeout", "keepalive.timeout")
if d.md.keepaliveTimeout <= 0 {
d.md.keepaliveTimeout = 30 * time.Second
}
d.md.keepalivePermitWithoutStream = mdutil.GetBool(md, "grpc.keepalive.permitWithoutStream", "keepalive.permitWithoutStream")
}
d.md.minConnectTimeout = mdutil.GetDuration(md, "grpc.minConnectTimeout", "minConnectTimeout")
if d.md.minConnectTimeout <= 0 {
d.md.minConnectTimeout = 30 * time.Second
}
return
}