Skip to content

Commit

Permalink
platform: Add group expand status
Browse files Browse the repository at this point in the history
  • Loading branch information
nekohasekai committed Aug 12, 2023
1 parent c7aff18 commit a89d51f
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 11 deletions.
2 changes: 2 additions & 0 deletions adapter/experimental.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type ClashServer interface {
type ClashCacheFile interface {
LoadSelected(group string) string
StoreSelected(group string, selected string) error
LoadGroupExpand(group string) (isExpand bool, loaded bool)
StoreGroupExpand(group string, expand bool) error
FakeIPStorage
}

Expand Down
49 changes: 38 additions & 11 deletions experimental/clashapi/cachefile/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import (
"go.etcd.io/bbolt"
)

var bucketSelected = []byte("selected")
var (
bucketSelected = []byte("selected")
bucketExpand = []byte("group_expand")
)

var _ adapter.ClashCacheFile = (*CacheFile)(nil)

Expand Down Expand Up @@ -49,21 +52,15 @@ func Open(path string, cacheID string) (*CacheFile, error) {
if name[0] == 0 {
return b.ForEachBucket(func(k []byte) error {
bucketName := string(k)
if !(bucketName == string(bucketSelected)) {
delErr := b.DeleteBucket(name)
if delErr != nil {
return delErr
}
if !(bucketName == string(bucketSelected) || bucketName == string(bucketExpand)) {
_ = b.DeleteBucket(name)
}
return nil
})
} else {
bucketName := string(name)
if !(bucketName == string(bucketSelected) || strings.HasPrefix(bucketName, fakeipBucketPrefix)) {
delErr := tx.DeleteBucket(name)
if delErr != nil {
return delErr
}
if !(bucketName == string(bucketSelected) || bucketName == string(bucketExpand) || strings.HasPrefix(bucketName, fakeipBucketPrefix)) {
_ = tx.DeleteBucket(name)
}
}
return nil
Expand Down Expand Up @@ -129,6 +126,36 @@ func (c *CacheFile) StoreSelected(group, selected string) error {
})
}

func (c *CacheFile) LoadGroupExpand(group string) (isExpand bool, loaded bool) {
c.DB.View(func(t *bbolt.Tx) error {
bucket := c.bucket(t, bucketExpand)
if bucket == nil {
return nil
}
expandBytes := bucket.Get([]byte(group))
if len(expandBytes) == 1 {
isExpand = expandBytes[0] == 1
loaded = true
}
return nil
})
return
}

func (c *CacheFile) StoreGroupExpand(group string, isExpand bool) error {
return c.DB.Batch(func(t *bbolt.Tx) error {
bucket, err := c.createBucket(t, bucketExpand)
if err != nil {
return err
}
if isExpand {
return bucket.Put([]byte(group), []byte{1})
} else {
return bucket.Put([]byte(group), []byte{0})
}
})
}

func (c *CacheFile) Close() error {
return c.DB.Close()
}
1 change: 1 addition & 0 deletions experimental/libbox/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ const (
CommandGroup
CommandSelectOutbound
CommandURLTest
CommandGroupExpand
)
84 changes: 84 additions & 0 deletions experimental/libbox/command_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/outbound"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
"github.com/sagernet/sing/service"
)
Expand All @@ -18,13 +19,27 @@ type OutboundGroup struct {
Type string
Selectable bool
Selected string
isExpand int8
items []*OutboundGroupItem
}

func (g *OutboundGroup) GetItems() OutboundGroupItemIterator {
return newIterator(g.items)
}

func (g *OutboundGroup) IsExpand(defaultValue bool) bool {
switch g.isExpand {
case -1:
return defaultValue
case 0:
return false
case 1:
return false
default:
panic("unexpected expand value")
}
}

type OutboundGroupIterator interface {
Next() *OutboundGroup
HasNext() bool
Expand Down Expand Up @@ -114,6 +129,11 @@ func readGroups(reader io.Reader) (OutboundGroupIterator, error) {
return nil, err
}

err = binary.Read(reader, binary.BigEndian, &group.isExpand)
if err != nil {
return nil, err
}

var itemLength uint16
err = binary.Read(reader, binary.BigEndian, &itemLength)
if err != nil {
Expand Down Expand Up @@ -152,6 +172,10 @@ func readGroups(reader io.Reader) (OutboundGroupIterator, error) {

func writeGroups(writer io.Writer, boxService *BoxService) error {
historyStorage := service.PtrFromContext[urltest.HistoryStorage](boxService.ctx)
var cacheFile adapter.ClashCacheFile
if clashServer := boxService.instance.Router().ClashServer(); clashServer != nil {
cacheFile = clashServer.CacheFile()
}

outbounds := boxService.instance.Router().Outbounds()
var iGroups []adapter.OutboundGroup
Expand All @@ -167,6 +191,15 @@ func writeGroups(writer io.Writer, boxService *BoxService) error {
group.Type = iGroup.Type()
_, group.Selectable = iGroup.(*outbound.Selector)
group.Selected = iGroup.Now()
if cacheFile != nil {
if isExpand, loaded := cacheFile.LoadGroupExpand(group.Tag); !loaded {
group.isExpand = -1
} else if isExpand {
group.isExpand = 1
} else {
group.isExpand = 0
}
}

for _, itemTag := range iGroup.All() {
itemOutbound, isLoaded := boxService.instance.Router().Outbound(itemTag)
Expand Down Expand Up @@ -207,6 +240,10 @@ func writeGroups(writer io.Writer, boxService *BoxService) error {
if err != nil {
return err
}
err = binary.Write(writer, binary.BigEndian, group.isExpand)
if err != nil {
return err
}
err = binary.Write(writer, binary.BigEndian, uint16(len(group.items)))
if err != nil {
return err
Expand All @@ -232,3 +269,50 @@ func writeGroups(writer io.Writer, boxService *BoxService) error {
}
return nil
}

func (c *CommandClient) SetGroupExpand(groupTag string, isExpand bool) error {
conn, err := c.directConnect()
if err != nil {
return err
}
defer conn.Close()
err = binary.Write(conn, binary.BigEndian, uint8(CommandGroupExpand))
if err != nil {
return err
}
err = rw.WriteVString(conn, groupTag)
if err != nil {
return err
}
err = binary.Write(conn, binary.BigEndian, isExpand)
if err != nil {
return err
}
return readError(conn)
}

func (s *CommandServer) handleSetGroupExpand(conn net.Conn) error {
defer conn.Close()
groupTag, err := rw.ReadVString(conn)
if err != nil {
return err
}
var isExpand bool
err = binary.Read(conn, binary.BigEndian, &isExpand)
if err != nil {
return err
}
service := s.service
if service == nil {
return writeError(conn, E.New("service not ready"))
}
if clashServer := service.instance.Router().ClashServer(); clashServer != nil {
if cacheFile := clashServer.CacheFile(); cacheFile != nil {
err = cacheFile.StoreGroupExpand(groupTag, isExpand)
if err != nil {
return writeError(conn, err)
}
}
}
return writeError(conn, nil)
}
2 changes: 2 additions & 0 deletions experimental/libbox/command_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ func (s *CommandServer) handleConnection(conn net.Conn) error {
return s.handleSelectOutbound(conn)
case CommandURLTest:
return s.handleURLTest(conn)
case CommandGroupExpand:
return s.handleSetGroupExpand(conn)
default:
return E.New("unknown command: ", command)
}
Expand Down

0 comments on commit a89d51f

Please sign in to comment.