mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
Compare commits
6 Commits
63b79b3087
...
f4de7d622a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4de7d622a | ||
|
|
fcd2b90852 | ||
|
|
0d772e6893 | ||
|
|
4806d5e588 | ||
|
|
2df43e4d1b | ||
|
|
5cbd7974df |
122
cmd/sing-box/cmd_tools_networkquality.go
Normal file
122
cmd/sing-box/cmd_tools_networkquality.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/common/networkquality"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
commandNetworkQualityFlagConfigURL string
|
||||
commandNetworkQualityFlagSerial bool
|
||||
commandNetworkQualityFlagMaxRuntime int
|
||||
)
|
||||
|
||||
var commandNetworkQuality = &cobra.Command{
|
||||
Use: "networkquality",
|
||||
Short: "Run a network quality test",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := runNetworkQuality()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
commandNetworkQuality.Flags().StringVar(
|
||||
&commandNetworkQualityFlagConfigURL,
|
||||
"config-url", "",
|
||||
"Network quality test config URL (default: Apple mensura)",
|
||||
)
|
||||
commandNetworkQuality.Flags().BoolVar(
|
||||
&commandNetworkQualityFlagSerial,
|
||||
"serial", false,
|
||||
"Run download and upload tests sequentially instead of in parallel",
|
||||
)
|
||||
commandNetworkQuality.Flags().IntVar(
|
||||
&commandNetworkQualityFlagMaxRuntime,
|
||||
"max-runtime", int(networkquality.DefaultMaxRuntime/time.Second),
|
||||
"Network quality maximum runtime in seconds",
|
||||
)
|
||||
commandTools.AddCommand(commandNetworkQuality)
|
||||
}
|
||||
|
||||
func runNetworkQuality() error {
|
||||
instance, err := createPreStartedClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer instance.Close()
|
||||
|
||||
dialer, err := createDialer(instance, commandToolsFlagOutbound)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
httpClient := networkquality.NewHTTPClient(dialer)
|
||||
defer httpClient.CloseIdleConnections()
|
||||
|
||||
fmt.Fprintln(os.Stderr, "==== NETWORK QUALITY TEST ====")
|
||||
|
||||
result, err := networkquality.Run(networkquality.Options{
|
||||
ConfigURL: commandNetworkQualityFlagConfigURL,
|
||||
HTTPClient: httpClient,
|
||||
Serial: commandNetworkQualityFlagSerial,
|
||||
MaxRuntime: time.Duration(commandNetworkQualityFlagMaxRuntime) * time.Second,
|
||||
Context: globalCtx,
|
||||
OnProgress: func(p networkquality.Progress) {
|
||||
if !commandNetworkQualityFlagSerial && p.Phase != networkquality.PhaseIdle {
|
||||
fmt.Fprintf(os.Stderr, "\rDownload: %s RPM: %d Upload: %s RPM: %d",
|
||||
formatBitrate(p.DownloadCapacity), p.DownloadRPM,
|
||||
formatBitrate(p.UploadCapacity), p.UploadRPM)
|
||||
return
|
||||
}
|
||||
switch networkquality.Phase(p.Phase) {
|
||||
case networkquality.PhaseIdle:
|
||||
if p.IdleLatencyMs > 0 {
|
||||
fmt.Fprintf(os.Stderr, "\rIdle Latency: %d ms", p.IdleLatencyMs)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "\rMeasuring idle latency...")
|
||||
}
|
||||
case networkquality.PhaseDownload:
|
||||
fmt.Fprintf(os.Stderr, "\rDownload: %s RPM: %d",
|
||||
formatBitrate(p.DownloadCapacity), p.DownloadRPM)
|
||||
case networkquality.PhaseUpload:
|
||||
fmt.Fprintf(os.Stderr, "\rUpload: %s RPM: %d",
|
||||
formatBitrate(p.UploadCapacity), p.UploadRPM)
|
||||
}
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr)
|
||||
fmt.Fprintln(os.Stderr, strings.Repeat("-", 40))
|
||||
fmt.Fprintf(os.Stderr, "Idle Latency: %d ms\n", result.IdleLatencyMs)
|
||||
fmt.Fprintf(os.Stderr, "Download Capacity: %-20s Accuracy: %s\n", formatBitrate(result.DownloadCapacity), result.DownloadCapacityAccuracy)
|
||||
fmt.Fprintf(os.Stderr, "Upload Capacity: %-20s Accuracy: %s\n", formatBitrate(result.UploadCapacity), result.UploadCapacityAccuracy)
|
||||
fmt.Fprintf(os.Stderr, "Download Responsiveness: %-20s Accuracy: %s\n", fmt.Sprintf("%d RPM", result.DownloadRPM), result.DownloadRPMAccuracy)
|
||||
fmt.Fprintf(os.Stderr, "Upload Responsiveness: %-20s Accuracy: %s\n", fmt.Sprintf("%d RPM", result.UploadRPM), result.UploadRPMAccuracy)
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatBitrate(bps int64) string {
|
||||
switch {
|
||||
case bps >= 1_000_000_000:
|
||||
return fmt.Sprintf("%.1f Gbps", float64(bps)/1_000_000_000)
|
||||
case bps >= 1_000_000:
|
||||
return fmt.Sprintf("%.1f Mbps", float64(bps)/1_000_000)
|
||||
case bps >= 1_000:
|
||||
return fmt.Sprintf("%.1f Kbps", float64(bps)/1_000)
|
||||
default:
|
||||
return fmt.Sprintf("%d bps", bps)
|
||||
}
|
||||
}
|
||||
109
common/networkquality/http.go
Normal file
109
common/networkquality/http.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package networkquality
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
sBufio "github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
// NewHTTPClient creates an http.Client that dials through the given dialer.
|
||||
// The dialer should already handle DNS resolution if needed.
|
||||
func NewHTTPClient(dialer N.Dialer) *http.Client {
|
||||
transport := &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: C.TCPTimeout,
|
||||
}
|
||||
if dialer != nil {
|
||||
transport.DialContext = func(ctx context.Context, network string, addr string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
}
|
||||
}
|
||||
return &http.Client{Transport: transport}
|
||||
}
|
||||
|
||||
func baseTransportFromClient(client *http.Client) (*http.Transport, error) {
|
||||
if client == nil {
|
||||
return nil, E.New("http client is nil")
|
||||
}
|
||||
if client.Transport == nil {
|
||||
return http.DefaultTransport.(*http.Transport).Clone(), nil
|
||||
}
|
||||
transport, ok := client.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
return nil, E.New("http client transport must be *http.Transport")
|
||||
}
|
||||
return transport.Clone(), nil
|
||||
}
|
||||
|
||||
func newMeasurementClient(
|
||||
baseClient *http.Client,
|
||||
connectEndpoint string,
|
||||
singleConnection bool,
|
||||
disableKeepAlives bool,
|
||||
readCounters []N.CountFunc,
|
||||
writeCounters []N.CountFunc,
|
||||
) (*http.Client, error) {
|
||||
transport, err := baseTransportFromClient(baseClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
transport.DisableCompression = true
|
||||
transport.DisableKeepAlives = disableKeepAlives
|
||||
if singleConnection {
|
||||
transport.MaxConnsPerHost = 1
|
||||
transport.MaxIdleConnsPerHost = 1
|
||||
transport.MaxIdleConns = 1
|
||||
}
|
||||
|
||||
baseDialContext := transport.DialContext
|
||||
if baseDialContext == nil {
|
||||
dialer := &net.Dialer{}
|
||||
baseDialContext = dialer.DialContext
|
||||
}
|
||||
connectEndpoint = strings.TrimSpace(connectEndpoint)
|
||||
transport.DialContext = func(ctx context.Context, network string, addr string) (net.Conn, error) {
|
||||
dialAddr := addr
|
||||
if connectEndpoint != "" {
|
||||
dialAddr = rewriteDialAddress(addr, connectEndpoint)
|
||||
}
|
||||
conn, dialErr := baseDialContext(ctx, network, dialAddr)
|
||||
if dialErr != nil {
|
||||
return nil, dialErr
|
||||
}
|
||||
if len(readCounters) > 0 || len(writeCounters) > 0 {
|
||||
return sBufio.NewCounterConn(conn, readCounters, writeCounters), nil
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
return &http.Client{
|
||||
Transport: transport,
|
||||
CheckRedirect: baseClient.CheckRedirect,
|
||||
Jar: baseClient.Jar,
|
||||
Timeout: baseClient.Timeout,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func rewriteDialAddress(addr string, connectEndpoint string) string {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return addr
|
||||
}
|
||||
endpointHost, endpointPort, err := net.SplitHostPort(connectEndpoint)
|
||||
if err == nil {
|
||||
host = endpointHost
|
||||
if endpointPort != "" {
|
||||
port = endpointPort
|
||||
}
|
||||
} else if connectEndpoint != "" {
|
||||
host = connectEndpoint
|
||||
}
|
||||
return net.JoinHostPort(host, port)
|
||||
}
|
||||
1408
common/networkquality/networkquality.go
Normal file
1408
common/networkquality/networkquality.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
"github.com/sagernet/sing-box/common/networkquality"
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
"github.com/sagernet/sing-box/experimental/clashapi"
|
||||
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
|
||||
@@ -1063,9 +1065,12 @@ func (s *StartedService) GetDeprecatedWarnings(ctx context.Context, empty *empty
|
||||
return &DeprecatedWarnings{
|
||||
Warnings: common.Map(notes, func(it deprecated.Note) *DeprecatedWarning {
|
||||
return &DeprecatedWarning{
|
||||
Message: it.Message(),
|
||||
Impending: it.Impending(),
|
||||
MigrationLink: it.MigrationLink,
|
||||
Message: it.Message(),
|
||||
Impending: it.Impending(),
|
||||
MigrationLink: it.MigrationLink,
|
||||
Description: it.Description,
|
||||
DeprecatedVersion: it.DeprecatedVersion,
|
||||
ScheduledVersion: it.ScheduledVersion,
|
||||
}
|
||||
}),
|
||||
}, nil
|
||||
@@ -1077,6 +1082,149 @@ func (s *StartedService) GetStartedAt(ctx context.Context, empty *emptypb.Empty)
|
||||
return &StartedAt{StartedAt: s.startedAt.UnixMilli()}, nil
|
||||
}
|
||||
|
||||
func (s *StartedService) ListOutbounds(ctx context.Context, _ *emptypb.Empty) (*OutboundList, error) {
|
||||
s.serviceAccess.RLock()
|
||||
if s.serviceStatus.Status != ServiceStatus_STARTED {
|
||||
s.serviceAccess.RUnlock()
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
boxService := s.instance
|
||||
s.serviceAccess.RUnlock()
|
||||
historyStorage := boxService.urlTestHistoryStorage
|
||||
outbounds := boxService.instance.Outbound().Outbounds()
|
||||
var list OutboundList
|
||||
for _, ob := range outbounds {
|
||||
item := &GroupItem{
|
||||
Tag: ob.Tag(),
|
||||
Type: ob.Type(),
|
||||
}
|
||||
if history := historyStorage.LoadURLTestHistory(adapter.OutboundTag(ob)); history != nil {
|
||||
item.UrlTestTime = history.Time.Unix()
|
||||
item.UrlTestDelay = int32(history.Delay)
|
||||
}
|
||||
list.Outbounds = append(list.Outbounds, item)
|
||||
}
|
||||
return &list, nil
|
||||
}
|
||||
|
||||
func (s *StartedService) SubscribeOutbounds(_ *emptypb.Empty, server grpc.ServerStreamingServer[OutboundList]) error {
|
||||
err := s.waitForStarted(server.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subscription, done, err := s.urlTestObserver.Subscribe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.urlTestObserver.UnSubscribe(subscription)
|
||||
for {
|
||||
s.serviceAccess.RLock()
|
||||
if s.serviceStatus.Status != ServiceStatus_STARTED {
|
||||
s.serviceAccess.RUnlock()
|
||||
return os.ErrInvalid
|
||||
}
|
||||
boxService := s.instance
|
||||
s.serviceAccess.RUnlock()
|
||||
historyStorage := boxService.urlTestHistoryStorage
|
||||
outbounds := boxService.instance.Outbound().Outbounds()
|
||||
var list OutboundList
|
||||
for _, ob := range outbounds {
|
||||
item := &GroupItem{
|
||||
Tag: ob.Tag(),
|
||||
Type: ob.Type(),
|
||||
}
|
||||
if history := historyStorage.LoadURLTestHistory(adapter.OutboundTag(ob)); history != nil {
|
||||
item.UrlTestTime = history.Time.Unix()
|
||||
item.UrlTestDelay = int32(history.Delay)
|
||||
}
|
||||
list.Outbounds = append(list.Outbounds, item)
|
||||
}
|
||||
err = server.Send(&list)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case <-subscription:
|
||||
case <-s.ctx.Done():
|
||||
return s.ctx.Err()
|
||||
case <-server.Context().Done():
|
||||
return server.Context().Err()
|
||||
case <-done:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StartedService) StartNetworkQualityTest(
|
||||
request *NetworkQualityTestRequest,
|
||||
server grpc.ServerStreamingServer[NetworkQualityTestProgress],
|
||||
) error {
|
||||
err := s.waitForStarted(server.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.serviceAccess.RLock()
|
||||
boxService := s.instance
|
||||
s.serviceAccess.RUnlock()
|
||||
|
||||
var outbound adapter.Outbound
|
||||
if request.OutboundTag == "" {
|
||||
outbound = boxService.instance.Outbound().Default()
|
||||
} else {
|
||||
var loaded bool
|
||||
outbound, loaded = boxService.instance.Outbound().Outbound(request.OutboundTag)
|
||||
if !loaded {
|
||||
return E.New("outbound not found: ", request.OutboundTag)
|
||||
}
|
||||
}
|
||||
|
||||
resolvedDialer := dialer.NewResolveDialer(boxService.ctx, outbound, true, "", adapter.DNSQueryOptions{}, 0)
|
||||
httpClient := networkquality.NewHTTPClient(resolvedDialer)
|
||||
defer httpClient.CloseIdleConnections()
|
||||
|
||||
result, nqErr := networkquality.Run(networkquality.Options{
|
||||
ConfigURL: request.ConfigURL,
|
||||
HTTPClient: httpClient,
|
||||
Serial: request.Serial,
|
||||
MaxRuntime: time.Duration(request.MaxRuntimeSeconds) * time.Second,
|
||||
Context: server.Context(),
|
||||
OnProgress: func(p networkquality.Progress) {
|
||||
_ = server.Send(&NetworkQualityTestProgress{
|
||||
Phase: int32(p.Phase),
|
||||
DownloadCapacity: p.DownloadCapacity,
|
||||
UploadCapacity: p.UploadCapacity,
|
||||
DownloadRPM: p.DownloadRPM,
|
||||
UploadRPM: p.UploadRPM,
|
||||
IdleLatencyMs: p.IdleLatencyMs,
|
||||
ElapsedMs: p.ElapsedMs,
|
||||
DownloadCapacityAccuracy: int32(p.DownloadCapacityAccuracy),
|
||||
UploadCapacityAccuracy: int32(p.UploadCapacityAccuracy),
|
||||
DownloadRPMAccuracy: int32(p.DownloadRPMAccuracy),
|
||||
UploadRPMAccuracy: int32(p.UploadRPMAccuracy),
|
||||
})
|
||||
},
|
||||
})
|
||||
if nqErr != nil {
|
||||
return server.Send(&NetworkQualityTestProgress{
|
||||
IsFinal: true,
|
||||
Error: nqErr.Error(),
|
||||
})
|
||||
}
|
||||
return server.Send(&NetworkQualityTestProgress{
|
||||
Phase: int32(networkquality.PhaseDone),
|
||||
DownloadCapacity: result.DownloadCapacity,
|
||||
UploadCapacity: result.UploadCapacity,
|
||||
DownloadRPM: result.DownloadRPM,
|
||||
UploadRPM: result.UploadRPM,
|
||||
IdleLatencyMs: result.IdleLatencyMs,
|
||||
IsFinal: true,
|
||||
DownloadCapacityAccuracy: int32(result.DownloadCapacityAccuracy),
|
||||
UploadCapacityAccuracy: int32(result.UploadCapacityAccuracy),
|
||||
DownloadRPMAccuracy: int32(result.DownloadRPMAccuracy),
|
||||
UploadRPMAccuracy: int32(result.UploadRPMAccuracy),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *StartedService) mustEmbedUnimplementedStartedServiceServer() {
|
||||
}
|
||||
|
||||
|
||||
@@ -1709,12 +1709,15 @@ func (x *DeprecatedWarnings) GetWarnings() []*DeprecatedWarning {
|
||||
}
|
||||
|
||||
type DeprecatedWarning struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
Impending bool `protobuf:"varint,2,opt,name=impending,proto3" json:"impending,omitempty"`
|
||||
MigrationLink string `protobuf:"bytes,3,opt,name=migrationLink,proto3" json:"migrationLink,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
Impending bool `protobuf:"varint,2,opt,name=impending,proto3" json:"impending,omitempty"`
|
||||
MigrationLink string `protobuf:"bytes,3,opt,name=migrationLink,proto3" json:"migrationLink,omitempty"`
|
||||
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
|
||||
DeprecatedVersion string `protobuf:"bytes,5,opt,name=deprecatedVersion,proto3" json:"deprecatedVersion,omitempty"`
|
||||
ScheduledVersion string `protobuf:"bytes,6,opt,name=scheduledVersion,proto3" json:"scheduledVersion,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DeprecatedWarning) Reset() {
|
||||
@@ -1768,6 +1771,27 @@ func (x *DeprecatedWarning) GetMigrationLink() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeprecatedWarning) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeprecatedWarning) GetDeprecatedVersion() string {
|
||||
if x != nil {
|
||||
return x.DeprecatedVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DeprecatedWarning) GetScheduledVersion() string {
|
||||
if x != nil {
|
||||
return x.ScheduledVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type StartedAt struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
StartedAt int64 `protobuf:"varint,1,opt,name=startedAt,proto3" json:"startedAt,omitempty"`
|
||||
@@ -1812,6 +1836,258 @@ func (x *StartedAt) GetStartedAt() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type OutboundList struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Outbounds []*GroupItem `protobuf:"bytes,1,rep,name=outbounds,proto3" json:"outbounds,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *OutboundList) Reset() {
|
||||
*x = OutboundList{}
|
||||
mi := &file_daemon_started_service_proto_msgTypes[26]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *OutboundList) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*OutboundList) ProtoMessage() {}
|
||||
|
||||
func (x *OutboundList) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_daemon_started_service_proto_msgTypes[26]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use OutboundList.ProtoReflect.Descriptor instead.
|
||||
func (*OutboundList) Descriptor() ([]byte, []int) {
|
||||
return file_daemon_started_service_proto_rawDescGZIP(), []int{26}
|
||||
}
|
||||
|
||||
func (x *OutboundList) GetOutbounds() []*GroupItem {
|
||||
if x != nil {
|
||||
return x.Outbounds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NetworkQualityTestRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ConfigURL string `protobuf:"bytes,1,opt,name=configURL,proto3" json:"configURL,omitempty"`
|
||||
OutboundTag string `protobuf:"bytes,2,opt,name=outboundTag,proto3" json:"outboundTag,omitempty"`
|
||||
Serial bool `protobuf:"varint,3,opt,name=serial,proto3" json:"serial,omitempty"`
|
||||
MaxRuntimeSeconds int32 `protobuf:"varint,4,opt,name=maxRuntimeSeconds,proto3" json:"maxRuntimeSeconds,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestRequest) Reset() {
|
||||
*x = NetworkQualityTestRequest{}
|
||||
mi := &file_daemon_started_service_proto_msgTypes[27]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NetworkQualityTestRequest) ProtoMessage() {}
|
||||
|
||||
func (x *NetworkQualityTestRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_daemon_started_service_proto_msgTypes[27]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NetworkQualityTestRequest.ProtoReflect.Descriptor instead.
|
||||
func (*NetworkQualityTestRequest) Descriptor() ([]byte, []int) {
|
||||
return file_daemon_started_service_proto_rawDescGZIP(), []int{27}
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestRequest) GetConfigURL() string {
|
||||
if x != nil {
|
||||
return x.ConfigURL
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestRequest) GetOutboundTag() string {
|
||||
if x != nil {
|
||||
return x.OutboundTag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestRequest) GetSerial() bool {
|
||||
if x != nil {
|
||||
return x.Serial
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestRequest) GetMaxRuntimeSeconds() int32 {
|
||||
if x != nil {
|
||||
return x.MaxRuntimeSeconds
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type NetworkQualityTestProgress struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Phase int32 `protobuf:"varint,1,opt,name=phase,proto3" json:"phase,omitempty"`
|
||||
DownloadCapacity int64 `protobuf:"varint,2,opt,name=downloadCapacity,proto3" json:"downloadCapacity,omitempty"`
|
||||
UploadCapacity int64 `protobuf:"varint,3,opt,name=uploadCapacity,proto3" json:"uploadCapacity,omitempty"`
|
||||
DownloadRPM int32 `protobuf:"varint,4,opt,name=downloadRPM,proto3" json:"downloadRPM,omitempty"`
|
||||
UploadRPM int32 `protobuf:"varint,5,opt,name=uploadRPM,proto3" json:"uploadRPM,omitempty"`
|
||||
IdleLatencyMs int32 `protobuf:"varint,6,opt,name=idleLatencyMs,proto3" json:"idleLatencyMs,omitempty"`
|
||||
ElapsedMs int64 `protobuf:"varint,7,opt,name=elapsedMs,proto3" json:"elapsedMs,omitempty"`
|
||||
IsFinal bool `protobuf:"varint,8,opt,name=isFinal,proto3" json:"isFinal,omitempty"`
|
||||
Error string `protobuf:"bytes,9,opt,name=error,proto3" json:"error,omitempty"`
|
||||
DownloadCapacityAccuracy int32 `protobuf:"varint,10,opt,name=downloadCapacityAccuracy,proto3" json:"downloadCapacityAccuracy,omitempty"`
|
||||
UploadCapacityAccuracy int32 `protobuf:"varint,11,opt,name=uploadCapacityAccuracy,proto3" json:"uploadCapacityAccuracy,omitempty"`
|
||||
DownloadRPMAccuracy int32 `protobuf:"varint,12,opt,name=downloadRPMAccuracy,proto3" json:"downloadRPMAccuracy,omitempty"`
|
||||
UploadRPMAccuracy int32 `protobuf:"varint,13,opt,name=uploadRPMAccuracy,proto3" json:"uploadRPMAccuracy,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) Reset() {
|
||||
*x = NetworkQualityTestProgress{}
|
||||
mi := &file_daemon_started_service_proto_msgTypes[28]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NetworkQualityTestProgress) ProtoMessage() {}
|
||||
|
||||
func (x *NetworkQualityTestProgress) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_daemon_started_service_proto_msgTypes[28]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NetworkQualityTestProgress.ProtoReflect.Descriptor instead.
|
||||
func (*NetworkQualityTestProgress) Descriptor() ([]byte, []int) {
|
||||
return file_daemon_started_service_proto_rawDescGZIP(), []int{28}
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetPhase() int32 {
|
||||
if x != nil {
|
||||
return x.Phase
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetDownloadCapacity() int64 {
|
||||
if x != nil {
|
||||
return x.DownloadCapacity
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetUploadCapacity() int64 {
|
||||
if x != nil {
|
||||
return x.UploadCapacity
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetDownloadRPM() int32 {
|
||||
if x != nil {
|
||||
return x.DownloadRPM
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetUploadRPM() int32 {
|
||||
if x != nil {
|
||||
return x.UploadRPM
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetIdleLatencyMs() int32 {
|
||||
if x != nil {
|
||||
return x.IdleLatencyMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetElapsedMs() int64 {
|
||||
if x != nil {
|
||||
return x.ElapsedMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetIsFinal() bool {
|
||||
if x != nil {
|
||||
return x.IsFinal
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetError() string {
|
||||
if x != nil {
|
||||
return x.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetDownloadCapacityAccuracy() int32 {
|
||||
if x != nil {
|
||||
return x.DownloadCapacityAccuracy
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetUploadCapacityAccuracy() int32 {
|
||||
if x != nil {
|
||||
return x.UploadCapacityAccuracy
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetDownloadRPMAccuracy() int32 {
|
||||
if x != nil {
|
||||
return x.DownloadRPMAccuracy
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkQualityTestProgress) GetUploadRPMAccuracy() int32 {
|
||||
if x != nil {
|
||||
return x.UploadRPMAccuracy
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Log_Message struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Level LogLevel `protobuf:"varint,1,opt,name=level,proto3,enum=daemon.LogLevel" json:"level,omitempty"`
|
||||
@@ -1822,7 +2098,7 @@ type Log_Message struct {
|
||||
|
||||
func (x *Log_Message) Reset() {
|
||||
*x = Log_Message{}
|
||||
mi := &file_daemon_started_service_proto_msgTypes[26]
|
||||
mi := &file_daemon_started_service_proto_msgTypes[29]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -1834,7 +2110,7 @@ func (x *Log_Message) String() string {
|
||||
func (*Log_Message) ProtoMessage() {}
|
||||
|
||||
func (x *Log_Message) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_daemon_started_service_proto_msgTypes[26]
|
||||
mi := &file_daemon_started_service_proto_msgTypes[29]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -1990,13 +2266,38 @@ const file_daemon_started_service_proto_rawDesc = "" +
|
||||
"\x16CloseConnectionRequest\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\tR\x02id\"K\n" +
|
||||
"\x12DeprecatedWarnings\x125\n" +
|
||||
"\bwarnings\x18\x01 \x03(\v2\x19.daemon.DeprecatedWarningR\bwarnings\"q\n" +
|
||||
"\bwarnings\x18\x01 \x03(\v2\x19.daemon.DeprecatedWarningR\bwarnings\"\xed\x01\n" +
|
||||
"\x11DeprecatedWarning\x12\x18\n" +
|
||||
"\amessage\x18\x01 \x01(\tR\amessage\x12\x1c\n" +
|
||||
"\timpending\x18\x02 \x01(\bR\timpending\x12$\n" +
|
||||
"\rmigrationLink\x18\x03 \x01(\tR\rmigrationLink\")\n" +
|
||||
"\rmigrationLink\x18\x03 \x01(\tR\rmigrationLink\x12 \n" +
|
||||
"\vdescription\x18\x04 \x01(\tR\vdescription\x12,\n" +
|
||||
"\x11deprecatedVersion\x18\x05 \x01(\tR\x11deprecatedVersion\x12*\n" +
|
||||
"\x10scheduledVersion\x18\x06 \x01(\tR\x10scheduledVersion\")\n" +
|
||||
"\tStartedAt\x12\x1c\n" +
|
||||
"\tstartedAt\x18\x01 \x01(\x03R\tstartedAt*U\n" +
|
||||
"\tstartedAt\x18\x01 \x01(\x03R\tstartedAt\"?\n" +
|
||||
"\fOutboundList\x12/\n" +
|
||||
"\toutbounds\x18\x01 \x03(\v2\x11.daemon.GroupItemR\toutbounds\"\xa1\x01\n" +
|
||||
"\x19NetworkQualityTestRequest\x12\x1c\n" +
|
||||
"\tconfigURL\x18\x01 \x01(\tR\tconfigURL\x12 \n" +
|
||||
"\voutboundTag\x18\x02 \x01(\tR\voutboundTag\x12\x16\n" +
|
||||
"\x06serial\x18\x03 \x01(\bR\x06serial\x12,\n" +
|
||||
"\x11maxRuntimeSeconds\x18\x04 \x01(\x05R\x11maxRuntimeSeconds\"\x8e\x04\n" +
|
||||
"\x1aNetworkQualityTestProgress\x12\x14\n" +
|
||||
"\x05phase\x18\x01 \x01(\x05R\x05phase\x12*\n" +
|
||||
"\x10downloadCapacity\x18\x02 \x01(\x03R\x10downloadCapacity\x12&\n" +
|
||||
"\x0euploadCapacity\x18\x03 \x01(\x03R\x0euploadCapacity\x12 \n" +
|
||||
"\vdownloadRPM\x18\x04 \x01(\x05R\vdownloadRPM\x12\x1c\n" +
|
||||
"\tuploadRPM\x18\x05 \x01(\x05R\tuploadRPM\x12$\n" +
|
||||
"\ridleLatencyMs\x18\x06 \x01(\x05R\ridleLatencyMs\x12\x1c\n" +
|
||||
"\telapsedMs\x18\a \x01(\x03R\telapsedMs\x12\x18\n" +
|
||||
"\aisFinal\x18\b \x01(\bR\aisFinal\x12\x14\n" +
|
||||
"\x05error\x18\t \x01(\tR\x05error\x12:\n" +
|
||||
"\x18downloadCapacityAccuracy\x18\n" +
|
||||
" \x01(\x05R\x18downloadCapacityAccuracy\x126\n" +
|
||||
"\x16uploadCapacityAccuracy\x18\v \x01(\x05R\x16uploadCapacityAccuracy\x120\n" +
|
||||
"\x13downloadRPMAccuracy\x18\f \x01(\x05R\x13downloadRPMAccuracy\x12,\n" +
|
||||
"\x11uploadRPMAccuracy\x18\r \x01(\x05R\x11uploadRPMAccuracy*U\n" +
|
||||
"\bLogLevel\x12\t\n" +
|
||||
"\x05PANIC\x10\x00\x12\t\n" +
|
||||
"\x05FATAL\x10\x01\x12\t\n" +
|
||||
@@ -2008,7 +2309,7 @@ const file_daemon_started_service_proto_rawDesc = "" +
|
||||
"\x13ConnectionEventType\x12\x18\n" +
|
||||
"\x14CONNECTION_EVENT_NEW\x10\x00\x12\x1b\n" +
|
||||
"\x17CONNECTION_EVENT_UPDATE\x10\x01\x12\x1b\n" +
|
||||
"\x17CONNECTION_EVENT_CLOSED\x10\x022\xf5\f\n" +
|
||||
"\x17CONNECTION_EVENT_CLOSED\x10\x022\xe4\x0e\n" +
|
||||
"\x0eStartedService\x12=\n" +
|
||||
"\vStopService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12?\n" +
|
||||
"\rReloadService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12K\n" +
|
||||
@@ -2032,7 +2333,10 @@ const file_daemon_started_service_proto_rawDesc = "" +
|
||||
"\x0fCloseConnection\x12\x1e.daemon.CloseConnectionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12G\n" +
|
||||
"\x13CloseAllConnections\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12M\n" +
|
||||
"\x15GetDeprecatedWarnings\x12\x16.google.protobuf.Empty\x1a\x1a.daemon.DeprecatedWarnings\"\x00\x12;\n" +
|
||||
"\fGetStartedAt\x12\x16.google.protobuf.Empty\x1a\x11.daemon.StartedAt\"\x00B%Z#github.com/sagernet/sing-box/daemonb\x06proto3"
|
||||
"\fGetStartedAt\x12\x16.google.protobuf.Empty\x1a\x11.daemon.StartedAt\"\x00\x12?\n" +
|
||||
"\rListOutbounds\x12\x16.google.protobuf.Empty\x1a\x14.daemon.OutboundList\"\x00\x12F\n" +
|
||||
"\x12SubscribeOutbounds\x12\x16.google.protobuf.Empty\x1a\x14.daemon.OutboundList\"\x000\x01\x12d\n" +
|
||||
"\x17StartNetworkQualityTest\x12!.daemon.NetworkQualityTestRequest\x1a\".daemon.NetworkQualityTestProgress\"\x000\x01B%Z#github.com/sagernet/sing-box/daemonb\x06proto3"
|
||||
|
||||
var (
|
||||
file_daemon_started_service_proto_rawDescOnce sync.Once
|
||||
@@ -2048,7 +2352,7 @@ func file_daemon_started_service_proto_rawDescGZIP() []byte {
|
||||
|
||||
var (
|
||||
file_daemon_started_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
|
||||
file_daemon_started_service_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
|
||||
file_daemon_started_service_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
|
||||
file_daemon_started_service_proto_goTypes = []any{
|
||||
(LogLevel)(0), // 0: daemon.LogLevel
|
||||
(ConnectionEventType)(0), // 1: daemon.ConnectionEventType
|
||||
@@ -2080,14 +2384,17 @@ var (
|
||||
(*DeprecatedWarnings)(nil), // 27: daemon.DeprecatedWarnings
|
||||
(*DeprecatedWarning)(nil), // 28: daemon.DeprecatedWarning
|
||||
(*StartedAt)(nil), // 29: daemon.StartedAt
|
||||
(*Log_Message)(nil), // 30: daemon.Log.Message
|
||||
(*emptypb.Empty)(nil), // 31: google.protobuf.Empty
|
||||
(*OutboundList)(nil), // 30: daemon.OutboundList
|
||||
(*NetworkQualityTestRequest)(nil), // 31: daemon.NetworkQualityTestRequest
|
||||
(*NetworkQualityTestProgress)(nil), // 32: daemon.NetworkQualityTestProgress
|
||||
(*Log_Message)(nil), // 33: daemon.Log.Message
|
||||
(*emptypb.Empty)(nil), // 34: google.protobuf.Empty
|
||||
}
|
||||
)
|
||||
|
||||
var file_daemon_started_service_proto_depIdxs = []int32{
|
||||
2, // 0: daemon.ServiceStatus.status:type_name -> daemon.ServiceStatus.Type
|
||||
30, // 1: daemon.Log.messages:type_name -> daemon.Log.Message
|
||||
33, // 1: daemon.Log.messages:type_name -> daemon.Log.Message
|
||||
0, // 2: daemon.DefaultLogLevel.level:type_name -> daemon.LogLevel
|
||||
11, // 3: daemon.Groups.group:type_name -> daemon.Group
|
||||
12, // 4: daemon.Group.items:type_name -> daemon.GroupItem
|
||||
@@ -2097,58 +2404,65 @@ var file_daemon_started_service_proto_depIdxs = []int32{
|
||||
22, // 8: daemon.ConnectionEvents.events:type_name -> daemon.ConnectionEvent
|
||||
25, // 9: daemon.Connection.processInfo:type_name -> daemon.ProcessInfo
|
||||
28, // 10: daemon.DeprecatedWarnings.warnings:type_name -> daemon.DeprecatedWarning
|
||||
0, // 11: daemon.Log.Message.level:type_name -> daemon.LogLevel
|
||||
31, // 12: daemon.StartedService.StopService:input_type -> google.protobuf.Empty
|
||||
31, // 13: daemon.StartedService.ReloadService:input_type -> google.protobuf.Empty
|
||||
31, // 14: daemon.StartedService.SubscribeServiceStatus:input_type -> google.protobuf.Empty
|
||||
31, // 15: daemon.StartedService.SubscribeLog:input_type -> google.protobuf.Empty
|
||||
31, // 16: daemon.StartedService.GetDefaultLogLevel:input_type -> google.protobuf.Empty
|
||||
31, // 17: daemon.StartedService.ClearLogs:input_type -> google.protobuf.Empty
|
||||
6, // 18: daemon.StartedService.SubscribeStatus:input_type -> daemon.SubscribeStatusRequest
|
||||
31, // 19: daemon.StartedService.SubscribeGroups:input_type -> google.protobuf.Empty
|
||||
31, // 20: daemon.StartedService.GetClashModeStatus:input_type -> google.protobuf.Empty
|
||||
31, // 21: daemon.StartedService.SubscribeClashMode:input_type -> google.protobuf.Empty
|
||||
16, // 22: daemon.StartedService.SetClashMode:input_type -> daemon.ClashMode
|
||||
13, // 23: daemon.StartedService.URLTest:input_type -> daemon.URLTestRequest
|
||||
14, // 24: daemon.StartedService.SelectOutbound:input_type -> daemon.SelectOutboundRequest
|
||||
15, // 25: daemon.StartedService.SetGroupExpand:input_type -> daemon.SetGroupExpandRequest
|
||||
31, // 26: daemon.StartedService.GetSystemProxyStatus:input_type -> google.protobuf.Empty
|
||||
19, // 27: daemon.StartedService.SetSystemProxyEnabled:input_type -> daemon.SetSystemProxyEnabledRequest
|
||||
20, // 28: daemon.StartedService.TriggerDebugCrash:input_type -> daemon.DebugCrashRequest
|
||||
31, // 29: daemon.StartedService.TriggerOOMReport:input_type -> google.protobuf.Empty
|
||||
21, // 30: daemon.StartedService.SubscribeConnections:input_type -> daemon.SubscribeConnectionsRequest
|
||||
26, // 31: daemon.StartedService.CloseConnection:input_type -> daemon.CloseConnectionRequest
|
||||
31, // 32: daemon.StartedService.CloseAllConnections:input_type -> google.protobuf.Empty
|
||||
31, // 33: daemon.StartedService.GetDeprecatedWarnings:input_type -> google.protobuf.Empty
|
||||
31, // 34: daemon.StartedService.GetStartedAt:input_type -> google.protobuf.Empty
|
||||
31, // 35: daemon.StartedService.StopService:output_type -> google.protobuf.Empty
|
||||
31, // 36: daemon.StartedService.ReloadService:output_type -> google.protobuf.Empty
|
||||
4, // 37: daemon.StartedService.SubscribeServiceStatus:output_type -> daemon.ServiceStatus
|
||||
7, // 38: daemon.StartedService.SubscribeLog:output_type -> daemon.Log
|
||||
8, // 39: daemon.StartedService.GetDefaultLogLevel:output_type -> daemon.DefaultLogLevel
|
||||
31, // 40: daemon.StartedService.ClearLogs:output_type -> google.protobuf.Empty
|
||||
9, // 41: daemon.StartedService.SubscribeStatus:output_type -> daemon.Status
|
||||
10, // 42: daemon.StartedService.SubscribeGroups:output_type -> daemon.Groups
|
||||
17, // 43: daemon.StartedService.GetClashModeStatus:output_type -> daemon.ClashModeStatus
|
||||
16, // 44: daemon.StartedService.SubscribeClashMode:output_type -> daemon.ClashMode
|
||||
31, // 45: daemon.StartedService.SetClashMode:output_type -> google.protobuf.Empty
|
||||
31, // 46: daemon.StartedService.URLTest:output_type -> google.protobuf.Empty
|
||||
31, // 47: daemon.StartedService.SelectOutbound:output_type -> google.protobuf.Empty
|
||||
31, // 48: daemon.StartedService.SetGroupExpand:output_type -> google.protobuf.Empty
|
||||
18, // 49: daemon.StartedService.GetSystemProxyStatus:output_type -> daemon.SystemProxyStatus
|
||||
31, // 50: daemon.StartedService.SetSystemProxyEnabled:output_type -> google.protobuf.Empty
|
||||
31, // 51: daemon.StartedService.TriggerDebugCrash:output_type -> google.protobuf.Empty
|
||||
31, // 52: daemon.StartedService.TriggerOOMReport:output_type -> google.protobuf.Empty
|
||||
23, // 53: daemon.StartedService.SubscribeConnections:output_type -> daemon.ConnectionEvents
|
||||
31, // 54: daemon.StartedService.CloseConnection:output_type -> google.protobuf.Empty
|
||||
31, // 55: daemon.StartedService.CloseAllConnections:output_type -> google.protobuf.Empty
|
||||
27, // 56: daemon.StartedService.GetDeprecatedWarnings:output_type -> daemon.DeprecatedWarnings
|
||||
29, // 57: daemon.StartedService.GetStartedAt:output_type -> daemon.StartedAt
|
||||
35, // [35:58] is the sub-list for method output_type
|
||||
12, // [12:35] is the sub-list for method input_type
|
||||
12, // [12:12] is the sub-list for extension type_name
|
||||
12, // [12:12] is the sub-list for extension extendee
|
||||
0, // [0:12] is the sub-list for field type_name
|
||||
12, // 11: daemon.OutboundList.outbounds:type_name -> daemon.GroupItem
|
||||
0, // 12: daemon.Log.Message.level:type_name -> daemon.LogLevel
|
||||
34, // 13: daemon.StartedService.StopService:input_type -> google.protobuf.Empty
|
||||
34, // 14: daemon.StartedService.ReloadService:input_type -> google.protobuf.Empty
|
||||
34, // 15: daemon.StartedService.SubscribeServiceStatus:input_type -> google.protobuf.Empty
|
||||
34, // 16: daemon.StartedService.SubscribeLog:input_type -> google.protobuf.Empty
|
||||
34, // 17: daemon.StartedService.GetDefaultLogLevel:input_type -> google.protobuf.Empty
|
||||
34, // 18: daemon.StartedService.ClearLogs:input_type -> google.protobuf.Empty
|
||||
6, // 19: daemon.StartedService.SubscribeStatus:input_type -> daemon.SubscribeStatusRequest
|
||||
34, // 20: daemon.StartedService.SubscribeGroups:input_type -> google.protobuf.Empty
|
||||
34, // 21: daemon.StartedService.GetClashModeStatus:input_type -> google.protobuf.Empty
|
||||
34, // 22: daemon.StartedService.SubscribeClashMode:input_type -> google.protobuf.Empty
|
||||
16, // 23: daemon.StartedService.SetClashMode:input_type -> daemon.ClashMode
|
||||
13, // 24: daemon.StartedService.URLTest:input_type -> daemon.URLTestRequest
|
||||
14, // 25: daemon.StartedService.SelectOutbound:input_type -> daemon.SelectOutboundRequest
|
||||
15, // 26: daemon.StartedService.SetGroupExpand:input_type -> daemon.SetGroupExpandRequest
|
||||
34, // 27: daemon.StartedService.GetSystemProxyStatus:input_type -> google.protobuf.Empty
|
||||
19, // 28: daemon.StartedService.SetSystemProxyEnabled:input_type -> daemon.SetSystemProxyEnabledRequest
|
||||
20, // 29: daemon.StartedService.TriggerDebugCrash:input_type -> daemon.DebugCrashRequest
|
||||
34, // 30: daemon.StartedService.TriggerOOMReport:input_type -> google.protobuf.Empty
|
||||
21, // 31: daemon.StartedService.SubscribeConnections:input_type -> daemon.SubscribeConnectionsRequest
|
||||
26, // 32: daemon.StartedService.CloseConnection:input_type -> daemon.CloseConnectionRequest
|
||||
34, // 33: daemon.StartedService.CloseAllConnections:input_type -> google.protobuf.Empty
|
||||
34, // 34: daemon.StartedService.GetDeprecatedWarnings:input_type -> google.protobuf.Empty
|
||||
34, // 35: daemon.StartedService.GetStartedAt:input_type -> google.protobuf.Empty
|
||||
34, // 36: daemon.StartedService.ListOutbounds:input_type -> google.protobuf.Empty
|
||||
34, // 37: daemon.StartedService.SubscribeOutbounds:input_type -> google.protobuf.Empty
|
||||
31, // 38: daemon.StartedService.StartNetworkQualityTest:input_type -> daemon.NetworkQualityTestRequest
|
||||
34, // 39: daemon.StartedService.StopService:output_type -> google.protobuf.Empty
|
||||
34, // 40: daemon.StartedService.ReloadService:output_type -> google.protobuf.Empty
|
||||
4, // 41: daemon.StartedService.SubscribeServiceStatus:output_type -> daemon.ServiceStatus
|
||||
7, // 42: daemon.StartedService.SubscribeLog:output_type -> daemon.Log
|
||||
8, // 43: daemon.StartedService.GetDefaultLogLevel:output_type -> daemon.DefaultLogLevel
|
||||
34, // 44: daemon.StartedService.ClearLogs:output_type -> google.protobuf.Empty
|
||||
9, // 45: daemon.StartedService.SubscribeStatus:output_type -> daemon.Status
|
||||
10, // 46: daemon.StartedService.SubscribeGroups:output_type -> daemon.Groups
|
||||
17, // 47: daemon.StartedService.GetClashModeStatus:output_type -> daemon.ClashModeStatus
|
||||
16, // 48: daemon.StartedService.SubscribeClashMode:output_type -> daemon.ClashMode
|
||||
34, // 49: daemon.StartedService.SetClashMode:output_type -> google.protobuf.Empty
|
||||
34, // 50: daemon.StartedService.URLTest:output_type -> google.protobuf.Empty
|
||||
34, // 51: daemon.StartedService.SelectOutbound:output_type -> google.protobuf.Empty
|
||||
34, // 52: daemon.StartedService.SetGroupExpand:output_type -> google.protobuf.Empty
|
||||
18, // 53: daemon.StartedService.GetSystemProxyStatus:output_type -> daemon.SystemProxyStatus
|
||||
34, // 54: daemon.StartedService.SetSystemProxyEnabled:output_type -> google.protobuf.Empty
|
||||
34, // 55: daemon.StartedService.TriggerDebugCrash:output_type -> google.protobuf.Empty
|
||||
34, // 56: daemon.StartedService.TriggerOOMReport:output_type -> google.protobuf.Empty
|
||||
23, // 57: daemon.StartedService.SubscribeConnections:output_type -> daemon.ConnectionEvents
|
||||
34, // 58: daemon.StartedService.CloseConnection:output_type -> google.protobuf.Empty
|
||||
34, // 59: daemon.StartedService.CloseAllConnections:output_type -> google.protobuf.Empty
|
||||
27, // 60: daemon.StartedService.GetDeprecatedWarnings:output_type -> daemon.DeprecatedWarnings
|
||||
29, // 61: daemon.StartedService.GetStartedAt:output_type -> daemon.StartedAt
|
||||
30, // 62: daemon.StartedService.ListOutbounds:output_type -> daemon.OutboundList
|
||||
30, // 63: daemon.StartedService.SubscribeOutbounds:output_type -> daemon.OutboundList
|
||||
32, // 64: daemon.StartedService.StartNetworkQualityTest:output_type -> daemon.NetworkQualityTestProgress
|
||||
39, // [39:65] is the sub-list for method output_type
|
||||
13, // [13:39] is the sub-list for method input_type
|
||||
13, // [13:13] is the sub-list for extension type_name
|
||||
13, // [13:13] is the sub-list for extension extendee
|
||||
0, // [0:13] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_daemon_started_service_proto_init() }
|
||||
@@ -2162,7 +2476,7 @@ func file_daemon_started_service_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_daemon_started_service_proto_rawDesc), len(file_daemon_started_service_proto_rawDesc)),
|
||||
NumEnums: 4,
|
||||
NumMessages: 27,
|
||||
NumMessages: 30,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -34,6 +34,10 @@ service StartedService {
|
||||
rpc CloseAllConnections(google.protobuf.Empty) returns(google.protobuf.Empty) {}
|
||||
rpc GetDeprecatedWarnings(google.protobuf.Empty) returns(DeprecatedWarnings) {}
|
||||
rpc GetStartedAt(google.protobuf.Empty) returns(StartedAt) {}
|
||||
|
||||
rpc ListOutbounds(google.protobuf.Empty) returns (OutboundList) {}
|
||||
rpc SubscribeOutbounds(google.protobuf.Empty) returns (stream OutboundList) {}
|
||||
rpc StartNetworkQualityTest(NetworkQualityTestRequest) returns (stream NetworkQualityTestProgress) {}
|
||||
}
|
||||
|
||||
message ServiceStatus {
|
||||
@@ -221,8 +225,38 @@ message DeprecatedWarning {
|
||||
string message = 1;
|
||||
bool impending = 2;
|
||||
string migrationLink = 3;
|
||||
string description = 4;
|
||||
string deprecatedVersion = 5;
|
||||
string scheduledVersion = 6;
|
||||
}
|
||||
|
||||
message StartedAt {
|
||||
int64 startedAt = 1;
|
||||
}
|
||||
|
||||
message OutboundList {
|
||||
repeated GroupItem outbounds = 1;
|
||||
}
|
||||
|
||||
message NetworkQualityTestRequest {
|
||||
string configURL = 1;
|
||||
string outboundTag = 2;
|
||||
bool serial = 3;
|
||||
int32 maxRuntimeSeconds = 4;
|
||||
}
|
||||
|
||||
message NetworkQualityTestProgress {
|
||||
int32 phase = 1;
|
||||
int64 downloadCapacity = 2;
|
||||
int64 uploadCapacity = 3;
|
||||
int32 downloadRPM = 4;
|
||||
int32 uploadRPM = 5;
|
||||
int32 idleLatencyMs = 6;
|
||||
int64 elapsedMs = 7;
|
||||
bool isFinal = 8;
|
||||
string error = 9;
|
||||
int32 downloadCapacityAccuracy = 10;
|
||||
int32 uploadCapacityAccuracy = 11;
|
||||
int32 downloadRPMAccuracy = 12;
|
||||
int32 uploadRPMAccuracy = 13;
|
||||
}
|
||||
|
||||
@@ -15,29 +15,32 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
StartedService_StopService_FullMethodName = "/daemon.StartedService/StopService"
|
||||
StartedService_ReloadService_FullMethodName = "/daemon.StartedService/ReloadService"
|
||||
StartedService_SubscribeServiceStatus_FullMethodName = "/daemon.StartedService/SubscribeServiceStatus"
|
||||
StartedService_SubscribeLog_FullMethodName = "/daemon.StartedService/SubscribeLog"
|
||||
StartedService_GetDefaultLogLevel_FullMethodName = "/daemon.StartedService/GetDefaultLogLevel"
|
||||
StartedService_ClearLogs_FullMethodName = "/daemon.StartedService/ClearLogs"
|
||||
StartedService_SubscribeStatus_FullMethodName = "/daemon.StartedService/SubscribeStatus"
|
||||
StartedService_SubscribeGroups_FullMethodName = "/daemon.StartedService/SubscribeGroups"
|
||||
StartedService_GetClashModeStatus_FullMethodName = "/daemon.StartedService/GetClashModeStatus"
|
||||
StartedService_SubscribeClashMode_FullMethodName = "/daemon.StartedService/SubscribeClashMode"
|
||||
StartedService_SetClashMode_FullMethodName = "/daemon.StartedService/SetClashMode"
|
||||
StartedService_URLTest_FullMethodName = "/daemon.StartedService/URLTest"
|
||||
StartedService_SelectOutbound_FullMethodName = "/daemon.StartedService/SelectOutbound"
|
||||
StartedService_SetGroupExpand_FullMethodName = "/daemon.StartedService/SetGroupExpand"
|
||||
StartedService_GetSystemProxyStatus_FullMethodName = "/daemon.StartedService/GetSystemProxyStatus"
|
||||
StartedService_SetSystemProxyEnabled_FullMethodName = "/daemon.StartedService/SetSystemProxyEnabled"
|
||||
StartedService_TriggerDebugCrash_FullMethodName = "/daemon.StartedService/TriggerDebugCrash"
|
||||
StartedService_TriggerOOMReport_FullMethodName = "/daemon.StartedService/TriggerOOMReport"
|
||||
StartedService_SubscribeConnections_FullMethodName = "/daemon.StartedService/SubscribeConnections"
|
||||
StartedService_CloseConnection_FullMethodName = "/daemon.StartedService/CloseConnection"
|
||||
StartedService_CloseAllConnections_FullMethodName = "/daemon.StartedService/CloseAllConnections"
|
||||
StartedService_GetDeprecatedWarnings_FullMethodName = "/daemon.StartedService/GetDeprecatedWarnings"
|
||||
StartedService_GetStartedAt_FullMethodName = "/daemon.StartedService/GetStartedAt"
|
||||
StartedService_StopService_FullMethodName = "/daemon.StartedService/StopService"
|
||||
StartedService_ReloadService_FullMethodName = "/daemon.StartedService/ReloadService"
|
||||
StartedService_SubscribeServiceStatus_FullMethodName = "/daemon.StartedService/SubscribeServiceStatus"
|
||||
StartedService_SubscribeLog_FullMethodName = "/daemon.StartedService/SubscribeLog"
|
||||
StartedService_GetDefaultLogLevel_FullMethodName = "/daemon.StartedService/GetDefaultLogLevel"
|
||||
StartedService_ClearLogs_FullMethodName = "/daemon.StartedService/ClearLogs"
|
||||
StartedService_SubscribeStatus_FullMethodName = "/daemon.StartedService/SubscribeStatus"
|
||||
StartedService_SubscribeGroups_FullMethodName = "/daemon.StartedService/SubscribeGroups"
|
||||
StartedService_GetClashModeStatus_FullMethodName = "/daemon.StartedService/GetClashModeStatus"
|
||||
StartedService_SubscribeClashMode_FullMethodName = "/daemon.StartedService/SubscribeClashMode"
|
||||
StartedService_SetClashMode_FullMethodName = "/daemon.StartedService/SetClashMode"
|
||||
StartedService_URLTest_FullMethodName = "/daemon.StartedService/URLTest"
|
||||
StartedService_SelectOutbound_FullMethodName = "/daemon.StartedService/SelectOutbound"
|
||||
StartedService_SetGroupExpand_FullMethodName = "/daemon.StartedService/SetGroupExpand"
|
||||
StartedService_GetSystemProxyStatus_FullMethodName = "/daemon.StartedService/GetSystemProxyStatus"
|
||||
StartedService_SetSystemProxyEnabled_FullMethodName = "/daemon.StartedService/SetSystemProxyEnabled"
|
||||
StartedService_TriggerDebugCrash_FullMethodName = "/daemon.StartedService/TriggerDebugCrash"
|
||||
StartedService_TriggerOOMReport_FullMethodName = "/daemon.StartedService/TriggerOOMReport"
|
||||
StartedService_SubscribeConnections_FullMethodName = "/daemon.StartedService/SubscribeConnections"
|
||||
StartedService_CloseConnection_FullMethodName = "/daemon.StartedService/CloseConnection"
|
||||
StartedService_CloseAllConnections_FullMethodName = "/daemon.StartedService/CloseAllConnections"
|
||||
StartedService_GetDeprecatedWarnings_FullMethodName = "/daemon.StartedService/GetDeprecatedWarnings"
|
||||
StartedService_GetStartedAt_FullMethodName = "/daemon.StartedService/GetStartedAt"
|
||||
StartedService_ListOutbounds_FullMethodName = "/daemon.StartedService/ListOutbounds"
|
||||
StartedService_SubscribeOutbounds_FullMethodName = "/daemon.StartedService/SubscribeOutbounds"
|
||||
StartedService_StartNetworkQualityTest_FullMethodName = "/daemon.StartedService/StartNetworkQualityTest"
|
||||
)
|
||||
|
||||
// StartedServiceClient is the client API for StartedService service.
|
||||
@@ -67,6 +70,9 @@ type StartedServiceClient interface {
|
||||
CloseAllConnections(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
GetDeprecatedWarnings(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*DeprecatedWarnings, error)
|
||||
GetStartedAt(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StartedAt, error)
|
||||
ListOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*OutboundList, error)
|
||||
SubscribeOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OutboundList], error)
|
||||
StartNetworkQualityTest(ctx context.Context, in *NetworkQualityTestRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[NetworkQualityTestProgress], error)
|
||||
}
|
||||
|
||||
type startedServiceClient struct {
|
||||
@@ -361,6 +367,54 @@ func (c *startedServiceClient) GetStartedAt(ctx context.Context, in *emptypb.Emp
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *startedServiceClient) ListOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*OutboundList, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(OutboundList)
|
||||
err := c.cc.Invoke(ctx, StartedService_ListOutbounds_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *startedServiceClient) SubscribeOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OutboundList], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &StartedService_ServiceDesc.Streams[6], StartedService_SubscribeOutbounds_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[emptypb.Empty, OutboundList]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type StartedService_SubscribeOutboundsClient = grpc.ServerStreamingClient[OutboundList]
|
||||
|
||||
func (c *startedServiceClient) StartNetworkQualityTest(ctx context.Context, in *NetworkQualityTestRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[NetworkQualityTestProgress], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &StartedService_ServiceDesc.Streams[7], StartedService_StartNetworkQualityTest_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[NetworkQualityTestRequest, NetworkQualityTestProgress]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type StartedService_StartNetworkQualityTestClient = grpc.ServerStreamingClient[NetworkQualityTestProgress]
|
||||
|
||||
// StartedServiceServer is the server API for StartedService service.
|
||||
// All implementations must embed UnimplementedStartedServiceServer
|
||||
// for forward compatibility.
|
||||
@@ -388,6 +442,9 @@ type StartedServiceServer interface {
|
||||
CloseAllConnections(context.Context, *emptypb.Empty) (*emptypb.Empty, error)
|
||||
GetDeprecatedWarnings(context.Context, *emptypb.Empty) (*DeprecatedWarnings, error)
|
||||
GetStartedAt(context.Context, *emptypb.Empty) (*StartedAt, error)
|
||||
ListOutbounds(context.Context, *emptypb.Empty) (*OutboundList, error)
|
||||
SubscribeOutbounds(*emptypb.Empty, grpc.ServerStreamingServer[OutboundList]) error
|
||||
StartNetworkQualityTest(*NetworkQualityTestRequest, grpc.ServerStreamingServer[NetworkQualityTestProgress]) error
|
||||
mustEmbedUnimplementedStartedServiceServer()
|
||||
}
|
||||
|
||||
@@ -489,6 +546,18 @@ func (UnimplementedStartedServiceServer) GetDeprecatedWarnings(context.Context,
|
||||
func (UnimplementedStartedServiceServer) GetStartedAt(context.Context, *emptypb.Empty) (*StartedAt, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method GetStartedAt not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedStartedServiceServer) ListOutbounds(context.Context, *emptypb.Empty) (*OutboundList, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListOutbounds not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedStartedServiceServer) SubscribeOutbounds(*emptypb.Empty, grpc.ServerStreamingServer[OutboundList]) error {
|
||||
return status.Error(codes.Unimplemented, "method SubscribeOutbounds not implemented")
|
||||
}
|
||||
|
||||
func (UnimplementedStartedServiceServer) StartNetworkQualityTest(*NetworkQualityTestRequest, grpc.ServerStreamingServer[NetworkQualityTestProgress]) error {
|
||||
return status.Error(codes.Unimplemented, "method StartNetworkQualityTest not implemented")
|
||||
}
|
||||
func (UnimplementedStartedServiceServer) mustEmbedUnimplementedStartedServiceServer() {}
|
||||
func (UnimplementedStartedServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -882,6 +951,46 @@ func _StartedService_GetStartedAt_Handler(srv interface{}, ctx context.Context,
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _StartedService_ListOutbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(emptypb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(StartedServiceServer).ListOutbounds(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: StartedService_ListOutbounds_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(StartedServiceServer).ListOutbounds(ctx, req.(*emptypb.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _StartedService_SubscribeOutbounds_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(emptypb.Empty)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(StartedServiceServer).SubscribeOutbounds(m, &grpc.GenericServerStream[emptypb.Empty, OutboundList]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type StartedService_SubscribeOutboundsServer = grpc.ServerStreamingServer[OutboundList]
|
||||
|
||||
func _StartedService_StartNetworkQualityTest_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(NetworkQualityTestRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(StartedServiceServer).StartNetworkQualityTest(m, &grpc.GenericServerStream[NetworkQualityTestRequest, NetworkQualityTestProgress]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type StartedService_StartNetworkQualityTestServer = grpc.ServerStreamingServer[NetworkQualityTestProgress]
|
||||
|
||||
// StartedService_ServiceDesc is the grpc.ServiceDesc for StartedService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -957,6 +1066,10 @@ var StartedService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetStartedAt",
|
||||
Handler: _StartedService_GetStartedAt_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListOutbounds",
|
||||
Handler: _StartedService_ListOutbounds_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
@@ -989,6 +1102,16 @@ var StartedService_ServiceDesc = grpc.ServiceDesc{
|
||||
Handler: _StartedService_SubscribeConnections_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "SubscribeOutbounds",
|
||||
Handler: _StartedService_SubscribeOutbounds_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "StartNetworkQualityTest",
|
||||
Handler: _StartedService_StartNetworkQualityTest_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "daemon/started_service.proto",
|
||||
}
|
||||
|
||||
@@ -29,24 +29,26 @@ import (
|
||||
mDNS "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
var _ adapter.DNSRouter = (*Router)(nil)
|
||||
var _ adapter.DNSRuleSetUpdateValidator = (*Router)(nil)
|
||||
var (
|
||||
_ adapter.DNSRouter = (*Router)(nil)
|
||||
_ adapter.DNSRuleSetUpdateValidator = (*Router)(nil)
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
transport adapter.DNSTransportManager
|
||||
outbound adapter.OutboundManager
|
||||
client adapter.DNSClient
|
||||
rawRules []option.DNSRule
|
||||
rules []adapter.DNSRule
|
||||
defaultDomainStrategy C.DomainStrategy
|
||||
dnsReverseMapping freelru.Cache[netip.Addr, string]
|
||||
platformInterface adapter.PlatformInterface
|
||||
legacyDNSMode bool
|
||||
rulesAccess sync.RWMutex
|
||||
started bool
|
||||
closing bool
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
transport adapter.DNSTransportManager
|
||||
outbound adapter.OutboundManager
|
||||
client adapter.DNSClient
|
||||
rawRules []option.DNSRule
|
||||
rules []adapter.DNSRule
|
||||
defaultDomainStrategy C.DomainStrategy
|
||||
dnsReverseMapping freelru.Cache[netip.Addr, string]
|
||||
platformInterface adapter.PlatformInterface
|
||||
legacyDNSMode bool
|
||||
rulesAccess sync.RWMutex
|
||||
started bool
|
||||
closing bool
|
||||
}
|
||||
|
||||
func NewRouter(ctx context.Context, logFactory log.Factory, options option.DNSOptions) *Router {
|
||||
|
||||
@@ -6,4 +6,5 @@ const (
|
||||
CommandGroup
|
||||
CommandClashMode
|
||||
CommandConnections
|
||||
CommandOutbounds
|
||||
)
|
||||
|
||||
@@ -47,6 +47,7 @@ type CommandClientHandler interface {
|
||||
WriteLogs(messageList LogIterator)
|
||||
WriteStatus(message *StatusMessage)
|
||||
WriteGroups(message OutboundGroupIterator)
|
||||
WriteOutbounds(message OutboundGroupItemIterator)
|
||||
InitializeClashMode(modeList StringIterator, currentMode string)
|
||||
UpdateClashMode(newMode string)
|
||||
WriteConnectionEvents(events *ConnectionEvents)
|
||||
@@ -243,6 +244,8 @@ func (c *CommandClient) dispatchCommands() error {
|
||||
go c.handleClashModeStream()
|
||||
case CommandConnections:
|
||||
go c.handleConnectionsStream()
|
||||
case CommandOutbounds:
|
||||
go c.handleOutboundsStream()
|
||||
default:
|
||||
return E.New("unknown command: ", command)
|
||||
}
|
||||
@@ -456,6 +459,25 @@ func (c *CommandClient) handleConnectionsStream() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommandClient) handleOutboundsStream() {
|
||||
client, ctx := c.getStreamContext()
|
||||
|
||||
stream, err := client.SubscribeOutbounds(ctx, &emptypb.Empty{})
|
||||
if err != nil {
|
||||
c.handler.Disconnected(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
list, err := stream.Recv()
|
||||
if err != nil {
|
||||
c.handler.Disconnected(err.Error())
|
||||
return
|
||||
}
|
||||
c.handler.WriteOutbounds(outboundGroupItemListFromGRPC(list))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommandClient) SelectOutbound(groupTag string, outboundTag string) error {
|
||||
_, err := callWithResult(c, func(client daemon.StartedServiceClient) (*emptypb.Empty, error) {
|
||||
return client.SelectOutbound(context.Background(), &daemon.SelectOutboundRequest{
|
||||
@@ -574,8 +596,10 @@ func (c *CommandClient) GetDeprecatedNotes() (DeprecatedNoteIterator, error) {
|
||||
var notes []*DeprecatedNote
|
||||
for _, warning := range warnings.Warnings {
|
||||
notes = append(notes, &DeprecatedNote{
|
||||
Description: warning.Message,
|
||||
MigrationLink: warning.MigrationLink,
|
||||
Description: warning.Description,
|
||||
DeprecatedVersion: warning.DeprecatedVersion,
|
||||
ScheduledVersion: warning.ScheduledVersion,
|
||||
MigrationLink: warning.MigrationLink,
|
||||
})
|
||||
}
|
||||
return newIterator(notes), nil
|
||||
@@ -601,3 +625,78 @@ func (c *CommandClient) SetGroupExpand(groupTag string, isExpand bool) error {
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *CommandClient) ListOutbounds() (OutboundGroupItemIterator, error) {
|
||||
return callWithResult(c, func(client daemon.StartedServiceClient) (OutboundGroupItemIterator, error) {
|
||||
list, err := client.ListOutbounds(context.Background(), &emptypb.Empty{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return outboundGroupItemListFromGRPC(list), nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *CommandClient) StartNetworkQualityTest(configURL string, outboundTag string, handler NetworkQualityTestHandler) error {
|
||||
return c.StartNetworkQualityTestWithSerialAndRuntime(
|
||||
configURL,
|
||||
outboundTag,
|
||||
false,
|
||||
NetworkQualityDefaultMaxRuntimeSeconds,
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *CommandClient) StartNetworkQualityTestWithSerial(configURL string, outboundTag string, serial bool, handler NetworkQualityTestHandler) error {
|
||||
return c.StartNetworkQualityTestWithSerialAndRuntime(
|
||||
configURL,
|
||||
outboundTag,
|
||||
serial,
|
||||
NetworkQualityDefaultMaxRuntimeSeconds,
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *CommandClient) StartNetworkQualityTestWithSerialAndRuntime(configURL string, outboundTag string, serial bool, maxRuntimeSeconds int32, handler NetworkQualityTestHandler) error {
|
||||
client, err := c.getClientForCall()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.standalone {
|
||||
defer c.closeConnection()
|
||||
}
|
||||
stream, err := client.StartNetworkQualityTest(context.Background(), &daemon.NetworkQualityTestRequest{
|
||||
ConfigURL: configURL,
|
||||
OutboundTag: outboundTag,
|
||||
Serial: serial,
|
||||
MaxRuntimeSeconds: maxRuntimeSeconds,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
event, recvErr := stream.Recv()
|
||||
if recvErr != nil {
|
||||
handler.OnError(recvErr.Error())
|
||||
return recvErr
|
||||
}
|
||||
if event.IsFinal {
|
||||
if event.Error != "" {
|
||||
handler.OnError(event.Error)
|
||||
} else {
|
||||
handler.OnResult(&NetworkQualityResult{
|
||||
DownloadCapacity: event.DownloadCapacity,
|
||||
UploadCapacity: event.UploadCapacity,
|
||||
DownloadRPM: event.DownloadRPM,
|
||||
UploadRPM: event.UploadRPM,
|
||||
IdleLatencyMs: event.IdleLatencyMs,
|
||||
DownloadCapacityAccuracy: event.DownloadCapacityAccuracy,
|
||||
UploadCapacityAccuracy: event.UploadCapacityAccuracy,
|
||||
DownloadRPMAccuracy: event.DownloadRPMAccuracy,
|
||||
UploadRPMAccuracy: event.UploadRPMAccuracy,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
handler.OnProgress(networkQualityProgressFromGRPC(event))
|
||||
}
|
||||
}
|
||||
|
||||
71
experimental/libbox/command_types_nq.go
Normal file
71
experimental/libbox/command_types_nq.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package libbox
|
||||
|
||||
import "github.com/sagernet/sing-box/daemon"
|
||||
|
||||
type NetworkQualityProgress struct {
|
||||
Phase int32
|
||||
DownloadCapacity int64
|
||||
UploadCapacity int64
|
||||
DownloadRPM int32
|
||||
UploadRPM int32
|
||||
IdleLatencyMs int32
|
||||
ElapsedMs int64
|
||||
IsFinal bool
|
||||
Error string
|
||||
DownloadCapacityAccuracy int32
|
||||
UploadCapacityAccuracy int32
|
||||
DownloadRPMAccuracy int32
|
||||
UploadRPMAccuracy int32
|
||||
}
|
||||
|
||||
type NetworkQualityResult struct {
|
||||
DownloadCapacity int64
|
||||
UploadCapacity int64
|
||||
DownloadRPM int32
|
||||
UploadRPM int32
|
||||
IdleLatencyMs int32
|
||||
DownloadCapacityAccuracy int32
|
||||
UploadCapacityAccuracy int32
|
||||
DownloadRPMAccuracy int32
|
||||
UploadRPMAccuracy int32
|
||||
}
|
||||
|
||||
type NetworkQualityTestHandler interface {
|
||||
OnProgress(progress *NetworkQualityProgress)
|
||||
OnResult(result *NetworkQualityResult)
|
||||
OnError(message string)
|
||||
}
|
||||
|
||||
func outboundGroupItemListFromGRPC(list *daemon.OutboundList) OutboundGroupItemIterator {
|
||||
if list == nil || len(list.Outbounds) == 0 {
|
||||
return newIterator([]*OutboundGroupItem{})
|
||||
}
|
||||
var items []*OutboundGroupItem
|
||||
for _, ob := range list.Outbounds {
|
||||
items = append(items, &OutboundGroupItem{
|
||||
Tag: ob.Tag,
|
||||
Type: ob.Type,
|
||||
URLTestTime: ob.UrlTestTime,
|
||||
URLTestDelay: ob.UrlTestDelay,
|
||||
})
|
||||
}
|
||||
return newIterator(items)
|
||||
}
|
||||
|
||||
func networkQualityProgressFromGRPC(event *daemon.NetworkQualityTestProgress) *NetworkQualityProgress {
|
||||
return &NetworkQualityProgress{
|
||||
Phase: event.Phase,
|
||||
DownloadCapacity: event.DownloadCapacity,
|
||||
UploadCapacity: event.UploadCapacity,
|
||||
DownloadRPM: event.DownloadRPM,
|
||||
UploadRPM: event.UploadRPM,
|
||||
IdleLatencyMs: event.IdleLatencyMs,
|
||||
ElapsedMs: event.ElapsedMs,
|
||||
IsFinal: event.IsFinal,
|
||||
Error: event.Error,
|
||||
DownloadCapacityAccuracy: event.DownloadCapacityAccuracy,
|
||||
UploadCapacityAccuracy: event.UploadCapacityAccuracy,
|
||||
DownloadRPMAccuracy: event.DownloadRPMAccuracy,
|
||||
UploadRPMAccuracy: event.UploadRPMAccuracy,
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"runtime"
|
||||
_ "runtime/pprof"
|
||||
"unsafe"
|
||||
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"encoding/binary"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
|
||||
75
experimental/libbox/networkquality.go
Normal file
75
experimental/libbox/networkquality.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/common/networkquality"
|
||||
)
|
||||
|
||||
type NetworkQualityTest struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewNetworkQualityTest() *NetworkQualityTest {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &NetworkQualityTest{ctx: ctx, cancel: cancel}
|
||||
}
|
||||
|
||||
func (t *NetworkQualityTest) Start(configURL string, handler NetworkQualityTestHandler) {
|
||||
t.StartWithSerialAndRuntime(configURL, false, NetworkQualityDefaultMaxRuntimeSeconds, handler)
|
||||
}
|
||||
|
||||
func (t *NetworkQualityTest) StartWithSerial(configURL string, serial bool, handler NetworkQualityTestHandler) {
|
||||
t.StartWithSerialAndRuntime(configURL, serial, NetworkQualityDefaultMaxRuntimeSeconds, handler)
|
||||
}
|
||||
|
||||
func (t *NetworkQualityTest) StartWithSerialAndRuntime(configURL string, serial bool, maxRuntimeSeconds int32, handler NetworkQualityTestHandler) {
|
||||
go func() {
|
||||
httpClient := networkquality.NewHTTPClient(nil)
|
||||
defer httpClient.CloseIdleConnections()
|
||||
|
||||
result, err := networkquality.Run(networkquality.Options{
|
||||
ConfigURL: configURL,
|
||||
HTTPClient: httpClient,
|
||||
Serial: serial,
|
||||
MaxRuntime: time.Duration(maxRuntimeSeconds) * time.Second,
|
||||
Context: t.ctx,
|
||||
OnProgress: func(p networkquality.Progress) {
|
||||
handler.OnProgress(&NetworkQualityProgress{
|
||||
Phase: int32(p.Phase),
|
||||
DownloadCapacity: p.DownloadCapacity,
|
||||
UploadCapacity: p.UploadCapacity,
|
||||
DownloadRPM: p.DownloadRPM,
|
||||
UploadRPM: p.UploadRPM,
|
||||
IdleLatencyMs: p.IdleLatencyMs,
|
||||
ElapsedMs: p.ElapsedMs,
|
||||
DownloadCapacityAccuracy: int32(p.DownloadCapacityAccuracy),
|
||||
UploadCapacityAccuracy: int32(p.UploadCapacityAccuracy),
|
||||
DownloadRPMAccuracy: int32(p.DownloadRPMAccuracy),
|
||||
UploadRPMAccuracy: int32(p.UploadRPMAccuracy),
|
||||
})
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
handler.OnError(err.Error())
|
||||
return
|
||||
}
|
||||
handler.OnResult(&NetworkQualityResult{
|
||||
DownloadCapacity: result.DownloadCapacity,
|
||||
UploadCapacity: result.UploadCapacity,
|
||||
DownloadRPM: result.DownloadRPM,
|
||||
UploadRPM: result.UploadRPM,
|
||||
IdleLatencyMs: result.IdleLatencyMs,
|
||||
DownloadCapacityAccuracy: int32(result.DownloadCapacityAccuracy),
|
||||
UploadCapacityAccuracy: int32(result.UploadCapacityAccuracy),
|
||||
DownloadRPMAccuracy: int32(result.DownloadRPMAccuracy),
|
||||
UploadRPMAccuracy: int32(result.UploadRPMAccuracy),
|
||||
})
|
||||
}()
|
||||
}
|
||||
|
||||
func (t *NetworkQualityTest) Cancel() {
|
||||
t.cancel()
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/common/networkquality"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/locale"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/service/oomkiller"
|
||||
"github.com/sagernet/sing/common/byteformats"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -97,8 +101,14 @@ func Setup(options *SetupOptions) error {
|
||||
return redirectStderr(filepath.Join(sWorkingPath, "CrashReport-"+sCrashReportSource+".log"))
|
||||
}
|
||||
|
||||
func SetLocale(localeId string) {
|
||||
locale.Set(localeId)
|
||||
func SetLocale(localeId string) error {
|
||||
if strings.Contains(localeId, "@") {
|
||||
localeId = strings.Split(localeId, "@")[0]
|
||||
}
|
||||
if !locale.Set(localeId) {
|
||||
return E.New("unsupported locale: ", localeId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Version() string {
|
||||
@@ -121,6 +131,29 @@ func FormatDuration(duration int64) string {
|
||||
return log.FormatDuration(time.Duration(duration) * time.Millisecond)
|
||||
}
|
||||
|
||||
func FormatBitrate(bps int64) string {
|
||||
switch {
|
||||
case bps >= 1_000_000_000:
|
||||
return fmt.Sprintf("%.1f Gbps", float64(bps)/1_000_000_000)
|
||||
case bps >= 1_000_000:
|
||||
return fmt.Sprintf("%.1f Mbps", float64(bps)/1_000_000)
|
||||
case bps >= 1_000:
|
||||
return fmt.Sprintf("%.1f Kbps", float64(bps)/1_000)
|
||||
default:
|
||||
return fmt.Sprintf("%d bps", bps)
|
||||
}
|
||||
}
|
||||
|
||||
const NetworkQualityDefaultConfigURL = networkquality.DefaultConfigURL
|
||||
|
||||
const NetworkQualityDefaultMaxRuntimeSeconds = int32(networkquality.DefaultMaxRuntime / time.Second)
|
||||
|
||||
const (
|
||||
NetworkQualityAccuracyLow = int32(networkquality.AccuracyLow)
|
||||
NetworkQualityAccuracyMedium = int32(networkquality.AccuracyMedium)
|
||||
NetworkQualityAccuracyHigh = int32(networkquality.AccuracyHigh)
|
||||
)
|
||||
|
||||
func ProxyDisplayType(proxyType string) string {
|
||||
return C.ProxyDisplayName(proxyType)
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -43,7 +43,7 @@ require (
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||
github.com/sagernet/sing-tun v0.8.7-0.20260407061419-c15a3c764d88
|
||||
github.com/sagernet/sing-tun v0.8.7-0.20260407152316-3ded9b354c8a
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.7
|
||||
|
||||
4
go.sum
4
go.sum
@@ -248,8 +248,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||
github.com/sagernet/sing-tun v0.8.7-0.20260407061419-c15a3c764d88 h1:jRxRE0nlEWkm4z+1rQxJzp/ji9yZ1FMDqMyV/evMlWA=
|
||||
github.com/sagernet/sing-tun v0.8.7-0.20260407061419-c15a3c764d88/go.mod h1:pLCo4o+LacXEzz0bhwhJkKBjLlKOGPBNOAZ97ZVZWzs=
|
||||
github.com/sagernet/sing-tun v0.8.7-0.20260407152316-3ded9b354c8a h1:L3757AYMq32oOb9iW2j7D/tat7eE7nvnthi7V1rJvwM=
|
||||
github.com/sagernet/sing-tun v0.8.7-0.20260407152316-3ded9b354c8a/go.mod h1:pLCo4o+LacXEzz0bhwhJkKBjLlKOGPBNOAZ97ZVZWzs=
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o=
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478=
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/sagernet/sing/common/json/badoption"
|
||||
"github.com/sagernet/sing/common/x/list"
|
||||
"github.com/sagernet/sing/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ static void stopMemoryPressureMonitor() {
|
||||
import "C"
|
||||
|
||||
import (
|
||||
runtimeDebug "runtime/debug"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -88,6 +89,7 @@ func (s *Service) Close() error {
|
||||
|
||||
//export goMemoryPressureCallback
|
||||
func goMemoryPressureCallback(status C.ulong) {
|
||||
runtimeDebug.FreeOSMemory()
|
||||
globalAccess.Lock()
|
||||
services := make([]*Service, len(globalServices))
|
||||
copy(services, globalServices)
|
||||
|
||||
@@ -107,6 +107,7 @@ type adaptiveTimer struct {
|
||||
access sync.Mutex
|
||||
timer *time.Timer
|
||||
state pressureState
|
||||
currentInterval time.Duration
|
||||
forceMinInterval bool
|
||||
pendingPressureBaseline bool
|
||||
pressureBaseline memorySample
|
||||
@@ -178,7 +179,9 @@ func (t *adaptiveTimer) poll() {
|
||||
t.state = t.nextState(sample)
|
||||
if t.state == pressureStateNormal {
|
||||
t.forceMinInterval = false
|
||||
t.pressureBaselineTime = time.Time{}
|
||||
if !t.pressureBaselineTime.IsZero() && time.Since(t.pressureBaselineTime) > t.maxInterval {
|
||||
t.pressureBaselineTime = time.Time{}
|
||||
}
|
||||
}
|
||||
t.timer.Reset(t.intervalForState())
|
||||
triggered = previousState != pressureStateTriggered && t.state == pressureStateTriggered
|
||||
@@ -272,13 +275,19 @@ func (t *adaptiveTimer) availableThresholds(sample memorySample) pressureThresho
|
||||
}
|
||||
|
||||
func (t *adaptiveTimer) intervalForState() time.Duration {
|
||||
if t.state == pressureStateNormal {
|
||||
return t.maxInterval
|
||||
switch {
|
||||
case t.forceMinInterval || t.state == pressureStateTriggered:
|
||||
t.currentInterval = t.minInterval
|
||||
case t.state == pressureStateArmed:
|
||||
t.currentInterval = t.armedInterval
|
||||
default:
|
||||
if t.currentInterval == 0 {
|
||||
t.currentInterval = t.maxInterval
|
||||
} else {
|
||||
t.currentInterval = min(t.currentInterval*2, t.maxInterval)
|
||||
}
|
||||
}
|
||||
if t.forceMinInterval || t.state == pressureStateTriggered {
|
||||
return t.minInterval
|
||||
}
|
||||
return t.armedInterval
|
||||
return t.currentInterval
|
||||
}
|
||||
|
||||
func (t *adaptiveTimer) logDetails(sample memorySample) string {
|
||||
|
||||
Reference in New Issue
Block a user