protocol.py 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. from __future__ import annotations
  2. import json
  3. import struct
  4. from dataclasses import dataclass
  5. from typing import Any
  6. HEADER = struct.Struct("!BIIQII")
  7. AUTH = 1
  8. TCP_OPEN = 2
  9. TCP_STATUS = 3
  10. TCP_DATA = 4
  11. TCP_CLOSE = 5
  12. UDP_SEND = 6
  13. UDP_RECV = 7
  14. PING = 8
  15. PONG = 9
  16. STATUS_OK = 0
  17. STATUS_ERR = 1
  18. @dataclass
  19. class Frame:
  20. kind: int
  21. session_id: int
  22. stream_id: int
  23. seq: int
  24. packet_id: int
  25. payload: bytes = b""
  26. def encode_json(data: Any) -> bytes:
  27. return json.dumps(data, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
  28. def decode_json(data: bytes) -> Any:
  29. return json.loads(data.decode("utf-8"))
  30. async def write_frame(writer, frame: Frame) -> None:
  31. writer.write(HEADER.pack(frame.kind, frame.session_id, frame.stream_id, frame.seq, frame.packet_id, len(frame.payload)))
  32. if frame.payload:
  33. writer.write(frame.payload)
  34. await writer.drain()
  35. async def read_frame(reader) -> Frame:
  36. header = await reader.readexactly(HEADER.size)
  37. kind, session_id, stream_id, seq, packet_id, length = HEADER.unpack(header)
  38. payload = await reader.readexactly(length) if length else b""
  39. return Frame(kind=kind, session_id=session_id, stream_id=stream_id, seq=seq, packet_id=packet_id, payload=payload)