From d55b65db1f0d0ff7669856d06478a0aa0ece5012 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Thu, 26 Mar 2026 14:43:20 +0400 Subject: [PATCH] v7: file storage limits - 1MB per file, 50MB total, FIFO eviction Co-Authored-By: Claude Opus 4.6 (1M context) --- chat.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/chat.py b/chat.py index eec502f..fb32f6c 100644 --- a/chat.py +++ b/chat.py @@ -25,16 +25,29 @@ import html import urllib.parse PORT = 9999 -VERSION = "6" +VERSION = "7" TUNNEL_TARGET = ("185.208.174.152", 22) -MAX_UPLOAD = 10 * 1024 * 1024 # 10 MB +MAX_FILE_SIZE = 1 * 1024 * 1024 # 1 MB per file +MAX_TOTAL_STORAGE = 50 * 1024 * 1024 # 50 MB total # ── Server ────────────────────────────────────────────────────────────── clients: dict[asyncio.StreamWriter, str] = {} # TCP clients sse_queues: list[asyncio.Queue] = [] # web clients history: list[dict] = [] -uploaded_files: dict[str, bytes] = {} # file_id -> raw bytes +uploaded_files: dict[str, bytes] = {} # file_id -> raw bytes (insertion order) +total_file_bytes = 0 + + +def store_file(file_id: str, data: bytes): + """Store a file, evicting oldest files if total storage exceeds limit.""" + global total_file_bytes + uploaded_files[file_id] = data + total_file_bytes += len(data) + while total_file_bytes > MAX_TOTAL_STORAGE and uploaded_files: + oldest_id = next(iter(uploaded_files)) + total_file_bytes -= len(uploaded_files.pop(oldest_id)) + async def broadcast(msg: dict): @@ -481,9 +494,9 @@ async def handle_http(reader, writer, first_line): if file_entry and file_entry[0]: filename = file_entry[0] file_data = file_entry[1] - if len(file_data) <= MAX_UPLOAD: + if len(file_data) <= MAX_FILE_SIZE: file_id = hashlib.sha256(file_data + str(time.time()).encode()).hexdigest()[:16] - uploaded_files[file_id] = file_data + store_file(file_id, file_data) await broadcast({ "ts": time.time(), "user": name, "text": f"[file: {filename}]", @@ -577,8 +590,10 @@ async def handle(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): pkt = json.loads(line) if pkt.get("type") == "file": file_data = base64.b64decode(pkt["data"]) + if len(file_data) > MAX_FILE_SIZE: + continue file_id = hashlib.sha256(file_data + str(time.time()).encode()).hexdigest()[:16] - uploaded_files[file_id] = file_data + store_file(file_id, file_data) await broadcast({ "ts": time.time(), "user": name, "text": f"[file: {pkt['filename']}]", @@ -693,8 +708,8 @@ class ChatClient: self.messages.append((f" *** file not found: {filepath}", CP_SYSTEM)) return size = os.path.getsize(filepath) - if size > MAX_UPLOAD: - self.messages.append((f" *** file too large ({size} bytes, max {MAX_UPLOAD})", CP_SYSTEM)) + if size > MAX_FILE_SIZE: + self.messages.append((f" *** file too large ({size} bytes, max {MAX_FILE_SIZE})", CP_SYSTEM)) return with open(filepath, "rb") as f: data = f.read()