commit 679a52e6cc8f31debbaf1748d43202be74fc5a4e Author: Pepsi Date: Mon Apr 21 10:08:18 2025 +0000 Initial commit diff --git a/DimyServer.py b/DimyServer.py new file mode 100644 index 0000000..541c7a2 --- /dev/null +++ b/DimyServer.py @@ -0,0 +1,155 @@ +# DimyServer.py - Backend server for DIMY protocol + +import socket +import threading +import http.server +import json +from pybloom_live import BloomFilter +from http.server import BaseHTTPRequestHandler, HTTPServer +import pickle +import os + +CBF_STORAGE = [] # Stores tuples of (client_id, CBF) uploaded by diagnosed users +TCP_PORT = 55000 # For QBF queries +HTTP_PORT = 8000 # For CBF uploads + +if os.getenv("DIMY_SERVER_TCP_PORT"): + TCP_PORT = int(os.getenv("DIMY_SERVER_TCP_PORT")) + print(f"[ENV] Using TCP port from environment: {TCP_PORT}") + +class CBFUploadHandler(BaseHTTPRequestHandler): + def do_POST(self): + print(f"[HTTP] Incoming POST to {self.path}") + + if self.path == '/upload_cbf': + content_length = int(self.headers['Content-Length']) + post_data = self.rfile.read(content_length) + + try: + data = json.loads(post_data) + cbf_hex = data.get("cbf") + + # Debug:show preview of received CBF data + print(f"[DEBUG] Received CBF hex: {cbf_hex[:60]}...") + + cbf_bytes = bytes.fromhex(cbf_hex) + cbf = pickle.loads(cbf_bytes) + client_id = data.get("client_id", "unknown") + + CBF_STORAGE.append((client_id, cbf)) + print(f"[HTTP] CBF uploaded and stored. It contains approx. {cbf.count} items") + if hasattr(cbf, 'bitarray'): + print("[CBF DEBUG] Bitarray size:", len(cbf.bitarray)) + + self.send_response(200) + self.end_headers() + self.wfile.write(b"CBF upload successful") + except Exception as e: + print(f"[UPLOAD ERROR] {e}") + self.send_response(400) + self.end_headers() + self.wfile.write(f"Error: {str(e)}".encode()) + + +def start_http_server(): + server = HTTPServer(("", HTTP_PORT), CBFUploadHandler) + print(f"[HTTP] CBF upload server running on port {HTTP_PORT}...") + server.serve_forever() + + +def handle_client_connection(client_socket): + try: + qbf_data = b"" + while True: + part = client_socket.recv(4096) + if not part: + break + qbf_data += part + + payload = pickle.loads(qbf_data) + qbf = pickle.loads(bytes.fromhex(payload["qbf"])) + encids = payload.get("encids", []) + client_id = payload.get("client_id", "unknown") + print("\n" + "/" * 30 + f" CLIENT {client_id[:8]} " + "/" * 30 + "\n") + + + print(f"[DEBUG] Received {len(qbf_data)} bytes of QBF data") + print("[DEBUG] QBF deserialized successfully") + print("[DEBUG] QBF received — count not available due to pybloom serialization") + + # Dump content-like preview if known (optional and not guaranteed accurate) + if hasattr(qbf, 'bitarray'): + print("[QBF DEBUG] Bitarray size:", len(qbf.bitarray)) + + if not CBF_STORAGE: + print("[DEBUG] No CBFs stored yet — auto 'not matched'") + else: + for i, (cbf_owner, cbf) in enumerate(CBF_STORAGE): + print(f"[DEBUG] CBF {i} contains approx. {cbf.count} items") + if hasattr(cbf, 'bitarray'): + print(f"[CBF {i} DEBUG] Bitarray size:", len(cbf.bitarray)) + if cbf_owner == client_id: + print(f"[DEBUG] Skipping self CBF {i} (client_id match)") + continue + print("[MATCH DEBUG] Checking EncIDs in QBF against CBF:") + for encid in encids: + print(f" → Checking {encid[:8]}...", end="") + try: + if encid.encode() in cbf: + print(" ✅ FOUND") + else: + print(" ❌ NOT FOUND") + except Exception as e: + print(f" [ERROR] {e}") + + matched = False + for i, (cbf_owner, cbf) in enumerate(CBF_STORAGE): + if cbf_owner == client_id: + continue + hit = any(encid.encode() in cbf for encid in encids) + if hit: + print(f"[MATCH DEBUG] QBF ∩ CBF {i}: match found ✅") + matched = True + else: + print(f"[MATCH DEBUG] QBF ∩ CBF {i}: no match ❌") + + response = b"matched" if matched else b"not matched" + if response == b"matched": + print("🔴 [MATCH] Match result: matched") + else: + print("✅ [MATCH] Match result: not matched") + + client_socket.sendall(response) + print(f"[TCP] Sent response: {response.decode()}") + print("\n" + "=" * 70 + "\n") + + + except Exception as inner_e: + print(f"[MATCH ERROR] {inner_e}") + client_socket.sendall(b"error") + + except Exception as e: + print(f"[TCP ERROR] {e}") + finally: + client_socket.close() + + +def start_tcp_server(): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind(("", TCP_PORT)) + server_socket.listen() + print(f"[TCP] Query server running on port {TCP_PORT}...") + + while True: + client_sock, addr = server_socket.accept() + print(f"[TCP] Connection from {addr}") + threading.Thread(target=handle_client_connection, args=(client_sock,), daemon=True).start() + + +def main(): + threading.Thread(target=start_http_server, daemon=True).start() + start_tcp_server() + + +if __name__ == '__main__': + main() diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d0a20c0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.13-alpine + +WORKDIR /usr/src/app + +COPY requirements.txt ./ + +RUN pip install --no-cache-dir -r requirements.txt + +COPY DimyServer.py . + +RUN rm requirements.txt + +EXPOSE 55000 +EXPOSE 8000 + +ENV DIMY_SERVER_TCP_PORT=55000 \ + DIMY_SERVER_HTTP_PORT=8000 + +CMD [ "python" , "./DimyServer.py" ] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..35fe3dc --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +bitarray==3.3.1 +cffi==1.17.1 +cryptography==44.0.2 +pybloom_live==4.0.0 +pycparser==2.22 +xxhash==3.5.0