Skip to content

Commit

Permalink
chore: change subscription-userinfo retrieval
Browse files Browse the repository at this point in the history
  • Loading branch information
xishang0128 committed Oct 19, 2024
1 parent ca3f1eb commit 8fb0d48
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 49 deletions.
64 changes: 27 additions & 37 deletions adapter/provider/provider.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package provider

import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
"runtime"
"strings"
Expand All @@ -14,7 +12,7 @@ import (
"github.com/metacubex/mihomo/adapter"
"github.com/metacubex/mihomo/common/convert"
"github.com/metacubex/mihomo/common/utils"
mihomoHttp "github.com/metacubex/mihomo/component/http"
"github.com/metacubex/mihomo/component/profile/cachefile"
"github.com/metacubex/mihomo/component/resource"
C "github.com/metacubex/mihomo/constant"
types "github.com/metacubex/mihomo/constant/provider"
Expand Down Expand Up @@ -80,7 +78,9 @@ func (pp *proxySetProvider) Initial() error {
if err != nil {
return err
}
pp.getSubscriptionInfo()
if pp.VehicleType() == types.HTTP {
pp.SetSubscriptionInfo(cachefile.Cache().GetSubscriptionInfo(pp.Name()))
}
pp.closeAllConnections()
return nil
}
Expand Down Expand Up @@ -117,35 +117,14 @@ func (pp *proxySetProvider) setProxies(proxies []C.Proxy) {
}
}

