#!/usr/bin/env python3 """ MongoDBserver. Implements the MongoDB wire protocol OP_MSG/OP_QUERY handshake. Responds to isMaster/hello, listDatabases, and authenticate commands. Logs all received messages as JSON. """ import asyncio import os import struct from decnet_logging import syslog_line, write_syslog_file, forward_syslog NODE_NAME = os.environ.get("NODE_NAME", "mongodb") SERVICE_NAME = "mongodb" LOG_TARGET = os.environ.get("LOG_TARGET", "") # Minimal BSON helpers def _bson_str(key: str, val: str) -> bytes: k = key.encode() + b"\x00" v = val.encode() + b"\x00" return b"\x02" + k + struct.pack(" bytes: return b"\x10" + key.encode() + b"\x00" + struct.pack(" bytes: return b"\x08" + key.encode() + b"\x00" + (b"\x01" if val else b"\x00") def _bson_doc(*fields: bytes) -> bytes: body = b"".join(fields) + b"\x00" return struct.pack(" bytes: # OP_REPLY header: total_len(4), req_id(4), response_to(4), opcode(4)=1, # flags(4), cursor_id(8), starting_from(4), number_returned(4), docs header = struct.pack( " bytes: payload = b"\x00" + doc flag_bits = struct.pack(" None: line = syslog_line(SERVICE_NAME, NODE_NAME, event_type, severity, **kwargs) print(line, flush=True) write_syslog_file(line) forward_syslog(line, LOG_TARGET) class MongoDBProtocol(asyncio.Protocol): def __init__(self): self._transport = None self._peer = None self._buf = b"" def connection_made(self, transport): self._transport = transport self._peer = transport.get_extra_info("peername", ("?", 0)) _log("connect", src=self._peer[0], src_port=self._peer[1]) def data_received(self, data): self._buf += data while len(self._buf) >= 16: msg_len = struct.unpack("