mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-14 05:11:17 +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' }}
|
if: ${{ matrix.jobs.test == 'test' }}
|
||||||
run: |
|
run: |
|
||||||
go test ./...
|
go test ./...
|
||||||
|
echo "---test with_gvisor---"
|
||||||
|
go test ./... -tags "with_gvisor" -count=1
|
||||||
|
|
||||||
- name: Update CA
|
- name: Update CA
|
||||||
run: |
|
run: |
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"github.com/metacubex/quic-go/congestion"
|
"github.com/metacubex/quic-go/congestion"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
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/ca"
|
||||||
"github.com/metacubex/mihomo/component/dialer"
|
"github.com/metacubex/mihomo/component/dialer"
|
||||||
"github.com/metacubex/mihomo/component/proxydialer"
|
"github.com/metacubex/mihomo/component/proxydialer"
|
||||||
@ -43,6 +45,8 @@ type Hysteria struct {
|
|||||||
|
|
||||||
option *HysteriaOption
|
option *HysteriaOption
|
||||||
client *core.Client
|
client *core.Client
|
||||||
|
|
||||||
|
closeCh chan struct{} // for test
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hysteria) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
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 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("hysteria %s create error: %w", addr, err)
|
return nil, fmt.Errorf("hysteria %s create error: %w", addr, err)
|
||||||
}
|
}
|
||||||
return &Hysteria{
|
outbound := &Hysteria{
|
||||||
Base: &Base{
|
Base: &Base{
|
||||||
name: option.Name,
|
name: option.Name,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
@ -231,7 +235,19 @@ func NewHysteria(option HysteriaOption) (*Hysteria, error) {
|
|||||||
},
|
},
|
||||||
option: &option,
|
option: &option,
|
||||||
client: client,
|
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 {
|
type hyPacketConn struct {
|
||||||
|
@ -38,6 +38,8 @@ type Hysteria2 struct {
|
|||||||
option *Hysteria2Option
|
option *Hysteria2Option
|
||||||
client *hysteria2.Client
|
client *hysteria2.Client
|
||||||
dialer proxydialer.SingDialer
|
dialer proxydialer.SingDialer
|
||||||
|
|
||||||
|
closeCh chan struct{} // for test
|
||||||
}
|
}
|
||||||
|
|
||||||
type Hysteria2Option struct {
|
type Hysteria2Option struct {
|
||||||
@ -89,6 +91,9 @@ func closeHysteria2(h *Hysteria2) {
|
|||||||
if h.client != nil {
|
if h.client != nil {
|
||||||
_ = h.client.CloseWithError(errors.New("proxy removed"))
|
_ = h.client.CloseWithError(errors.New("proxy removed"))
|
||||||
}
|
}
|
||||||
|
if h.closeCh != nil {
|
||||||
|
close(h.closeCh)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) {
|
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)
|
err = wg.init(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// must do a small sleep before test GC
|
// must do a small sleep before test GC
|
||||||
// because it maybe deadlocks if w.device.Close call too fast after w.device.Start
|
// 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 {
|
func (c *Client) Close() error {
|
||||||
c.reconnectMutex.Lock()
|
c.reconnectMutex.Lock()
|
||||||
defer c.reconnectMutex.Unlock()
|
defer c.reconnectMutex.Unlock()
|
||||||
err := c.quicSession.CloseWithError(closeErrorCodeGeneric, "")
|
var err error
|
||||||
|
if c.quicSession != nil {
|
||||||
|
err = c.quicSession.CloseWithError(closeErrorCodeGeneric, "")
|
||||||
|
}
|
||||||
c.closed = true
|
c.closed = true
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user