mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-20 00:50:06 +08:00
fix: StreamGunWithConn not synchronously close the incoming net.Conn
This commit is contained in:
parent
622d99d000
commit
7de24e26b4
@ -281,7 +281,7 @@ func newPacketConn(pc net.PacketConn, a C.ProxyAdapter) C.PacketConn {
|
|||||||
epc := N.NewEnhancePacketConn(pc)
|
epc := N.NewEnhancePacketConn(pc)
|
||||||
if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn
|
if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn
|
||||||
epc = N.NewDeadlineEnhancePacketConn(epc) // most conn from outbound can't handle readDeadline correctly
|
epc = N.NewDeadlineEnhancePacketConn(epc) // most conn from outbound can't handle readDeadline correctly
|
||||||
epc = N.NewRefPacketConn(epc, a) // add ref for autoCloseProxyAdapter
|
epc = N.NewRefPacketConn(epc, a) // add ref for autoCloseProxyAdapter
|
||||||
}
|
}
|
||||||
return &packetConn{epc, []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), parseRemoteDestination(a.Addr())}
|
return &packetConn{epc, []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), parseRemoteDestination(a.Addr())}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -313,7 +313,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if option.Network == "grpc" {
|
if option.Network == "grpc" {
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
var err error
|
var err error
|
||||||
var cDialer C.Dialer = dialer.NewDialer(t.Base.DialOptions()...)
|
var cDialer C.Dialer = dialer.NewDialer(t.Base.DialOptions()...)
|
||||||
if len(t.option.DialerProxy) > 0 {
|
if len(t.option.DialerProxy) > 0 {
|
||||||
@ -322,7 +322,7 @@ func NewTrojan(option TrojanOption) (*Trojan, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c, err := cDialer.DialContext(context.Background(), "tcp", t.addr)
|
c, err := cDialer.DialContext(ctx, "tcp", t.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", t.addr, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -571,7 +571,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||||||
option.HTTP2Opts.Host = append(option.HTTP2Opts.Host, "www.example.com")
|
option.HTTP2Opts.Host = append(option.HTTP2Opts.Host, "www.example.com")
|
||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
var err error
|
var err error
|
||||||
var cDialer C.Dialer = dialer.NewDialer(v.Base.DialOptions()...)
|
var cDialer C.Dialer = dialer.NewDialer(v.Base.DialOptions()...)
|
||||||
if len(v.option.DialerProxy) > 0 {
|
if len(v.option.DialerProxy) > 0 {
|
||||||
@ -580,7 +580,7 @@ func NewVless(option VlessOption) (*Vless, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c, err := cDialer.DialContext(context.Background(), "tcp", v.addr)
|
c, err := cDialer.DialContext(ctx, "tcp", v.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -478,7 +478,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
|||||||
option.HTTP2Opts.Host = append(option.HTTP2Opts.Host, "www.example.com")
|
option.HTTP2Opts.Host = append(option.HTTP2Opts.Host, "www.example.com")
|
||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
var err error
|
var err error
|
||||||
var cDialer C.Dialer = dialer.NewDialer(v.Base.DialOptions()...)
|
var cDialer C.Dialer = dialer.NewDialer(v.Base.DialOptions()...)
|
||||||
if len(v.option.DialerProxy) > 0 {
|
if len(v.option.DialerProxy) > 0 {
|
||||||
@ -487,7 +487,7 @@ func NewVmess(option VmessOption) (*Vmess, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c, err := cDialer.DialContext(context.Background(), "tcp", v.addr)
|
c, err := cDialer.DialContext(ctx, "tcp", v.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,12 +36,12 @@ var defaultHeader = http.Header{
|
|||||||
"user-agent": []string{"grpc-go/1.36.0"},
|
"user-agent": []string{"grpc-go/1.36.0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
type DialFn = func(network, addr string) (net.Conn, error)
|
type DialFn = func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
initFn func() (io.ReadCloser, netAddr, error)
|
initFn func() (io.ReadCloser, netAddr, error)
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
flusher http.Flusher
|
closer io.Closer
|
||||||
netAddr
|
netAddr
|
||||||
|
|
||||||
reader io.ReadCloser
|
reader io.ReadCloser
|
||||||
@ -149,8 +149,8 @@ func (g *Conn) Write(b []byte) (n int, err error) {
|
|||||||
err = g.err
|
err = g.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.flusher != nil {
|
if flusher, ok := g.writer.(http.Flusher); ok {
|
||||||
g.flusher.Flush()
|
flusher.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(b), err
|
return len(b), err
|
||||||
@ -172,8 +172,8 @@ func (g *Conn) WriteBuffer(buffer *buf.Buffer) error {
|
|||||||
err = g.err
|
err = g.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.flusher != nil {
|
if flusher, ok := g.writer.(http.Flusher); ok {
|
||||||
g.flusher.Flush()
|
flusher.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@ -185,14 +185,27 @@ func (g *Conn) FrontHeadroom() int {
|
|||||||
|
|
||||||
func (g *Conn) Close() error {
|
func (g *Conn) Close() error {
|
||||||
g.close.Store(true)
|
g.close.Store(true)
|
||||||
|
var errorArr []error
|
||||||
|
|
||||||
if reader := g.reader; reader != nil {
|
if reader := g.reader; reader != nil {
|
||||||
reader.Close()
|
if err := reader.Close(); err != nil {
|
||||||
|
errorArr = append(errorArr, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if closer, ok := g.writer.(io.Closer); ok {
|
if closer, ok := g.writer.(io.Closer); ok {
|
||||||
return closer.Close()
|
if err := closer.Close(); err != nil {
|
||||||
|
errorArr = append(errorArr, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
if closer := g.closer; closer != nil {
|
||||||
|
if err := closer.Close(); err != nil {
|
||||||
|
errorArr = append(errorArr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Join(errorArr...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Conn) SetReadDeadline(t time.Time) error { return g.SetDeadline(t) }
|
func (g *Conn) SetReadDeadline(t time.Time) error { return g.SetDeadline(t) }
|
||||||
@ -212,7 +225,7 @@ func (g *Conn) SetDeadline(t time.Time) error {
|
|||||||
|
|
||||||
func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, Fingerprint string, realityConfig *tlsC.RealityConfig) *TransportWrap {
|
func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, Fingerprint string, realityConfig *tlsC.RealityConfig) *TransportWrap {
|
||||||
dialFunc := func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
|
dialFunc := func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||||
pconn, err := dialFn(network, addr)
|
pconn, err := dialFn(ctx, network, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -327,10 +340,17 @@ func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func StreamGunWithConn(conn net.Conn, tlsConfig *tls.Config, cfg *Config, realityConfig *tlsC.RealityConfig) (net.Conn, error) {
|
func StreamGunWithConn(conn net.Conn, tlsConfig *tls.Config, cfg *Config, realityConfig *tlsC.RealityConfig) (net.Conn, error) {
|
||||||
dialFn := func(network, addr string) (net.Conn, error) {
|
dialFn := func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
transport := NewHTTP2Client(dialFn, tlsConfig, cfg.ClientFingerprint, realityConfig)
|
transport := NewHTTP2Client(dialFn, tlsConfig, cfg.ClientFingerprint, realityConfig)
|
||||||
return StreamGunWithTransport(transport, cfg)
|
c, err := StreamGunWithTransport(transport, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c, ok := c.(*Conn); ok { // The incoming net.Conn should be closed synchronously with the generated gun.Conn
|
||||||
|
c.closer = conn
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,8 +56,7 @@ func NewServerHandler(options ServerOption) http.Handler {
|
|||||||
}
|
}
|
||||||
return request.Body, nAddr, nil
|
return request.Body, nAddr, nil
|
||||||
},
|
},
|
||||||
writer: writer,
|
writer: writer,
|
||||||
flusher: writer.(http.Flusher),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper := &h2ConnWrapper{
|
wrapper := &h2ConnWrapper{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user