mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-03-11 02:49:57 +00:00
feat: add ping-interval to grpc-opts
This commit is contained in:
@@ -27,8 +27,7 @@ type Trojan struct {
|
||||
hexPassword [trojan.KeyLength]byte
|
||||
|
||||
// for gun mux
|
||||
gunConfig *gun.Config
|
||||
gunTransport *gun.TransportWrap
|
||||
gunTransport *gun.Transport
|
||||
|
||||
realityConfig *tlsC.RealityConfig
|
||||
echConfig *ech.Config
|
||||
@@ -178,7 +177,7 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Con
|
||||
var c net.Conn
|
||||
// gun transport
|
||||
if t.gunTransport != nil {
|
||||
c, err = gun.StreamGunWithTransport(t.gunTransport, t.gunConfig)
|
||||
c, err = t.gunTransport.Dial()
|
||||
} else {
|
||||
c, err = t.dialer.DialContext(ctx, "tcp", t.addr)
|
||||
}
|
||||
@@ -206,7 +205,7 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata)
|
||||
var c net.Conn
|
||||
// grpc transport
|
||||
if t.gunTransport != nil {
|
||||
c, err = gun.StreamGunWithTransport(t.gunTransport, t.gunConfig)
|
||||
c, err = t.gunTransport.Dial()
|
||||
} else {
|
||||
c, err = t.dialer.DialContext(ctx, "tcp", t.addr)
|
||||
}
|
||||
@@ -317,13 +316,14 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
||||
Reality: t.realityConfig,
|
||||
}
|
||||
|
||||
t.gunTransport = gun.NewHTTP2Client(dialFn, tlsConfig)
|
||||
|
||||
t.gunConfig = &gun.Config{
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
UserAgent: option.GrpcOpts.GrpcUserAgent,
|
||||
Host: option.SNI,
|
||||
gunConfig := &gun.Config{
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
UserAgent: option.GrpcOpts.GrpcUserAgent,
|
||||
Host: option.SNI,
|
||||
PingInterval: option.GrpcOpts.PingInterval,
|
||||
}
|
||||
|
||||
t.gunTransport = gun.NewTransport(dialFn, tlsConfig, gunConfig)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
|
||||
@@ -33,8 +33,7 @@ type Vless struct {
|
||||
encryption *encryption.ClientInstance
|
||||
|
||||
// for gun mux
|
||||
gunConfig *gun.Config
|
||||
gunTransport *gun.TransportWrap
|
||||
gunTransport *gun.Transport
|
||||
|
||||
realityConfig *tlsC.RealityConfig
|
||||
echConfig *ech.Config
|
||||
@@ -234,7 +233,7 @@ func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
||||
var c net.Conn
|
||||
// gun transport
|
||||
if v.gunTransport != nil {
|
||||
c, err = gun.StreamGunWithTransport(v.gunTransport, v.gunConfig)
|
||||
c, err = v.gunTransport.Dial()
|
||||
} else {
|
||||
c, err = v.dialer.DialContext(ctx, "tcp", v.addr)
|
||||
}
|
||||
@@ -260,7 +259,7 @@ func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (
|
||||
var c net.Conn
|
||||
// gun transport
|
||||
if v.gunTransport != nil {
|
||||
c, err = gun.StreamGunWithTransport(v.gunTransport, v.gunConfig)
|
||||
c, err = v.gunTransport.Dial()
|
||||
} else {
|
||||
c, err = v.dialer.DialContext(ctx, "tcp", v.addr)
|
||||
}
|
||||
@@ -431,9 +430,10 @@ func NewVless(option VlessOption) (*Vless, error) {
|
||||
}
|
||||
|
||||
gunConfig := &gun.Config{
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
UserAgent: option.GrpcOpts.GrpcUserAgent,
|
||||
Host: option.ServerName,
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
UserAgent: option.GrpcOpts.GrpcUserAgent,
|
||||
Host: option.ServerName,
|
||||
PingInterval: option.GrpcOpts.PingInterval,
|
||||
}
|
||||
if option.ServerName == "" {
|
||||
gunConfig.Host = v.addr
|
||||
@@ -457,9 +457,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
||||
}
|
||||
}
|
||||
|
||||
v.gunConfig = gunConfig
|
||||
|
||||
v.gunTransport = gun.NewHTTP2Client(dialFn, tlsConfig)
|
||||
v.gunTransport = gun.NewTransport(dialFn, tlsConfig, gunConfig)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
|
||||
@@ -34,8 +34,7 @@ type Vmess struct {
|
||||
option *VmessOption
|
||||
|
||||
// for gun mux
|
||||
gunConfig *gun.Config
|
||||
gunTransport *gun.TransportWrap
|
||||
gunTransport *gun.Transport
|
||||
|
||||
realityConfig *tlsC.RealityConfig
|
||||
echConfig *ech.Config
|
||||
@@ -86,6 +85,7 @@ type HTTP2Options struct {
|
||||
type GrpcOptions struct {
|
||||
GrpcServiceName string `proxy:"grpc-service-name,omitempty"`
|
||||
GrpcUserAgent string `proxy:"grpc-user-agent,omitempty"`
|
||||
PingInterval int `proxy:"ping-interval,omitempty"`
|
||||
}
|
||||
|
||||
type WSOptions struct {
|
||||
@@ -295,7 +295,7 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn
|
||||
var c net.Conn
|
||||
// gun transport
|
||||
if v.gunTransport != nil {
|
||||
c, err = gun.StreamGunWithTransport(v.gunTransport, v.gunConfig)
|
||||
c, err = v.gunTransport.Dial()
|
||||
} else {
|
||||
c, err = v.dialer.DialContext(ctx, "tcp", v.addr)
|
||||
}
|
||||
@@ -318,7 +318,7 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata) (
|
||||
var c net.Conn
|
||||
// gun transport
|
||||
if v.gunTransport != nil {
|
||||
c, err = gun.StreamGunWithTransport(v.gunTransport, v.gunConfig)
|
||||
c, err = v.gunTransport.Dial()
|
||||
} else {
|
||||
c, err = v.dialer.DialContext(ctx, "tcp", v.addr)
|
||||
}
|
||||
@@ -437,9 +437,10 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
||||
}
|
||||
|
||||
gunConfig := &gun.Config{
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
UserAgent: option.GrpcOpts.GrpcUserAgent,
|
||||
Host: option.ServerName,
|
||||
ServiceName: option.GrpcOpts.GrpcServiceName,
|
||||
UserAgent: option.GrpcOpts.GrpcUserAgent,
|
||||
Host: option.ServerName,
|
||||
PingInterval: option.GrpcOpts.PingInterval,
|
||||
}
|
||||
if option.ServerName == "" {
|
||||
gunConfig.Host = v.addr
|
||||
@@ -463,9 +464,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
||||
}
|
||||
}
|
||||
|
||||
v.gunConfig = gunConfig
|
||||
|
||||
v.gunTransport = gun.NewHTTP2Client(dialFn, tlsConfig)
|
||||
v.gunTransport = gun.NewTransport(dialFn, tlsConfig, gunConfig)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
|
||||
@@ -669,6 +669,7 @@ proxies: # socks5
|
||||
grpc-opts:
|
||||
grpc-service-name: "example"
|
||||
# grpc-user-agent: "grpc-go/1.36.0"
|
||||
# ping-interval: 0 # 默认关闭,单位为秒
|
||||
# ip-version: ipv4
|
||||
|
||||
# vless
|
||||
@@ -759,6 +760,7 @@ proxies: # socks5
|
||||
grpc-opts:
|
||||
grpc-service-name: "grpc"
|
||||
# grpc-user-agent: "grpc-go/1.36.0"
|
||||
# ping-interval: 0 # 默认关闭,单位为秒
|
||||
|
||||
reality-opts:
|
||||
public-key: CrrQSjAG_YkHLwvM2M-7XkKJilgL5upBKCp0od0tLhE
|
||||
@@ -830,6 +832,7 @@ proxies: # socks5
|
||||
grpc-opts:
|
||||
grpc-service-name: "example"
|
||||
# grpc-user-agent: "grpc-go/1.36.0"
|
||||
# ping-interval: 0 # 默认关闭,单位为秒
|
||||
|
||||
- name: trojan-ws
|
||||
server: server
|
||||
|
||||
@@ -59,9 +59,10 @@ type Conn struct {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ServiceName string
|
||||
UserAgent string
|
||||
Host string
|
||||
ServiceName string
|
||||
UserAgent string
|
||||
Host string
|
||||
PingInterval int
|
||||
}
|
||||
|
||||
func (g *Conn) initReader() {
|
||||
@@ -246,7 +247,7 @@ func (g *Conn) SetDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewHTTP2Client(dialFn DialFn, tlsConfig *vmess.TLSConfig) *TransportWrap {
|
||||
func NewTransport(dialFn DialFn, tlsConfig *vmess.TLSConfig, gunCfg *Config) *Transport {
|
||||
dialFunc := func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, C.DefaultTLSTimeout)
|
||||
defer cancel()
|
||||
@@ -288,14 +289,16 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *vmess.TLSConfig) *TransportWrap {
|
||||
DialTLSContext: dialFunc,
|
||||
AllowHTTP: false,
|
||||
DisableCompression: true,
|
||||
ReadIdleTimeout: time.Duration(gunCfg.PingInterval) * time.Second, // If zero, no health check is performed
|
||||
PingTimeout: 0,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
wrap := &TransportWrap{
|
||||
Http2Transport: transport,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
wrap := &Transport{
|
||||
transport: transport,
|
||||
cfg: gunCfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
return wrap
|
||||
}
|
||||
@@ -307,18 +310,18 @@ func ServiceNameToPath(serviceName string) string {
|
||||
return "/" + serviceName + "/Tun"
|
||||
}
|
||||
|
||||
func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, error) {
|
||||
func (t *Transport) Dial() (net.Conn, error) {
|
||||
serviceName := "GunService"
|
||||
if cfg.ServiceName != "" {
|
||||
serviceName = cfg.ServiceName
|
||||
if t.cfg.ServiceName != "" {
|
||||
serviceName = t.cfg.ServiceName
|
||||
}
|
||||
path := ServiceNameToPath(serviceName)
|
||||
|
||||
reader, writer := io.Pipe()
|
||||
|
||||
header := defaultHeader.Clone()
|
||||
if cfg.UserAgent != "" {
|
||||
header.Set("User-Agent", cfg.UserAgent)
|
||||
if t.cfg.UserAgent != "" {
|
||||
header.Set("User-Agent", t.cfg.UserAgent)
|
||||
}
|
||||
|
||||
request := &http.Request{
|
||||
@@ -326,17 +329,17 @@ func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, er
|
||||
Body: reader,
|
||||
URL: &url.URL{
|
||||
Scheme: "https",
|
||||
Host: cfg.Host,
|
||||
Host: t.cfg.Host,
|
||||
Path: path,
|
||||
// for unescape path
|
||||
Opaque: "//" + cfg.Host + path,
|
||||
Opaque: "//" + t.cfg.Host + path,
|
||||
},
|
||||
Proto: "HTTP/2",
|
||||
ProtoMajor: 2,
|
||||
ProtoMinor: 0,
|
||||
Header: header,
|
||||
}
|
||||
request = request.WithContext(transport.ctx)
|
||||
request = request.WithContext(t.ctx)
|
||||
|
||||
conn := &Conn{
|
||||
initFn: func() (io.ReadCloser, NetAddr, error) {
|
||||
@@ -348,7 +351,7 @@ func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, er
|
||||
},
|
||||
}
|
||||
request = request.WithContext(httptrace.WithClientTrace(request.Context(), trace))
|
||||
response, err := transport.RoundTrip(request)
|
||||
response, err := t.transport.RoundTrip(request)
|
||||
if err != nil {
|
||||
return nil, nAddr, err
|
||||
}
|
||||
@@ -361,13 +364,13 @@ func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, er
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func StreamGunWithConn(conn net.Conn, tlsConfig *vmess.TLSConfig, cfg *Config) (net.Conn, error) {
|
||||
func StreamGunWithConn(conn net.Conn, tlsConfig *vmess.TLSConfig, gunCfg *Config) (net.Conn, error) {
|
||||
dialFn := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
transport := NewHTTP2Client(dialFn, tlsConfig)
|
||||
c, err := StreamGunWithTransport(transport, cfg)
|
||||
transport := NewTransport(dialFn, tlsConfig, gunCfg)
|
||||
c, err := transport.Dial()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,17 +10,18 @@ import (
|
||||
"github.com/metacubex/http"
|
||||
)
|
||||
|
||||
type TransportWrap struct {
|
||||
*http.Http2Transport
|
||||
type Transport struct {
|
||||
transport *http.Http2Transport
|
||||
cfg *Config
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func (tw *TransportWrap) Close() error {
|
||||
tw.closeOnce.Do(func() {
|
||||
tw.cancel()
|
||||
CloseTransport(tw.Http2Transport)
|
||||
func (t *Transport) Close() error {
|
||||
t.closeOnce.Do(func() {
|
||||
t.cancel()
|
||||
CloseHttp2Transport(t.transport)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func closeClientConn(cc *http.Http2ClientConn) { // like forceCloseConn() in htt
|
||||
_ = cc.Close()
|
||||
}
|
||||
|
||||
func CloseTransport(tr *http.Http2Transport) {
|
||||
func CloseHttp2Transport(tr *http.Http2Transport) {
|
||||
connPool := transportConnPool(tr)
|
||||
p := (*clientConnPool)((*efaceWords)(unsafe.Pointer(&connPool)).data)
|
||||
p.mu.Lock()
|
||||
|
||||
@@ -11,7 +11,7 @@ func forceCloseAllConnections(roundTripper RoundTripper) {
|
||||
roundTripper.CloseIdleConnections()
|
||||
switch tr := roundTripper.(type) {
|
||||
case *http.Http2Transport:
|
||||
gun.CloseTransport(tr)
|
||||
gun.CloseHttp2Transport(tr)
|
||||
case *http3.Transport:
|
||||
_ = tr.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user