Skip to content

Commit

Permalink
new: add singbox
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddify-com committed May 18, 2023
1 parent 2b07b26 commit d8ffc24
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 0 deletions.
1 change: 1 addition & 0 deletions xtlsapi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from xtlsapi.client.XrayClient import XrayClient
from xtlsapi.client.SingboxClient import SingboxClient
import xtlsapi.exceptions
from xtlsapi.ext import utils
11 changes: 11 additions & 0 deletions xtlsapi/client/SingboxClient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from grpc import insecure_channel as grpc_insecure_channel

from xtlsapi.api_services import APIService


class SingboxClient(APIService):
def __init__(self, host, port):
self.host = host
self.port = port
self._channel = grpc_insecure_channel(f'{host}:{port}')
super().__init__()
3 changes: 3 additions & 0 deletions xtlsapi/singbox_api/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
sudo apt install -y protobuf-compiler
protoc ./stats.proto --python_out=./
python3 -m grpc_tools.protoc -I ./ --python_out=./ --grpc_python_out=./ ./stats.proto
53 changes: 53 additions & 0 deletions xtlsapi/singbox_api/stats.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
syntax = "proto3";

package experimental.v2rayapi;
option go_package = "github.com/sagernet/sing-box/experimental/v2rayapi";

message GetStatsRequest {
// Name of the stat counter.
string name = 1;
// Whether or not to reset the counter to fetching its value.
bool reset = 2;
}

message Stat {
string name = 1;
int64 value = 2;
}

message GetStatsResponse {
Stat stat = 1;
}

message QueryStatsRequest {
// Deprecated, use Patterns instead
string pattern = 1;
bool reset = 2;
repeated string patterns = 3;
bool regexp = 4;
}

message QueryStatsResponse {
repeated Stat stat = 1;
}

message SysStatsRequest {}

message SysStatsResponse {
uint32 NumGoroutine = 1;
uint32 NumGC = 2;
uint64 Alloc = 3;
uint64 TotalAlloc = 4;
uint64 Sys = 5;
uint64 Mallocs = 6;
uint64 Frees = 7;
uint64 LiveObjects = 8;
uint64 PauseTotalNs = 9;
uint32 Uptime = 10;
}

service StatsService {
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
}
40 changes: 40 additions & 0 deletions xtlsapi/singbox_api/stats_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions xtlsapi/singbox_api/stats_pb2_grpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

import stats_pb2 as stats__pb2


class StatsServiceStub(object):
"""Missing associated documentation comment in .proto file."""

def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetStats = channel.unary_unary(
'/experimental.v2rayapi.StatsService/GetStats',
request_serializer=stats__pb2.GetStatsRequest.SerializeToString,
response_deserializer=stats__pb2.GetStatsResponse.FromString,
)
self.QueryStats = channel.unary_unary(
'/experimental.v2rayapi.StatsService/QueryStats',
request_serializer=stats__pb2.QueryStatsRequest.SerializeToString,
response_deserializer=stats__pb2.QueryStatsResponse.FromString,
)
self.GetSysStats = channel.unary_unary(
'/experimental.v2rayapi.StatsService/GetSysStats',
request_serializer=stats__pb2.SysStatsRequest.SerializeToString,
response_deserializer=stats__pb2.SysStatsResponse.FromString,
)


class StatsServiceServicer(object):
"""Missing associated documentation comment in .proto file."""

