mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
refactor: 移除 Python 后端源码,全面迁移至 Rust gateway 架构
- 删除全部 Python 源码 (src/) 及 Alembic 迁移脚本,归档至 _deprecated_py_src/ - 重构 Rust gateway ai_pipeline: 拆分 planner/finalize 模块,新增 contracts/adaptation 层 - 重组 handlers 模块为 admin/public/proxy/internal/shared 子模块结构 - 新增 executor 模块,引入 Rust 原生数据库迁移 (aether-data/migrations) - 简化 CI/Docker 构建流程,移除 base image 二级构建,统一为单一 app image - 移除 Python 相关基础设施文件 (entrypoint.sh, gunicorn_conf.py, Dockerfile.base)
This commit is contained in:
124
_deprecated_py_src/services/proxy_node/tunnel_protocol.py
Normal file
124
_deprecated_py_src/services/proxy_node/tunnel_protocol.py
Normal file
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
WebSocket \u96a7\u9053\u4e8c\u8fdb\u5236\u5e27\u534f\u8bae
|
||||
|
||||
\u5e27\u683c\u5f0f:
|
||||
| stream_id (4B) | msg_type (1B) | flags (1B) | payload_len (4B) | payload (NB) |
|
||||
|
||||
\u7528\u4e8e Aether \u4e0e aether-proxy \u4e4b\u95f4\u7684 WebSocket \u96a7\u9053\u591a\u8def\u590d\u7528\u901a\u4fe1\u3002
|
||||
"""
|
||||
|
||||
import struct
|
||||
from enum import IntEnum
|
||||
from typing import Self
|
||||
|
||||
_U64_MAX = (1 << 64) - 1
|
||||
|
||||
HEADER_SIZE = 10 # 4 + 1 + 1 + 4 bytes
|
||||
|
||||
|
||||
class MsgType(IntEnum):
|
||||
"""\u6d88\u606f\u7c7b\u578b"""
|
||||
|
||||
REQUEST_HEADERS = 0x01 # Aether -> Proxy: \u8bf7\u6c42\u5143\u6570\u636e (JSON)
|
||||
REQUEST_BODY = 0x02 # Aether -> Proxy: \u8bf7\u6c42\u4f53
|
||||
RESPONSE_HEADERS = 0x03 # Proxy -> Aether: \u54cd\u5e94\u72b6\u6001\u7801 + headers (JSON)
|
||||
RESPONSE_BODY = 0x04 # Proxy -> Aether: \u54cd\u5e94\u4f53\uff08\u6d41\u5f0f\u5206\u5757\uff09
|
||||
STREAM_END = 0x05 # \u53cc\u5411: \u6d41\u7ed3\u675f
|
||||
STREAM_ERROR = 0x06 # \u53cc\u5411: \u6d41\u9519\u8bef
|
||||
|
||||
PING = 0x10 # \u53cc\u5411: \u5fc3\u8df3 (stream_id=0)
|
||||
PONG = 0x11 # \u53cc\u5411: \u5fc3\u8df3\u54cd\u5e94 (stream_id=0)
|
||||
GOAWAY = 0x12 # \u53cc\u5411: \u4f18\u96c5\u5173\u95ed (stream_id=0)
|
||||
HEARTBEAT_DATA = 0x13 # Proxy -> Aether: \u6307\u6807\u4e0a\u62a5
|
||||
HEARTBEAT_ACK = 0x14 # Aether -> Proxy: \u5fc3\u8df3\u786e\u8ba4 + \u8fdc\u7a0b\u914d\u7f6e
|
||||
NODE_STATUS = 0x15 # Tunnel relay -> Worker: \u8282\u70b9\u8fde\u63a5\u72b6\u6001\u5e7f\u64ad
|
||||
|
||||
|
||||
class FrameFlags:
|
||||
"""\u5e27\u6807\u5fd7\u4f4d"""
|
||||
|
||||
END_STREAM = 0x01
|
||||
GZIP_COMPRESSED = 0x02
|
||||
|
||||
|
||||
class Frame:
|
||||
"""WebSocket \u96a7\u9053\u5e27"""
|
||||
|
||||
__slots__ = ("stream_id", "msg_type", "flags", "payload")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
stream_id: int,
|
||||
msg_type: MsgType,
|
||||
flags: int = 0,
|
||||
payload: bytes = b"",
|
||||
) -> None:
|
||||
self.stream_id = stream_id
|
||||
self.msg_type = msg_type
|
||||
self.flags = flags
|
||||
self.payload = payload
|
||||
|
||||
def encode(self) -> bytes:
|
||||
header = struct.pack(
|
||||
"!IBBI",
|
||||
self.stream_id,
|
||||
self.msg_type,
|
||||
self.flags,
|
||||
len(self.payload),
|
||||
)
|
||||
return header + self.payload
|
||||
|
||||
@classmethod
|
||||
def decode(cls, data: bytes) -> Self:
|
||||
if len(data) < HEADER_SIZE:
|
||||
raise ValueError(
|
||||
f"\u5e27\u6570\u636e\u592a\u77ed: \u9700\u8981 {HEADER_SIZE} \u5b57\u8282, \u5b9e\u9645 {len(data)}"
|
||||
)
|
||||
stream_id, msg_type_raw, flags, payload_len = struct.unpack("!IBBI", data[:HEADER_SIZE])
|
||||
expected_total = HEADER_SIZE + payload_len
|
||||
if len(data) < expected_total:
|
||||
raise ValueError(
|
||||
f"\u5e27\u6570\u636e\u4e0d\u5b8c\u6574: \u9700\u8981 {expected_total} \u5b57\u8282, \u5b9e\u9645 {len(data)}"
|
||||
)
|
||||
try:
|
||||
msg_type = MsgType(msg_type_raw)
|
||||
except ValueError:
|
||||
raise ValueError(f"\u672a\u77e5\u6d88\u606f\u7c7b\u578b: 0x{msg_type_raw:02x}")
|
||||
payload = data[HEADER_SIZE:expected_total]
|
||||
return cls(stream_id, msg_type, flags, payload)
|
||||
|
||||
@property
|
||||
def is_end_stream(self) -> bool:
|
||||
return bool(self.flags & FrameFlags.END_STREAM)
|
||||
|
||||
@property
|
||||
def is_gzip(self) -> bool:
|
||||
return bool(self.flags & FrameFlags.GZIP_COMPRESSED)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"Frame(stream={self.stream_id}, type={self.msg_type.name}, "
|
||||
f"flags=0x{self.flags:02x}, payload_len={len(self.payload)})"
|
||||
)
|
||||
|
||||
|
||||
def normalize_heartbeat_id(value: object) -> int | None:
|
||||
"""Normalize heartbeat_id to u64-compatible int for Rust ACK parsing."""
|
||||
if isinstance(value, bool) or value is None:
|
||||
return None
|
||||
parsed: int | None = None
|
||||
if isinstance(value, int):
|
||||
parsed = value
|
||||
elif isinstance(value, float):
|
||||
if value.is_integer():
|
||||
parsed = int(value)
|
||||
elif isinstance(value, str):
|
||||
stripped = value.strip()
|
||||
if stripped.isdigit():
|
||||
try:
|
||||
parsed = int(stripped)
|
||||
except ValueError:
|
||||
parsed = None
|
||||
if parsed is None or parsed < 0 or parsed > _U64_MAX:
|
||||
return None
|
||||
return parsed
|
||||
Reference in New Issue
Block a user