|
@@ -14,9 +14,12 @@ from .relay_client import RelayManager
|
|
|
from .transparent_edge import TransparentEdge
|
|
from .transparent_edge import TransparentEdge
|
|
|
|
|
|
|
|
|
|
|
|
|
-WIN_RE = re.compile(
|
|
|
|
|
|
|
+TCP_WIN_RE = re.compile(
|
|
|
r"tcp win session=(?P<session>\d+) target=(?P<host>[^:]+):(?P<port>\d+) winner=(?P<winner>\S+) .*?direct=(?P<direct>\d+) .*?relay=(?P<relay>\d+)"
|
|
r"tcp win session=(?P<session>\d+) target=(?P<host>[^:]+):(?P<port>\d+) winner=(?P<winner>\S+) .*?direct=(?P<direct>\d+) .*?relay=(?P<relay>\d+)"
|
|
|
)
|
|
)
|
|
|
|
|
+UDP_WIN_RE = re.compile(
|
|
|
|
|
+ r"udp flow=(?P<flow>\d+) winner=(?P<winner>\S+) target=(?P<host>[^:]+):(?P<port>\d+)"
|
|
|
|
|
+)
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
@@ -79,47 +82,87 @@ def handle_summary(args: argparse.Namespace) -> int:
|
|
|
if not log_path.exists():
|
|
if not log_path.exists():
|
|
|
raise SystemExit(f"log file not found: {log_path}")
|
|
raise SystemExit(f"log file not found: {log_path}")
|
|
|
|
|
|
|
|
- total = 0
|
|
|
|
|
- direct = 0
|
|
|
|
|
- relay = 0
|
|
|
|
|
- winners: dict[str, int] = defaultdict(int)
|
|
|
|
|
- targets: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
|
|
|
|
|
|
|
+ tcp_total = 0
|
|
|
|
|
+ tcp_direct = 0
|
|
|
|
|
+ tcp_relay = 0
|
|
|
|
|
+ tcp_winners: dict[str, int] = defaultdict(int)
|
|
|
|
|
+ tcp_targets: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
|
|
|
|
|
+
|
|
|
|
|
+ udp_total = 0
|
|
|
|
|
+ udp_direct = 0
|
|
|
|
|
+ udp_relay = 0
|
|
|
|
|
+ udp_winners: dict[str, int] = defaultdict(int)
|
|
|
|
|
+ udp_targets: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
|
|
|
|
|
|
|
|
for line in log_path.read_text(errors="replace").splitlines():
|
|
for line in log_path.read_text(errors="replace").splitlines():
|
|
|
- match = WIN_RE.search(line)
|
|
|
|
|
- if not match:
|
|
|
|
|
|
|
+ tcp_match = TCP_WIN_RE.search(line)
|
|
|
|
|
+ if tcp_match:
|
|
|
|
|
+ tcp_total += 1
|
|
|
|
|
+ winner = tcp_match.group("winner")
|
|
|
|
|
+ host = tcp_match.group("host")
|
|
|
|
|
+ port = tcp_match.group("port")
|
|
|
|
|
+ key = f"{host}:{port}"
|
|
|
|
|
+ tcp_winners[winner] += 1
|
|
|
|
|
+ tcp_targets[key][winner] += 1
|
|
|
|
|
+ if winner == "direct":
|
|
|
|
|
+ tcp_direct += 1
|
|
|
|
|
+ else:
|
|
|
|
|
+ tcp_relay += 1
|
|
|
continue
|
|
continue
|
|
|
- total += 1
|
|
|
|
|
- winner = match.group("winner")
|
|
|
|
|
- host = match.group("host")
|
|
|
|
|
- port = match.group("port")
|
|
|
|
|
- key = f"{host}:{port}"
|
|
|
|
|
- winners[winner] += 1
|
|
|
|
|
- targets[key][winner] += 1
|
|
|
|
|
- if winner == "direct":
|
|
|
|
|
- direct += 1
|
|
|
|
|
- else:
|
|
|
|
|
- relay += 1
|
|
|
|
|
-
|
|
|
|
|
- ordered_targets = sorted(
|
|
|
|
|
- targets.items(),
|
|
|
|
|
|
|
+
|
|
|
|
|
+ udp_match = UDP_WIN_RE.search(line)
|
|
|
|
|
+ if udp_match:
|
|
|
|
|
+ udp_total += 1
|
|
|
|
|
+ winner = udp_match.group("winner")
|
|
|
|
|
+ host = udp_match.group("host")
|
|
|
|
|
+ port = udp_match.group("port")
|
|
|
|
|
+ key = f"{host}:{port}"
|
|
|
|
|
+ udp_winners[winner] += 1
|
|
|
|
|
+ udp_targets[key][winner] += 1
|
|
|
|
|
+ if winner == "direct":
|
|
|
|
|
+ udp_direct += 1
|
|
|
|
|
+ else:
|
|
|
|
|
+ udp_relay += 1
|
|
|
|
|
+
|
|
|
|
|
+ tcp_ordered_targets = sorted(
|
|
|
|
|
+ tcp_targets.items(),
|
|
|
|
|
+ key=lambda item: sum(item[1].values()),
|
|
|
|
|
+ reverse=True,
|
|
|
|
|
+ )[: max(args.top, 0)]
|
|
|
|
|
+ udp_ordered_targets = sorted(
|
|
|
|
|
+ udp_targets.items(),
|
|
|
key=lambda item: sum(item[1].values()),
|
|
key=lambda item: sum(item[1].values()),
|
|
|
reverse=True,
|
|
reverse=True,
|
|
|
)[: max(args.top, 0)]
|
|
)[: max(args.top, 0)]
|
|
|
|
|
|
|
|
result = {
|
|
result = {
|
|
|
"log_file": str(log_path),
|
|
"log_file": str(log_path),
|
|
|
- "total": total,
|
|
|
|
|
- "direct": direct,
|
|
|
|
|
- "relay": relay,
|
|
|
|
|
- "winners": dict(sorted(winners.items(), key=lambda item: (-item[1], item[0]))),
|
|
|
|
|
- "targets": [
|
|
|
|
|
- {
|
|
|
|
|
- "target": target,
|
|
|
|
|
- "wins": dict(sorted(counts.items(), key=lambda item: (-item[1], item[0]))),
|
|
|
|
|
- }
|
|
|
|
|
- for target, counts in ordered_targets
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+ "tcp": {
|
|
|
|
|
+ "total": tcp_total,
|
|
|
|
|
+ "direct": tcp_direct,
|
|
|
|
|
+ "relay": tcp_relay,
|
|
|
|
|
+ "winners": dict(sorted(tcp_winners.items(), key=lambda item: (-item[1], item[0]))),
|
|
|
|
|
+ "targets": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "target": target,
|
|
|
|
|
+ "wins": dict(sorted(counts.items(), key=lambda item: (-item[1], item[0]))),
|
|
|
|
|
+ }
|
|
|
|
|
+ for target, counts in tcp_ordered_targets
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ "udp": {
|
|
|
|
|
+ "total": udp_total,
|
|
|
|
|
+ "direct": udp_direct,
|
|
|
|
|
+ "relay": udp_relay,
|
|
|
|
|
+ "winners": dict(sorted(udp_winners.items(), key=lambda item: (-item[1], item[0]))),
|
|
|
|
|
+ "targets": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "target": target,
|
|
|
|
|
+ "wins": dict(sorted(counts.items(), key=lambda item: (-item[1], item[0]))),
|
|
|
|
|
+ }
|
|
|
|
|
+ for target, counts in udp_ordered_targets
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if args.json:
|
|
if args.json:
|
|
@@ -127,14 +170,16 @@ def handle_summary(args: argparse.Namespace) -> int:
|
|
|
return 0
|
|
return 0
|
|
|
|
|
|
|
|
print(f"log: {log_path}")
|
|
print(f"log: {log_path}")
|
|
|
- print(f"total: {total} direct: {direct} relay: {relay}")
|
|
|
|
|
- print("winners:")
|
|
|
|
|
- for name, count in result["winners"].items():
|
|
|
|
|
- print(f" {name}: {count}")
|
|
|
|
|
- print("targets:")
|
|
|
|
|
- for item in result["targets"]:
|
|
|
|
|
- wins = ", ".join(f"{name}={count}" for name, count in item["wins"].items())
|
|
|
|
|
- print(f" {item['target']}: {wins}")
|
|
|
|
|
|
|
+ for protocol in ("tcp", "udp"):
|
|
|
|
|
+ section = result[protocol]
|
|
|
|
|
+ print(f"{protocol}: total={section['total']} direct={section['direct']} relay={section['relay']}")
|
|
|
|
|
+ print("winners:")
|
|
|
|
|
+ for name, count in section["winners"].items():
|
|
|
|
|
+ print(f" {name}: {count}")
|
|
|
|
|
+ print("targets:")
|
|
|
|
|
+ for item in section["targets"]:
|
|
|
|
|
+ wins = ", ".join(f"{name}={count}" for name, count in item["wins"].items())
|
|
|
|
|
+ print(f" {item['target']}: {wins}")
|
|
|
return 0
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|