func (pp *proxySetProvider) getSubscriptionInfo() {
if pp.VehicleType() != types.HTTP {
return
func (pp *proxySetProvider) SetSubscriptionInfo(userInfo string) {
pp.subscriptionInfo = NewSubscriptionInfo(userInfo)
}

func (pp *proxySetProvider) SetProvider(provider types.ProxyProvider) {
if httpVehicle, ok := pp.Vehicle().(*resource.HTTPVehicle); ok {
httpVehicle.SetProvider(provider)
}
go func() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
defer cancel()
resp, err := mihomoHttp.HttpRequestWithProxy(ctx, pp.Vehicle().Url(),
http.MethodGet, nil, nil, pp.Vehicle().Proxy())
if err != nil {
return
}
defer resp.Body.Close()

userInfoStr := strings.TrimSpace(resp.Header.Get("subscription-userinfo"))
if userInfoStr == "" {
resp2, err := mihomoHttp.HttpRequestWithProxy(ctx, pp.Vehicle().Url(),
http.MethodGet, http.Header{"User-Agent": {"Quantumultx"}}, nil, pp.Vehicle().Proxy())
if err != nil {
return
}
defer resp2.Body.Close()
userInfoStr = strings.TrimSpace(resp2.Header.Get("subscription-userinfo"))
if userInfoStr == "" {
return
}
}
pp.subscriptionInfo = NewSubscriptionInfo(userInfoStr)
}()
}

func (pp *proxySetProvider) closeAllConnections() {
Expand Down Expand Up @@ -196,6 +175,9 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, exc
fetcher := resource.NewFetcher[[]C.Proxy](name, interval, vehicle, proxiesParseAndFilter(filter, excludeFilter, excludeTypeArray, filterRegs, excludeFilterReg, dialerProxy, override), proxiesOnUpdate(pd))
pd.Fetcher = fetcher
wrapper := &ProxySetProvider{pd}
if httpVehicle, ok := vehicle.(*resource.HTTPVehicle); ok {
httpVehicle.SetProvider(wrapper)
}
runtime.SetFinalizer(wrapper, (*ProxySetProvider).Close)
return wrapper, nil
}
Expand All @@ -205,16 +187,21 @@ func (pp *ProxySetProvider) Close() error {
return pp.proxySetProvider.Close()
}

func (pp *ProxySetProvider) SetProvider(provider types.ProxyProvider) {
pp.proxySetProvider.SetProvider(provider)
}

// CompatibleProvider for auto gc
type CompatibleProvider struct {
*compatibleProvider
}

type compatibleProvider struct {
name string
healthCheck *HealthCheck
proxies []C.Proxy
version uint32
name string
healthCheck *HealthCheck
subscriptionInfo *SubscriptionInfo
proxies []C.Proxy
version uint32
}

func (cp *compatibleProvider) MarshalJSON() ([]byte, error) {
Expand Down Expand Up @@ -284,6 +271,10 @@ func (cp *compatibleProvider) Close() error {
return nil
}

func (cp *compatibleProvider) SetSubscriptionInfo(userInfo string) {
cp.subscriptionInfo = NewSubscriptionInfo(userInfo)
}

func NewCompatibleProvider(name string, proxies []C.Proxy, hc *HealthCheck) (*CompatibleProvider, error) {
if len(proxies) == 0 {
return nil, errors.New("provider need one proxy at least")
Expand Down Expand Up @@ -313,7 +304,6 @@ func proxiesOnUpdate(pd *proxySetProvider) func([]C.Proxy) {
return func(elm []C.Proxy) {
pd.setProxies(elm)
pd.version += 1
pd.getSubscriptionInfo()
}
}

Expand Down
3 changes: 1 addition & 2 deletions adapter/provider/subscription_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ type SubscriptionInfo struct {
}

func NewSubscriptionInfo(userinfo string) (si *SubscriptionInfo) {
userinfo = strings.ToLower(userinfo)
userinfo = strings.ReplaceAll(userinfo, " ", "")
userinfo = strings.ReplaceAll(strings.ToLower(userinfo), " ", "")
si = new(SubscriptionInfo)

for _, field := range strings.Split(userinfo, ";") {
Expand Down
7 changes: 4 additions & 3 deletions component/profile/cachefile/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ var (
fileMode os.FileMode = 0o666
defaultCache *CacheFile

bucketSelected = []byte("selected")
bucketFakeip = []byte("fakeip")
bucketETag = []byte("etag")
bucketSelected = []byte("selected")
bucketFakeip = []byte("fakeip")
bucketETag = []byte("etag")
bucketSubscriptionInfo = []byte("subscriptioninfo")
)

// CacheFile store and update the cache file
Expand Down
41 changes: 41 additions & 0 deletions component/profile/cachefile/subscriptioninfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cachefile

import (
"github.com/metacubex/mihomo/log"

"github.com/metacubex/bbolt"
)

func (c *CacheFile) SetSubscriptionInfo(name string, userInfo string) {
if c.DB == nil {
return
}

err := c.DB.Batch(func(t *bbolt.Tx) error {
bucket, err := t.CreateBucketIfNotExists(bucketSubscriptionInfo)
if err != nil {
return err
}

return bucket.Put([]byte(name), []byte(userInfo))
})
if err != nil {
log.Warnln("[CacheFile] write cache to %s failed: %s", c.DB.Path(), err.Error())
return
}
}
func (c *CacheFile) GetSubscriptionInfo(name string) (userInfo string) {
if c.DB == nil {
return
}
c.DB.View(func(t *bbolt.Tx) error {
if bucket := t.Bucket(bucketSubscriptionInfo); bucket != nil {
if v := bucket.Get([]byte(name)); v != nil {
userInfo = string(v)
}
}
return nil
})

return
}
22 changes: 17 additions & 5 deletions component/resource/vehicle.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ func NewFileVehicle(path string) *FileVehicle {
}

type HTTPVehicle struct {
url string
path string
proxy string
header http.Header
timeout time.Duration
url string
path string
proxy string
header http.Header
timeout time.Duration
provider types.ProxyProvider
}

func (h *HTTPVehicle) Url() string {
Expand All @@ -111,6 +112,10 @@ func (h *HTTPVehicle) Write(buf []byte) error {
return safeWrite(h.path, buf)
}

func (h *HTTPVehicle) SetProvider(provider types.ProxyProvider) {
h.provider = provider
}

func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []byte, hash utils.HashType, err error) {
ctx, cancel := context.WithTimeout(ctx, h.timeout)
defer cancel()
Expand All @@ -133,6 +138,13 @@ func (h *HTTPVehicle) Read(ctx context.Context, oldHash utils.HashType) (buf []b
return
}
defer resp.Body.Close()

if h.provider != nil {
subscriptionInfo := resp.Header.Get("subscription-userinfo")
cachefile.Cache().SetSubscriptionInfo(h.provider.Name(), subscriptionInfo)
h.provider.SetSubscriptionInfo(subscriptionInfo)
}

if resp.StatusCode < 200 || resp.StatusCode > 299 {
if setIfNoneMatch && resp.StatusCode == http.StatusNotModified {
return nil, oldHash, nil
Expand Down
4 changes: 2 additions & 2 deletions constant/adapters.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ func (at AdapterType) String() string {
return "WireGuard"
case Tuic:
return "Tuic"
case Ssh:
return "Ssh"

case Relay:
return "Relay"
Expand All @@ -224,8 +226,6 @@ func (at AdapterType) String() string {
return "URLTest"
case LoadBalance:
return "LoadBalance"
case Ssh:
return "Ssh"
default:
return "Unknown"
}
Expand Down
1 change: 1 addition & 0 deletions constant/provider/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type ProxyProvider interface {
Version() uint32
RegisterHealthCheckTask(url string, expectedStatus utils.IntRanges[uint16], filter string, interval uint)
HealthCheckURL() string
SetSubscriptionInfo(userInfo string)
}

// RuleProvider interface
Expand Down

0 comments on commit 8fb0d48

Please sign in to comment.