41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
import json
|
|
import struct
|
|
|
|
MAX_MESSAGE = 1024 * 1024
|
|
|
|
|
|
def read_exact(stream, length):
|
|
data = bytearray()
|
|
while len(data) < length:
|
|
chunk = stream.read(length - len(data))
|
|
if not chunk:
|
|
if not data:
|
|
return None
|
|
raise EOFError("Оборвано сообщение native messaging.")
|
|
data.extend(chunk)
|
|
return bytes(data)
|
|
|
|
|
|
def read_message(stream):
|
|
header = read_exact(stream, 4)
|
|
if header is None:
|
|
return None
|
|
size = struct.unpack("<I", header)[0]
|
|
if not 0 < size <= MAX_MESSAGE:
|
|
raise ValueError("Превышен размер сообщения.")
|
|
raw = read_exact(stream, size)
|
|
if raw is None:
|
|
raise EOFError("Отсутствует тело сообщения.")
|
|
message = json.loads(raw.decode("utf-8"))
|
|
if not isinstance(message, dict):
|
|
raise ValueError("Сообщение должно быть объектом.")
|
|
return message
|
|
|
|
|
|
def write_message(stream, message):
|
|
raw = json.dumps(message, ensure_ascii=False, allow_nan=False, separators=(",", ":")).encode("utf-8")
|
|
if len(raw) > MAX_MESSAGE:
|
|
raise ValueError("Ответ слишком большой.")
|
|
stream.write(struct.pack("<I", len(raw)) + raw)
|
|
stream.flush()
|