| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 | 
							- package libbox
 
- import (
 
- 	"encoding/binary"
 
- 	"net"
 
- 	"time"
 
- 	"github.com/sagernet/sing-box/adapter"
 
- 	"github.com/sagernet/sing-box/common/urltest"
 
- 	"github.com/sagernet/sing-box/protocol/group"
 
- 	"github.com/sagernet/sing/common"
 
- 	"github.com/sagernet/sing/common/batch"
 
- 	E "github.com/sagernet/sing/common/exceptions"
 
- 	"github.com/sagernet/sing/common/varbin"
 
- 	"github.com/sagernet/sing/service"
 
- )
 
- func (c *CommandClient) URLTest(groupTag string) error {
 
- 	conn, err := c.directConnect()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	defer conn.Close()
 
- 	err = binary.Write(conn, binary.BigEndian, uint8(CommandURLTest))
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	err = varbin.Write(conn, binary.BigEndian, groupTag)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return readError(conn)
 
- }
 
- func (s *CommandServer) handleURLTest(conn net.Conn) error {
 
- 	groupTag, err := varbin.ReadValue[string](conn, binary.BigEndian)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	serviceNow := s.service
 
- 	if serviceNow == nil {
 
- 		return nil
 
- 	}
 
- 	abstractOutboundGroup, isLoaded := serviceNow.instance.Outbound().Outbound(groupTag)
 
- 	if !isLoaded {
 
- 		return writeError(conn, E.New("outbound group not found: ", groupTag))
 
- 	}
 
- 	outboundGroup, isOutboundGroup := abstractOutboundGroup.(adapter.OutboundGroup)
 
- 	if !isOutboundGroup {
 
- 		return writeError(conn, E.New("outbound is not a group: ", groupTag))
 
- 	}
 
- 	urlTest, isURLTest := abstractOutboundGroup.(*group.URLTest)
 
- 	if isURLTest {
 
- 		go urlTest.CheckOutbounds()
 
- 	} else {
 
- 		historyStorage := service.PtrFromContext[urltest.HistoryStorage](serviceNow.ctx)
 
- 		outbounds := common.Filter(common.Map(outboundGroup.All(), func(it string) adapter.Outbound {
 
- 			itOutbound, _ := serviceNow.instance.Outbound().Outbound(it)
 
- 			return itOutbound
 
- 		}), func(it adapter.Outbound) bool {
 
- 			if it == nil {
 
- 				return false
 
- 			}
 
- 			_, isGroup := it.(adapter.OutboundGroup)
 
- 			return !isGroup
 
- 		})
 
- 		b, _ := batch.New(serviceNow.ctx, batch.WithConcurrencyNum[any](10))
 
- 		for _, detour := range outbounds {
 
- 			outboundToTest := detour
 
- 			outboundTag := outboundToTest.Tag()
 
- 			b.Go(outboundTag, func() (any, error) {
 
- 				t, err := urltest.URLTest(serviceNow.ctx, "", outboundToTest)
 
- 				if err != nil {
 
- 					historyStorage.DeleteURLTestHistory(outboundTag)
 
- 				} else {
 
- 					historyStorage.StoreURLTestHistory(outboundTag, &adapter.URLTestHistory{
 
- 						Time:  time.Now(),
 
- 						Delay: t,
 
- 					})
 
- 				}
 
- 				return nil, nil
 
- 			})
 
- 		}
 
- 	}
 
- 	return writeError(conn, nil)
 
- }
 
 
  |