#!/usr/bin/env python3 """ Configuration uWSGI pour l'intégration des WebSockets avec OEDB """ import os import sys import json import time import asyncio from oedb.utils.logging import logger # Import l'application Falcon principale sys.path.insert(0, os.path.dirname(__file__)) from backend import app # Import le gestionnaire WebSocket from oedb.resources.demo.websocket import WebSocketManager # Créer une instance du gestionnaire WebSocket ws_manager = WebSocketManager() # Gestionnaire de WebSocket pour uWSGI def websocket_handler(environ, start_response): """Gestionnaire pour les connexions WebSocket.""" path = environ.get('PATH_INFO', '') # Vérifier si c'est une requête WebSocket et qu'elle est sur le bon chemin if path == '/ws' and environ.get('HTTP_UPGRADE', '').lower() == 'websocket': try: # Importer uwsgi ici car il n'est disponible qu'à l'exécution dans l'environnement uWSGI import uwsgi # Passer la requête au gestionnaire de WebSocket uWSGI uwsgi.websocket_handshake() logger.info(f"Nouvelle connexion WebSocket établie") client_id = id(environ) # Simuler la fonction handle_connection pour ce client try: # Ajouter le client à la liste with ws_manager.lock: ws_manager.clients[client_id] = { 'websocket': environ, # Utiliser environ comme proxy 'username': None, 'position': None, 'last_seen': time.time(), 'show_only_to_friends': False, } # Envoyer la liste des utilisateurs connectés users_list = [] with ws_manager.lock: for client_info in ws_manager.clients.values(): if client_info.get('username'): users_list.append({ 'username': client_info['username'], 'timestamp': time.time() }) # Envoyer la liste des utilisateurs uwsgi.websocket_send(json.dumps({ 'type': 'users', 'users': users_list }).encode('utf-8')) # Boucle de traitement des messages while True: msg = uwsgi.websocket_recv() data = json.loads(msg.decode('utf-8')) message_type = data.get('type') if message_type == 'position': # Traiter la mise à jour de position username = data.get('username') position = data.get('position') timestamp = data.get('timestamp') show_only_to_friends = data.get('showOnlyToFriends', False) # Mettre à jour les informations du client with ws_manager.lock: if client_id in ws_manager.clients: ws_manager.clients[client_id]['username'] = username ws_manager.clients[client_id]['position'] = position ws_manager.clients[client_id]['last_seen'] = time.time() ws_manager.clients[client_id]['show_only_to_friends'] = show_only_to_friends # Mettre à jour dans le dictionnaire des positions ws_manager.positions[username] = { 'position': position, 'timestamp': timestamp, 'show_only_to_friends': show_only_to_friends } # Diffuser à tous les autres clients broadcast_position(username, position, timestamp, show_only_to_friends) elif message_type in ['pouet', 'friendRequest']: # Rediriger ces messages vers les destinataires handle_direct_message(data, message_type) except Exception as e: logger.error(f"Erreur WebSocket: {e}") finally: # Supprimer le client de la liste with ws_manager.lock: if client_id in ws_manager.clients: username = ws_manager.clients[client_id].get('username') if username and username in ws_manager.positions: del ws_manager.positions[username] del ws_manager.clients[client_id] except Exception as e: logger.error(f"Erreur de connexion WebSocket: {e}") return ['500 Internal Server Error', [], [b'WebSocket Error']] # Si ce n'est pas une requête WebSocket, passer à l'application WSGI return app(environ, start_response) # Fonctions utilitaires pour les WebSockets uWSGI def broadcast_position(username, position, timestamp, show_only_to_friends): """Diffuse la position d'un utilisateur à tous les autres utilisateurs.""" import uwsgi message = json.dumps({ 'type': 'position', 'username': username, 'position': position, 'timestamp': timestamp, 'showOnlyToFriends': show_only_to_friends }).encode('utf-8') with ws_manager.lock: for client_id, client_info in ws_manager.clients.items(): # Ne pas envoyer à l'utilisateur lui-même if client_info.get('username') == username: continue try: # Dans uWSGI, nous devons utiliser environ pour identifier le socket if 'websocket' in client_info: uwsgi.websocket_send(message) except Exception as e: logger.error(f"Erreur d'envoi de broadcast de position: {e}") def handle_direct_message(data, message_type): """Traite un message direct (pouet ou demande d'ami).""" import uwsgi from_user = data.get('from') to_user = data.get('to') if not from_user or not to_user: return # Trouver le client destinataire recipient_client_id = None with ws_manager.lock: for client_id, client_info in ws_manager.clients.items(): if client_info.get('username') == to_user: recipient_client_id = client_id break if recipient_client_id and recipient_client_id in ws_manager.clients: # Préparer le message selon le type if message_type == 'pouet': msg = json.dumps({ 'type': 'pouet', 'from': from_user, 'timestamp': data.get('timestamp') }).encode('utf-8') logger.info(f"Pouet pouet envoyé de {from_user} à {to_user}") elif message_type == 'friendRequest': msg = json.dumps({ 'type': 'friendRequest', 'from': from_user, 'timestamp': data.get('timestamp') }).encode('utf-8') logger.info(f"Demande d'ami envoyée de {from_user} à {to_user}") # Envoyer le message try: uwsgi.websocket_send(msg) except Exception as e: logger.error(f"Erreur d'envoi de message direct: {e}") # Appliquer le patch au démarrage patch_websocket_manager() # Application WSGI pour uWSGI application = websocket_handler # Remarque: Pour utiliser ce fichier, démarrez uWSGI avec: # uwsgi --http :8080 --http-websockets --wsgi-file wsgi_websocket.py --async 100 --ugreen