fix(traffic): keep client accounting independent of outbound counters

The traffic poll read every Xray counter in one QueryStats reply under
gRPC's default 4 MiB receive limit; past it the whole poll failed and
no client was counted, so quotas stopped being enforced. Outbound
counters carry tags derived from third-party link remarks, so one long
remark was enough.

Poll the user, inbound and outbound families separately with a 64 MiB
limit, keep counting the families that answer, and cap a subscription
link's slug at 64 runes so the tag stays small to begin with.
This commit is contained in:
MHSanaei
2026-10-31 08:46:13 +00:00
parent 61ee202750
commit 3cdb7e2b49
4 changed files with 123 additions and 32 deletions
+6
View File
@@ -1255,6 +1255,8 @@ func base64DecodeFlexible(s string) (string, error) {
// replacing every other run of characters with a single dash.
var slugRe = regexp.MustCompile(`[^\p{L}\p{N}]+`)
const maxSlugRunes = 64
func SlugRemark(remark string) string {
s := strings.ToLower(strings.TrimSpace(remark))
s = slugRe.ReplaceAllString(s, "-")
@@ -1266,6 +1268,10 @@ func SlugRemark(remark string) string {
for strings.Contains(s, "--") {
s = strings.ReplaceAll(s, "--", "-")
}
// The tag names Xray counters, a traffic row and the config; a link author picks the remark.
if r := []rune(s); len(r) > maxSlugRunes {
s = strings.TrimRight(string(r[:maxSlugRunes]), "-")
}
return s
}
+4
View File
@@ -533,6 +533,10 @@ func TestSlugAndSuggest(t *testing.T) {
if got := SuggestTag("ru-", "Сервер 2", 0); got != "ru-сервер-2" {
t.Errorf("unicode suggest tag got %q", got)
}
// The tag names Xray counters and an outbound_traffics row; a provider picks the remark.
if got := SlugRemark(strings.Repeat("Ab ", 1<<20)); got != strings.Repeat("ab-", 21)+"a" {
t.Errorf("megabyte remark slug = %.80q (%d bytes), want the first 64 runes", got, len(got))
}
}
// The obfs-local plugin the panel exports carries the only description of