import ssl
import socket
import threading
import sys

BACKEND_HOST = '127.0.0.1'
BACKEND_PORT = 8002
CERT_FILE = 'cert.crt'
KEY_FILE = 'cert.key'

def pipe(source, destination):
    try:
        while True:
            data = source.recv(16384)
            if not data:
                break
            destination.sendall(data)
    except Exception:
        pass
    finally:
        try:
            source.close()
        except Exception:
            pass
        try:
            destination.close()
        except Exception:
            pass

def handle_client(client_sock, context):
    try:
        # Peek at first byte to detect TLS handshake (0x16 == 22)
        first_byte = client_sock.recv(1, socket.MSG_PEEK)
        if first_byte == b'\x16':
            client_sock = context.wrap_socket(client_sock, server_side=True)

        backend_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        backend_sock.connect((BACKEND_HOST, BACKEND_PORT))

        t1 = threading.Thread(target=pipe, args=(client_sock, backend_sock), daemon=True)
        t2 = threading.Thread(target=pipe, args=(backend_sock, client_sock), daemon=True)
        t1.start()
        t2.start()
    except Exception as e:
        try:
            client_sock.close()
        except Exception:
            pass

def serve_port(port, context):
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        server.bind(('0.0.0.0', port))
    except Exception as e:
        print(f"❌ Failed to bind to 0.0.0.0:{port}: {e}", flush=True)
        return
    server.listen(128)
    print(f"🚀 Hybrid HTTP/HTTPS Server listening on 0.0.0.0:{port} -> backend {BACKEND_PORT}", flush=True)
    while True:
        try:
            client, _ = server.accept()
            t = threading.Thread(target=handle_client, args=(client, context), daemon=True)
            t.start()
        except Exception:
            pass

def main():
    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)

    # Listen on port 5000 (supports both HTTP and HTTPS)
    t_5000 = threading.Thread(target=serve_port, args=(5000, context), daemon=True)
    t_5000.start()
    t_5000.join()

if __name__ == '__main__':
    main()
