mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-13 12:46:36 +08:00
init
This commit is contained in:
@@ -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")}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user