mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-09 02:41:22 +08:00
fix: hysteria1 outbound should be closed when proxy removed
This commit is contained in:
parent
81756fc927
commit
9cf3eb39f5
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -207,6 +207,8 @@ jobs:
|
||||
if: ${{ matrix.jobs.test == 'test' }}
|
||||
run: |
|
||||
go test ./...
|
||||
echo "---test with_gvisor---"
|
||||
go test ./... -tags "with_gvisor" -count=1
|
||||
|
||||
- name: Update CA
|
||||
run: |
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@ -14,6 +15,7 @@ import (
|
||||
"github.com/metacubex/quic-go/congestion"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
|
||||
CN "github.com/metacubex/mihomo/common/net"
|
||||
"github.com/metacubex/mihomo/component/ca"
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/component/proxydialer"
|
||||
@ -43,6 +45,8 @@ type Hysteria struct {
|
||||
|
||||
option *HysteriaOption
|
||||
client *core.Client
|
||||
|
||||
closeCh chan struct{} // for test
|
||||
}
|
||||
|
||||
func (h *Hysteria) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||
@ -51,7 +55,7 @@ func (h *Hysteria) DialContext(ctx context.Context, metadata *C.Metadata, opts .
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewConn(tcpConn, h), nil
|
||||
return NewConn(CN.NewRefConn(tcpConn, h), h), nil
|
||||
}
|
||||
|
||||
func (h *Hysteria) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||
@ -59,7 +63,7 @@ func (h *Hysteria) ListenPacketContext(ctx context.Context, metadata *C.Metadata
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newPacketConn(&hyPacketConn{udpConn}, h), nil
|
||||
return newPacketConn(CN.NewRefPacketConn(&hyPacketConn{udpConn}, h), h), nil
|
||||
}
|
||||
|
||||
func (h *Hysteria) genHdc(ctx context.Context, opts ...dialer.Option) utils.PacketDialer {
|
||||
@ -218,7 +222,7 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("hysteria %s create error: %w", addr, err)
|
||||
}
|
||||
return &Hysteria{
|
||||
outbound := &Hysteria{
|
||||
Base: &Base{
|
||||
name: option.Name,
|
||||
addr: addr,
|
||||
@ -231,7 +235,19 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
|
||||
},
|
||||
option: &option,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
runtime.SetFinalizer(outbound, closeHysteria)
|
||||
|
||||
return outbound, nil
|
||||
}
|
||||
|
||||
func closeHysteria(h *Hysteria) {
|
||||
if h.client != nil {
|
||||
_ = h.client.Close()
|
||||
}
|
||||
if h.closeCh != nil {
|
||||
close(h.closeCh)
|
||||
}
|
||||
}
|
||||
|
||||
type hyPacketConn struct {
|
||||
|
@ -38,6 +38,8 @@ type Hysteria2 struct {
|
||||
option *Hysteria2Option
|
||||
client *hysteria2.Client
|
||||
dialer proxydialer.SingDialer
|
||||
|
||||
closeCh chan struct{} // for test
|
||||
}
|
||||
|
||||
type Hysteria2Option struct {
|
||||
@ -89,6 +91,9 @@ func closeHysteria2(h *Hysteria2) {
|
||||
if h.client != nil {
|
||||
_ = h.client.CloseWithError(errors.New("proxy removed"))
|
||||
}
|
||||
if h.closeCh != nil {
|
||||
close(h.closeCh)
|
||||
}
|
||||
}
|
||||
|
||||
func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
|
||||
|
38
adapter/outbound/hysteria2_test.go
Normal file
38
adapter/outbound/hysteria2_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package outbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHysteria2GC(t *testing.T) {
|
||||
option := Hysteria2Option{}
|
||||
option.Server = "127.0.0.1"
|
||||
option.Ports = "200,204,401-429,501-503"
|
||||
option.HopInterval = 30
|
||||
option.Password = "password"
|
||||
option.Obfs = "salamander"
|
||||
option.ObfsPassword = "password"
|
||||
option.SNI = "example.com"
|
||||
option.ALPN = []string{"h3"}
|
||||
hy, err := NewHysteria2(option)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
closeCh := make(chan struct{})
|
||||
hy.closeCh = closeCh
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
|
||||
hy = nil
|
||||
runtime.GC()
|
||||
select {
|
||||
case <-closeCh:
|
||||
return
|
||||
case <-ctx.Done():
|
||||
t.Error("timeout not GC")
|
||||
}
|
||||
}
|
39
adapter/outbound/hysteria_test.go
Normal file
39
adapter/outbound/hysteria_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
package outbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHysteriaGC(t *testing.T) {
|
||||
option := HysteriaOption{}
|
||||
option.Server = "127.0.0.1"
|
||||
option.Ports = "200,204,401-429,501-503"
|
||||
option.Protocol = "udp"
|
||||
option.Up = "1Mbps"
|
||||
option.Down = "1Mbps"
|
||||
option.HopInterval = 30
|
||||
option.Obfs = "salamander"
|
||||
option.SNI = "example.com"
|
||||
option.ALPN = []string{"h3"}
|
||||
hy, err := NewHysteria(option)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
closeCh := make(chan struct{})
|
||||
hy.closeCh = closeCh
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
|
||||
hy = nil
|
||||
runtime.GC()
|
||||
select {
|
||||
case <-closeCh:
|
||||
return
|
||||
case <-ctx.Done():
|
||||
t.Error("timeout not GC")
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ func TestWireGuardGC(t *testing.T) {
|
||||
err = wg.init(ctx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
// must do a small sleep before test GC
|
||||
// because it maybe deadlocks if w.device.Close call too fast after w.device.Start
|
||||
|
@ -289,7 +289,10 @@ func (c *Client) DialUDP(dialer utils.PacketDialer) (UDPConn, error) {
|
||||
func (c *Client) Close() error {
|
||||
c.reconnectMutex.Lock()
|
||||
defer c.reconnectMutex.Unlock()
|
||||
err := c.quicSession.CloseWithError(closeErrorCodeGeneric, "")
|
||||
var err error
|
||||
if c.quicSession != nil {
|
||||
err = c.quicSession.CloseWithError(closeErrorCodeGeneric, "")
|
||||
}
|
||||
c.closed = true
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user