Skip to content

Commit

Permalink
Merge branch 'apernet:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
cedar2025 authored Mar 6, 2024
2 parents 19e695a + 84d72ef commit 8283289
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 42 deletions.
2 changes: 1 addition & 1 deletion app/cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (c *clientConfig) fillConnFactory(hyConfig *client.Config) error {
if hyConfig.ServerAddr.Network() == "udphop" {
hopAddr := hyConfig.ServerAddr.(*udphop.UDPHopAddr)
newFunc = func(addr net.Addr) (net.PacketConn, error) {
return udphop.NewUDPHopPacketConn(hopAddr, c.Transport.UDP.HopInterval)
return udphop.NewUDPHopPacketConn(hopAddr, c.Transport.UDP.HopInterval, nil)
}
} else {
newFunc = func(addr net.Addr) (net.PacketConn, error) {
Expand Down
2 changes: 1 addition & 1 deletion app/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
)

require (
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f // indirect
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d // indirect
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions app/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjgzx9vOcyCqsOY3c9kofDZ1n+qaw35ZY=
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM=
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f h1:4jBGc3SlgQT8YFqHhfnK7EVFVY292CxagfNqfPiQZhY=
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I=
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI=
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
Expand Down
12 changes: 6 additions & 6 deletions app/internal/utils/bpsconv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ func TestStringToBps(t *testing.T) {
wantErr bool
}{
{"bps", args{"800 bps"}, 100, false},
{"kbps", args{"800 kbps"}, 102400, false},
{"mbps", args{"800 mbps"}, 104857600, false},
{"gbps", args{"800 gbps"}, 107374182400, false},
{"tbps", args{"800 tbps"}, 109951162777600, false},
{"mbps simp", args{"100m"}, 13107200, false},
{"gbps simp upper", args{"2G"}, 268435456, false},
{"kbps", args{"800 kbps"}, 100_000, false},
{"mbps", args{"800 mbps"}, 100_000_000, false},
{"gbps", args{"800 gbps"}, 100_000_000_000, false},
{"tbps", args{"800 tbps"}, 100_000_000_000_000, false},
{"mbps simp", args{"100m"}, 12_500_000, false},
{"gbps simp upper", args{"2G"}, 250_000_000, false},
{"invalid 1", args{"damn"}, 0, true},
{"invalid 2", args{"6444"}, 0, true},
{"invalid 3", args{"5.4 mbps"}, 0, true},
Expand Down
74 changes: 63 additions & 11 deletions app/internal/utils/geoloader.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils

import (
"fmt"
"io"
"net/http"
"os"
Expand All @@ -15,6 +16,7 @@ const (
geoipURL = "https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geoip.dat"
geositeFilename = "geosite.dat"
geositeURL = "https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat"
geoDlTmpPattern = ".hysteria-geoloader.dlpart.*"

geoDefaultUpdateInterval = 7 * 24 * time.Hour // 7 days
)
Expand All @@ -41,6 +43,10 @@ func (l *GeoLoader) shouldDownload(filename string) bool {
if os.IsNotExist(err) {
return true
}
if info.Size() == 0 {
// empty files are loadable by v2geo, but we consider it broken
return true
}
dt := time.Now().Sub(info.ModTime())
if l.UpdateInterval == 0 {
return dt > geoDefaultUpdateInterval
Expand All @@ -49,7 +55,7 @@ func (l *GeoLoader) shouldDownload(filename string) bool {
}
}

func (l *GeoLoader) download(filename, url string) error {
func (l *GeoLoader) downloadAndCheck(filename, url string, checkFunc func(filename string) error) error {
l.DownloadFunc(filename, url)

resp, err := http.Get(url)
Expand All @@ -59,16 +65,34 @@ func (l *GeoLoader) download(filename, url string) error {
}
defer resp.Body.Close()

f, err := os.Create(filename)
f, err := os.CreateTemp(".", geoDlTmpPattern)
if err != nil {
l.DownloadErrFunc(err)
return err
}
defer f.Close()
defer os.Remove(f.Name())

_, err = io.Copy(f, resp.Body)
l.DownloadErrFunc(err)
return err
if err != nil {
f.Close()
l.DownloadErrFunc(err)
return err
}
f.Close()

err = checkFunc(f.Name())
if err != nil {
l.DownloadErrFunc(fmt.Errorf("integrity check failed: %w", err))
return err
}

err = os.Rename(f.Name(), filename)
if err != nil {
l.DownloadErrFunc(fmt.Errorf("rename failed: %w", err))
return err
}

return nil
}

func (l *GeoLoader) LoadGeoIP() (map[string]*v2geo.GeoIP, error) {
Expand All @@ -81,10 +105,24 @@ func (l *GeoLoader) LoadGeoIP() (map[string]*v2geo.GeoIP, error) {
autoDL = true
filename = geoipFilename
}
if autoDL && l.shouldDownload(filename) {
err := l.download(filename, geoipURL)
if autoDL {
if !l.shouldDownload(filename) {
m, err := v2geo.LoadGeoIP(filename)
if err == nil {
l.geoipMap = m
return m, nil
}
// file is broken, download it again
}
err := l.downloadAndCheck(filename, geoipURL, func(filename string) error {
_, err := v2geo.LoadGeoIP(filename)
return err
})
if err != nil {
return nil, err
// as long as the previous download exists, fallback to it
if _, serr := os.Stat(filename); os.IsNotExist(serr) {
return nil, err
}
}
}
m, err := v2geo.LoadGeoIP(filename)
Expand All @@ -105,10 +143,24 @@ func (l *GeoLoader) LoadGeoSite() (map[string]*v2geo.GeoSite, error) {
autoDL = true
filename = geositeFilename
}
if autoDL && l.shouldDownload(filename) {
err := l.download(filename, geositeURL)
if autoDL {
if !l.shouldDownload(filename) {
m, err := v2geo.LoadGeoSite(filename)
if err == nil {
l.geositeMap = m
return m, nil
}
// file is broken, download it again
}
err := l.downloadAndCheck(filename, geositeURL, func(filename string) error {
_, err := v2geo.LoadGeoSite(filename)
return err
})
if err != nil {
return nil, err
// as long as the previous download exists, fallback to it
if _, serr := os.Stat(filename); os.IsNotExist(serr) {
return nil, err
}
}
}
m, err := v2geo.LoadGeoSite(filename)
Expand Down
2 changes: 1 addition & 1 deletion core/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/apernet/hysteria/core
go 1.21

require (
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d
github.com/stretchr/testify v1.8.4
go.uber.org/goleak v1.2.1
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
Expand Down
4 changes: 2 additions & 2 deletions core/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f h1:4jBGc3SlgQT8YFqHhfnK7EVFVY292CxagfNqfPiQZhY=
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I=
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI=
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down
2 changes: 1 addition & 1 deletion extras/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
)

require (
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f // indirect
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
Expand Down
4 changes: 2 additions & 2 deletions extras/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f h1:4jBGc3SlgQT8YFqHhfnK7EVFVY292CxagfNqfPiQZhY=
github.com/apernet/quic-go v0.41.1-0.20240122005439-5bf4609c416f/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I=
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI=
github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
Expand Down
26 changes: 25 additions & 1 deletion extras/outbounds/ob_socks5.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,31 @@ type errSOCKS5RequestFailed struct {
}

func (e errSOCKS5RequestFailed) Error() string {
return fmt.Sprintf("SOCKS5 request failed: %d", e.Rep)
var msg string
// RFC 1928
switch e.Rep {
case 0x00:
msg = "succeeded"
case 0x01:
msg = "general SOCKS server failure"
case 0x02:
msg = "connection not allowed by ruleset"
case 0x03:
msg = "Network unreachable"
case 0x04:
msg = "Host unreachable"
case 0x05:
msg = "Connection refused"
case 0x06:
msg = "TTL expired"
case 0x07:
msg = "Command not supported"
case 0x08:
msg = "Address type not supported"
default:
msg = "undefined"
}
return fmt.Sprintf("SOCKS5 request failed: %s (%d)", msg, e.Rep)
}

// socks5Outbound is a PluggableOutbound that connects to the target using
Expand Down
37 changes: 23 additions & 14 deletions extras/transport/udphop/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ const (
)

type udpHopPacketConn struct {
Addr net.Addr
Addrs []net.Addr
HopInterval time.Duration
Addr net.Addr
Addrs []net.Addr
HopInterval time.Duration
ListenUDPFunc ListenUDPFunc

connMutex sync.RWMutex
prevConn net.PacketConn
Expand All @@ -43,29 +44,37 @@ type udpPacket struct {
Err error
}

func NewUDPHopPacketConn(addr *UDPHopAddr, hopInterval time.Duration) (net.PacketConn, error) {
type ListenUDPFunc func() (net.PacketConn, error)

func NewUDPHopPacketConn(addr *UDPHopAddr, hopInterval time.Duration, listenUDPFunc ListenUDPFunc) (net.PacketConn, error) {
if hopInterval == 0 {
hopInterval = defaultHopInterval
} else if hopInterval < 5*time.Second {
return nil, errors.New("hop interval must be at least 5 seconds")
}
if listenUDPFunc == nil {
listenUDPFunc = func() (net.PacketConn, error) {
return net.ListenUDP("udp", nil)
}
}
addrs, err := addr.addrs()
if err != nil {
return nil, err
}
curConn, err := net.ListenUDP("udp", nil)
curConn, err := listenUDPFunc()
if err != nil {
return nil, err
}
hConn := &udpHopPacketConn{
Addr: addr,
Addrs: addrs,
HopInterval: hopInterval,
prevConn: nil,
currentConn: curConn,
addrIndex: rand.Intn(len(addrs)),
recvQueue: make(chan *udpPacket, packetQueueSize),
closeChan: make(chan struct{}),
Addr: addr,
Addrs: addrs,
HopInterval: hopInterval,
ListenUDPFunc: listenUDPFunc,
prevConn: nil,
currentConn: curConn,
addrIndex: rand.Intn(len(addrs)),
recvQueue: make(chan *udpPacket, packetQueueSize),
closeChan: make(chan struct{}),
bufPool: sync.Pool{
New: func() interface{} {
return make([]byte, udpBufferSize)
Expand Down Expand Up @@ -121,7 +130,7 @@ func (u *udpHopPacketConn) hop() {
if u.closed {
return
}
newConn, err := net.ListenUDP("udp", nil)
newConn, err := u.ListenUDPFunc()
if err != nil {
// Could be temporary, just skip this hop
return
Expand Down

0 comments on commit 8283289

Please sign in to comment.