from flask import Flask, render_template from flask_socketio import SocketIO, emit import ssl import os app = Flask(__name__, static_folder='static', template_folder='templates') app.config['SECRET_KEY'] = 'your-secret-key-change-this-in-production' socketio = SocketIO(app, cors_allowed_origins="*") # Store connected clients with their usernames connected_clients = {} # Format: {session_id: {'username': 'name', 'connected_at': timestamp}} @app.route('/') def index(): return render_template('index.html') @socketio.on('connect') def handle_connect(auth): from flask import request print(f'Client connected: {request.sid}') # type: ignore connected_clients[request.sid] = {'username': None, 'connected_at': None} # type: ignore @socketio.on('disconnect') def handle_disconnect(): from flask import request print(f'Client disconnected: {request.sid}') # type: ignore if request.sid in connected_clients: # type: ignore del connected_clients[request.sid] # type: ignore # Notify other clients about disconnection emit('user_disconnected', {'id': request.sid}, broadcast=True, include_self=False) # type: ignore @socketio.on('offer') def handle_offer(data): from flask import request print(f'Received offer from {request.sid}') # type: ignore # Broadcast offer to all other clients data['id'] = request.sid # type: ignore emit('offer', data, broadcast=True, include_self=False) @socketio.on('answer') def handle_answer(data): from flask import request print(f'Received answer from {request.sid}') # type: ignore # Send answer to specific client emit('answer', data, to=data['id']) @socketio.on('ice_candidate') def handle_ice_candidate(data): from flask import request print(f'Received ICE candidate from {request.sid}') # type: ignore # Broadcast ICE candidate to all other clients or specific client if 'target_id' in data: emit('ice_candidate', data, to=data['target_id']) else: emit('ice_candidate', data, broadcast=True, include_self=False) @socketio.on('join_room') def handle_join_room(data=None): from flask import request username = data.get('username', 'Anonymous') if data else 'Anonymous' print(f'Client {request.sid} ({username}) joining room') # type: ignore # Update client info with username if request.sid in connected_clients: # type: ignore connected_clients[request.sid]['username'] = username # type: ignore connected_clients[request.sid]['connected_at'] = __import__('time').time() # type: ignore # Get list of existing users with usernames (excluding the new user) existing_users = [] for user_id, user_info in connected_clients.items(): if user_id != request.sid and user_info['username']: # type: ignore existing_users.append({ 'id': user_id, 'username': user_info['username'] }) # Send existing users list to the new user if existing_users: emit('existing_users', {'users': existing_users}) # Notify existing clients about new user emit('user_joined', { 'id': request.sid, # type: ignore 'username': username }, broadcast=True, include_self=False) if __name__ == '__main__': # Set up SSL context context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain('cert.pem', 'key.pem') print("Starting Flask-SocketIO server on https://localhost:3000") socketio.run(app, host='localhost', port=3000, ssl_context=context, debug=True)