def GetStats(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def QueryStats(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')

def GetSysStats(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')


def add_StatsServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetStats': grpc.unary_unary_rpc_method_handler(
servicer.GetStats,
request_deserializer=stats__pb2.GetStatsRequest.FromString,
response_serializer=stats__pb2.GetStatsResponse.SerializeToString,
),
'QueryStats': grpc.unary_unary_rpc_method_handler(
servicer.QueryStats,
request_deserializer=stats__pb2.QueryStatsRequest.FromString,
response_serializer=stats__pb2.QueryStatsResponse.SerializeToString,
),
'GetSysStats': grpc.unary_unary_rpc_method_handler(
servicer.GetSysStats,
request_deserializer=stats__pb2.SysStatsRequest.FromString,
response_serializer=stats__pb2.SysStatsResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'experimental.v2rayapi.StatsService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))


# This class is part of an EXPERIMENTAL API.
class StatsService(object):
"""Missing associated documentation comment in .proto file."""

@staticmethod
def GetStats(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/experimental.v2rayapi.StatsService/GetStats',
stats__pb2.GetStatsRequest.SerializeToString,
stats__pb2.GetStatsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

@staticmethod
def QueryStats(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/experimental.v2rayapi.StatsService/QueryStats',
stats__pb2.QueryStatsRequest.SerializeToString,
stats__pb2.QueryStatsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

@staticmethod
def GetSysStats(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/experimental.v2rayapi.StatsService/GetSysStats',
stats__pb2.SysStatsRequest.SerializeToString,
stats__pb2.SysStatsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
7 changes: 7 additions & 0 deletions xtlsapi/singbox_api_services/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .stats import StatsAPIService
from .handler import HandlerAPIService
from .logger import LoggerAPIService


class APIService(StatsAPIService):
pass
7 changes: 7 additions & 0 deletions xtlsapi/singbox_api_services/_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from xtlsapi.singbox_api import stats_pb2_grpc



class BaseService:
def __init__(self):
self.stats_stub = stats_pb2_grpc.StatsServiceStub(self._channel)
18 changes: 18 additions & 0 deletions xtlsapi/singbox_api_services/stats/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from .get_client_upload_traffic import GetClientUploadTraffic
from .get_client_download_traffic import GetClientDownloadTraffic
from .get_inbound_upload_traffic import GetInboundUploadTraffic
from .get_inbound_download_traffic import GetInboundDownloadTraffic
from .get_total_upload_traffic import GetTotalUploadTraffic
from .get_total_download_traffic import GetTotalDownloadTraffic
from .get_statsquery import StatsQuery

class StatsAPIService(
GetClientUploadTraffic,
GetClientDownloadTraffic,
GetInboundUploadTraffic,
GetInboundDownloadTraffic,
GetTotalUploadTraffic,
GetTotalDownloadTraffic,
StatsQuery
):
pass
17 changes: 17 additions & 0 deletions xtlsapi/singbox_api_services/stats/get_client_download_traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import grpc
from xtlsapi.singbox_api import stats_pb2

from .._base import BaseService


class GetClientDownloadTraffic(BaseService):
def get_client_download_traffic(self, email, reset=False):
try:
return self.stats_stub.GetStats(
stats_pb2.GetStatsRequest(
name=f"user>>>{email}>>>traffic>>>downlink", reset=reset
)
).stat.value
except grpc.RpcError:
# raise
return None
15 changes: 15 additions & 0 deletions xtlsapi/singbox_api_services/stats/get_client_upload_traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import grpc
from xtlsapi.singbox_api import stats_pb2
from .._base import BaseService


class GetClientUploadTraffic(BaseService):
def get_client_upload_traffic(self, email, reset=False):
try:
return self.stats_stub.GetStats(
stats_pb2.GetStatsRequest(
name=f"user>>>{email}>>>traffic>>>uplink", reset=reset
)
).stat.value
except grpc.RpcError:
return None
16 changes: 16 additions & 0 deletions xtlsapi/singbox_api_services/stats/get_inbound_download_traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import grpc
from xtlsapi.singbox_api import stats_pb2
from .._base import BaseService


class GetInboundDownloadTraffic(BaseService):
def get_inbound_download_traffic(self, tag, reset=False):
try:
return self.stats_stub.GetStats(
stats_pb2.GetStatsRequest(
name=f"inbound>>>{tag}>>>traffic>>>downlink", reset=reset
)
).stat.value
except grpc.RpcError:
# raise
return None
16 changes: 16 additions & 0 deletions xtlsapi/singbox_api_services/stats/get_inbound_upload_traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import grpc
from xtlsapi.singbox_api import stats_pb2
from .._base import BaseService


class GetInboundUploadTraffic(BaseService):
def get_inbound_upload_traffic(self, tag, reset=False):
try:
return self.stats_stub.GetStats(
stats_pb2.GetStatsRequest(
name=f"inbound>>>{tag}>>>traffic>>>uplink", reset=reset
)
).stat.value
except grpc.RpcError:
# raise
return None
17 changes: 17 additions & 0 deletions xtlsapi/singbox_api_services/stats/get_statsquery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import grpc
from xtlsapi.singbox_api import stats_pb2

from .._base import BaseService


class StatsQuery(BaseService):
def stats_query(self, pattern):
try:
return self.stats_stub.QueryStats(
stats_pb2.QueryStatsRequest(
pattern=pattern
)
).stat
except grpc.RpcError:
raise
return None
17 changes: 17 additions & 0 deletions xtlsapi/singbox_api_services/stats/get_total_download_traffic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import grpc
from xtlsapi.singbox_api import stats_pb2
from .._base import BaseService


class GetTotalDownloadTraffic(BaseService):
def get_total_download_traffic(self, reset=False):
raise Exception('Not Implemented')
try:
return self.stats_stub.GetStats(
stats_pb2.GetStatsRequest(
name=f"outbound>>>statout>>>traffic>>>downlink", reset=reset
)
).stat.value
except grpc.RpcError:
# raise
return None
Loading

0 comments on commit d8ffc24

Please sign in to comment.