Initial commit
This commit is contained in:
155
DimyServer.py
Normal file
155
DimyServer.py
Normal file
@@ -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()
|
||||
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@@ -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" ]
|
||||
6
requirements.txt
Normal file
6
requirements.txt
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user