T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.quebec/private_html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.quebec/private_html/server-https.js
// Load environment variables from appropriate file
const envFile = process.env.NODE_ENV === 'production' ? '.env.production' : '.env.local';
require('dotenv').config({ path: envFile });

// Workaround for Next.js 15.3.3 Watchpack issue
process.env.NODE_ENV = process.env.NODE_ENV || 'development';

const { createServer } = require('https');
const { createServer: createHttpServer } = require('http');
const { parse } = require('url');
const fs = require('fs');
const path = require('path');
const next = require('next');
const WebSocket = require('ws');
const os = require('os');

const dev = process.env.NODE_ENV !== 'production';
const hostname = process.env.HOSTNAME || '0.0.0.0'; // Allow network access
const port = process.env.PORT || 3000;
const httpsPort = process.env.HTTPS_PORT || 3443;

// Global variables for WebSocket management
global.wsClients = new Map();
global.wsRoomSubscriptions = new Map();
global.wsUserPresence = new Map();

// Helper function to get network IP
const getNetworkIP = () => {
  const interfaces = os.networkInterfaces();
  for (const name of Object.keys(interfaces)) {
    for (const iface of interfaces[name]) {
      if (iface.family === 'IPv4' && !iface.internal) {
        return iface.address;
      }
    }
  }
  return '15.235.50.60';
};

// HTTPS configuration
const getHttpsOptions = () => {
  try {
    // Try network certificates first (supports IP addresses)
    const networkKeyPath = path.join(__dirname, 'certificates', 'network-key.pem');
    const networkCertPath = path.join(__dirname, 'certificates', 'network-cert.pem');
    
    if (fs.existsSync(networkKeyPath) && fs.existsSync(networkCertPath)) {
      console.log('🌐 Using network certificates (supports IP addresses)');
      return {
        key: fs.readFileSync(networkKeyPath),
        cert: fs.readFileSync(networkCertPath)
      };
    }
    
    // Fallback to localhost certificates
    const keyPath = path.join(__dirname, 'certificates', 'localhost-key.pem');
    const certPath = path.join(__dirname, 'certificates', 'localhost.pem');
    
    if (fs.existsSync(keyPath) && fs.existsSync(certPath)) {
      console.log('🏠 Using localhost certificates (localhost only)');
      return {
        key: fs.readFileSync(keyPath),
        cert: fs.readFileSync(certPath)
      };
    }
  } catch (error) {
    console.warn('Could not load HTTPS certificates:', error.message);
  }
  return null;
};

// Workaround for Next.js 15.3.3 Watchpack issue
const app = next({ 
  dev, 
  hostname, 
  port,
  // Add custom webpack config to avoid Watchpack issues
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.watchOptions = {
        poll: 1000,
        aggregateTimeout: 300,
      };
    }
    return config;
  }
});
const handle = app.getRequestHandler();

function initializeWebSocketServer(server) {
  // Prevent multiple instances of the WebSocket server in development
  if (global.wsServer) {
    console.log('WebSocket server is already running.');
    return;
  }

  const wss = new WebSocket.Server({ noServer: true });
  global.wsServer = wss;

  const clients = global.wsClients;
  const roomSubscriptions = global.wsRoomSubscriptions;
  const userPresence = global.wsUserPresence;
  
  // Make clients accessible globally for debug endpoints
  global.wsClients = clients;

  /**
   * Broadcasts the updated list of participants to everyone in a room.
   * @param {string} roomId The ID of the room.
   */
  const broadcastParticipantList = (roomId) => {
    const participants = [];
    if (roomSubscriptions.has(roomId)) {
      for (const ws of roomSubscriptions.get(roomId)) {
        const clientInfo = clients.get(ws);
        if (clientInfo) {
          // Avoid adding duplicates if a user has multiple connections
          if (!participants.some(p => p.id === clientInfo.user.id)) {
            participants.push(clientInfo.user);
          }
        }
      }
    }
    
    const message = JSON.stringify({
      type: 'PARTICIPANT_LIST_UPDATE',
      data: { roomId, participants },
    });

    if (roomSubscriptions.has(roomId)) {
      roomSubscriptions.get(roomId).forEach(ws => ws.send(message));
    }
  };

  // Handle server upgrade requests to switch to WebSocket protocol
  server.on('upgrade', (request, socket, head) => {
    const { pathname } = parse(request.url, true);
    const clientIP = request.socket.remoteAddress;
    const origin = request.headers.origin;
    
    console.log(`[${new Date().toISOString()}] 🔌 WebSocket upgrade request from ${clientIP} to ${pathname}`);
    
    if (pathname === '/_ws') {
      // SECURITY: Origin validation to prevent Cross-Site WebSocket Hijacking (CSWH)
      const allowedOrigins = [
        'https://15.235.50.60:3443',
        'https://127.0.0.1:3443',
        'https://10.119.255.188:3443',
        'http://15.235.50.60:3000',
        'http://127.0.0.1:3000',
        'http://10.119.255.188:3000'
      ];
      
      if (origin && !allowedOrigins.includes(origin)) {
        console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Rejecting WebSocket from unauthorized origin: ${origin}`);
        socket.destroy();
        return;
      }
      
      console.log(`[${new Date().toISOString()}] ✅ Accepting WebSocket upgrade for /_ws from ${clientIP} (Origin: ${origin || 'none'})`);
      wss.handleUpgrade(request, socket, head, (ws) => {
        wss.emit('connection', ws, request);
      });
    } else if (pathname === '/_next/webpack-hmr') {
      console.log(`[${new Date().toISOString()}] ✅ Allowing Next.js HMR WebSocket from ${clientIP}`);
      // Allow Next.js HMR WebSocket connections
      return;
    } else {
      console.log(`[${new Date().toISOString()}] ❌ Rejecting WebSocket upgrade for unknown path: ${pathname} from ${clientIP}`);
      socket.destroy();
    }
  });

  wss.on('connection', (ws, req) => {
    const url = new URL(req.url, `http://${req.headers.host}`);
    
    // SECURITY: Support both new token format and legacy format during transition
    const token = url.searchParams.get('token');
    const legacyUserId = url.searchParams.get('userId');
    const legacyUser = url.searchParams.get('user');
    const legacyConnId = url.searchParams.get('connId');
    
    let userId, user, connId;
    
    if (token) {
      // NEW SECURE TOKEN FORMAT
      try {
        const decoded = JSON.parse(Buffer.from(token, 'base64').toString());
        userId = decoded.userId;
        connId = decoded.connId || 'unknown';
        user = {
          id: decoded.userId,
          name: decoded.name,
        };
        
        // SECURITY: Token age validation (prevent replay attacks)
        const tokenAge = Date.now() - decoded.timestamp;
        if (tokenAge > 300000) { // 5 minutes max token age
          console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Token expired (age: ${tokenAge}ms)`);
          ws.close(1008, 'Token expired');
          return;
        }
        
        console.log(`[${new Date().toISOString()}] ✅ Secure token authentication for user: ${user.name} (${userId}) [${connId}]`);
        
      } catch (error) {
        console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Invalid token format:`, error.message);
        ws.close(1008, 'Invalid token format');
        return;
      }
    } else if (legacyUserId && legacyUser) {
      // LEGACY FORMAT (temporarily supported for transition)
      try {
        userId = legacyUserId;
        user = JSON.parse(decodeURIComponent(legacyUser));
        connId = legacyConnId || 'unknown';
        
        console.log(`[${new Date().toISOString()}] ⚠️ LEGACY: Using legacy authentication for user: ${user.name} (${userId}) [${connId}]`);
        
      } catch (error) {
        console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Invalid legacy user format:`, error.message);
        ws.close(1008, 'Invalid user data');
        return;
      }
    } else {
      console.log(`[${new Date().toISOString()}] 🚨 SECURITY: No authentication provided`);
      ws.close(1008, 'Authentication required');
      return;
    }

    if (!userId || !user.id) {
      console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Connection rejected - invalid user data in token`);
      ws.close(1008, 'Invalid user data');
      return;
    }
    
    console.log(`[${new Date().toISOString()}] ✅ WebSocket connection established for user: ${user.name} (${userId}) [${connId}]`);

    // SECURITY: Rate limiting per connection
    const rateLimiter = {
      messages: 0,
      lastReset: Date.now(),
      maxMessages: 100, // Max 100 messages per minute per connection
      windowMs: 60000
    };

    // Set user presence to online
    userPresence.set(userId, {
      status: 'online',
      lastSeen: Date.now(),
      currentRoom: null
    });

    const clientInfo = { userId, user, rooms: new Set(), isAlive: true, connId, rateLimiter };
    clients.set(ws, clientInfo);
    // Also store client info on the WebSocket instance for API access
    ws.clientInfo = clientInfo;

    // Broadcast presence update
    const presenceMessage = JSON.stringify({
      type: 'PRESENCE_UPDATE',
      data: {
        userId,
        status: 'online',
        timestamp: Date.now()
      }
    });
    
    // Broadcast to all connected clients
    wss.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        try {
          client.send(presenceMessage);
        } catch (error) {
          console.error(`[${new Date().toISOString()}] Error broadcasting presence message:`, error);
        }
      }
    });

    ws.on('message', (data) => {
      const clientInfo = clients.get(ws);
      if (!clientInfo) return;

      // SECURITY: Rate limiting check
      const now = Date.now();
      if (now - clientInfo.rateLimiter.lastReset > clientInfo.rateLimiter.windowMs) {
        clientInfo.rateLimiter.messages = 0;
        clientInfo.rateLimiter.lastReset = now;
      }
      
      if (clientInfo.rateLimiter.messages >= clientInfo.rateLimiter.maxMessages) {
        console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Rate limit exceeded for user ${userId}, closing connection`);
        ws.close(1008, 'Rate limit exceeded');
        return;
      }
      clientInfo.rateLimiter.messages++;

      // Heartbeat check
      if (data.toString() === '{"type":"ping"}') {
        clientInfo.isAlive = true;
        ws.send(JSON.stringify({ type: 'pong' }));
        return;
      }

      try {
        const message = JSON.parse(data);
        
        // SECURITY: Input validation
        if (!message || typeof message !== 'object' || !message.type) {
          console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Invalid message format from user ${userId}`);
          return;
        }

        // SECURITY: Message type validation (whitelist)
        const allowedTypes = [
          'JOIN_ROOM', 'LEAVE_ROOM', 'CHAT_MESSAGE', 'DIRECT_MESSAGE', 'TYPING_START', 'TYPING_STOP',
                  'webrtc-offer', 'webrtc-answer', 'webrtc-ice-candidate', 'webrtc-end-call',
        'webrtc-call-rejected', 'webrtc-call-accepted', 'webrtc-call-cancelled', 'ping', 'pong'
        ];
        
        if (!allowedTypes.includes(message.type)) {
          console.log(`[${new Date().toISOString()}] 🚨 SECURITY: Unauthorized message type '${message.type}' from user ${userId}`);
          return;
        }

        switch (message.type) {
          case 'JOIN_ROOM': {
            const { chatRoomId } = message.data;
            if (chatRoomId) {
              if (!roomSubscriptions.has(chatRoomId)) {
                roomSubscriptions.set(chatRoomId, new Set());
              }
              roomSubscriptions.get(chatRoomId).add(ws);
              clientInfo.rooms.add(chatRoomId);
              
              // Update user presence with current room
              if (userPresence.has(clientInfo.userId)) {
                userPresence.set(clientInfo.userId, {
                  ...userPresence.get(clientInfo.userId),
                  currentRoom: chatRoomId
                });
              }
              
              console.log(`[${new Date().toISOString()}] User ${clientInfo.user.name} joined room ${chatRoomId}`);
              broadcastParticipantList(chatRoomId);
              
              // Send acknowledgment if required
              if (message.requiresAck) {
                ws.send(JSON.stringify({
                  type: 'MESSAGE_ACK',
                  data: { messageId: message.id, success: true }
                }));
              }
            }
            break;
          }

          case 'LEAVE_ROOM': {
            const { chatRoomId } = message.data;
            if (chatRoomId && roomSubscriptions.has(chatRoomId)) {
              roomSubscriptions.get(chatRoomId).delete(ws);
              clientInfo.rooms.delete(chatRoomId);
              
              // Update user presence
              if (userPresence.has(clientInfo.userId)) {
                const presence = userPresence.get(clientInfo.userId);
                if (presence.currentRoom === chatRoomId) {
                  userPresence.set(clientInfo.userId, {
                    ...presence,
                    currentRoom: null
                  });
                }
              }
              
              console.log(`[${new Date().toISOString()}] User ${clientInfo.user.name} left room ${chatRoomId}`);
              broadcastParticipantList(chatRoomId);
              
              // Send acknowledgment if required
              if (message.requiresAck) {
                ws.send(JSON.stringify({
                  type: 'MESSAGE_ACK',
                  data: { messageId: message.id, success: true }
                }));
              }
            }
            break;
          }

          case 'PRESENCE_UPDATE': {
            const { status } = message.data;
            if (userPresence.has(clientInfo.userId)) {
              userPresence.set(clientInfo.userId, {
                ...userPresence.get(clientInfo.userId),
                status,
                lastSeen: Date.now()
              });
              
              // Broadcast presence update to all clients
              const presenceMessage = JSON.stringify({
                type: 'PRESENCE_UPDATE',
                data: {
                  userId: clientInfo.userId,
                  status,
                  timestamp: Date.now()
                }
              });
              
              wss.clients.forEach(client => {
                if (client.readyState === WebSocket.OPEN) {
                  client.send(presenceMessage);
                }
              });
            }
            break;
          }

          case 'DIRECT_MESSAGE': {
            // Handle direct messages between users
            const { recipientId } = message.data;
            if (recipientId) {
              const outboundMessage = JSON.stringify(message);
              
              // Find the recipient's WebSocket connection(s)
              clients.forEach((clientInfo, clientWs) => {
                if (clientInfo.userId === recipientId && clientWs.readyState === WebSocket.OPEN) {
                  clientWs.send(outboundMessage);
                }
              });
              
              console.log(`[${new Date().toISOString()}] Direct message sent from ${clientInfo.user.name} to user ${recipientId}`);
            }
            break;
          }

          case 'CHAT_MESSAGE': {
            const { chatRoomId } = message.data;
            if (chatRoomId && roomSubscriptions.has(chatRoomId)) {
              const outboundMessage = JSON.stringify(message);
              roomSubscriptions.get(chatRoomId).forEach(clientWs => {
                if (clientWs.readyState === WebSocket.OPEN) {
                  clientWs.send(outboundMessage);
                }
              });
              
              // Send acknowledgment if required
              if (message.requiresAck) {
                ws.send(JSON.stringify({
                  type: 'MESSAGE_ACK',
                  data: { messageId: message.id, success: true }
                }));
              }
            }
            break;
          }

          case 'TYPING': {
            const { roomId } = message.data;
            if (roomId && roomSubscriptions.has(roomId)) {
              const outboundMessage = JSON.stringify(message);
              roomSubscriptions.get(roomId).forEach(clientWs => {
                if (clientWs !== ws && clientWs.readyState === WebSocket.OPEN) {
                  clientWs.send(outboundMessage);
                }
              });
            }
            break;
          }

          case 'ping': {
            // Enhanced ping with latency measurement
            ws.send(JSON.stringify({ 
              type: 'pong',
              timestamp: Date.now()
            }));
            // Mark client as alive when they send ping
            if (clientInfo) {
              clientInfo.isAlive = true;
            }
            break;
          }

          case 'pong': {
            // Client responded to our ping - mark as alive
            if (clientInfo) {
              clientInfo.isAlive = true;
              console.log(`[${new Date().toISOString()}] Received pong from ${clientInfo.user.name} - connection healthy`);
            }
            break;
          }

          // WebRTC Signaling for Video Calls
          case 'webrtc-offer':
          case 'webrtc-answer':
          case 'webrtc-ice-candidate':
          case 'webrtc-end-call':
          case 'webrtc-call-rejected':
          case 'webrtc-call-accepted':
          case 'webrtc-call-cancelled': {
            const { recipientId } = message.data;
            if (recipientId) {
              const signalMessage = JSON.stringify({
                type: message.type,
                senderId: clientInfo.userId,
                senderName: clientInfo.user.name || 'Unknown User',
                data: message.data
              });

              // DEBUG: Log all connected user IDs to help identify the issue
              console.log(`🔍 DEBUG - WebRTC signaling attempt:`);
              console.log(`🔍 Sender: ${clientInfo.user.name} (${clientInfo.userId})`);
              console.log(`🔍 Looking for recipient: ${recipientId}`);
              console.log(`🔍 Currently connected users:`);
              
              const connectedUserIds = [];
              clients.forEach((info, ws) => {
                const status = ws.readyState === WebSocket.OPEN ? 'OPEN' : 'CLOSED';
                console.log(`🔍   - ${info.user.name} (${info.userId}) [${status}]`);
                connectedUserIds.push(info.userId);
              });
              
              console.log(`🔍 Total connected users: ${connectedUserIds.length}`);

              // Find the recipient's WebSocket connection
              let signalSent = false;
              clients.forEach((recipientInfo, clientWs) => {
                if (recipientInfo.userId === recipientId && clientWs.readyState === WebSocket.OPEN) {
                  try {
                    clientWs.send(signalMessage);
                    signalSent = true;
                    console.log(`✅ Sending WebRTC signal to ${recipientInfo.user.name} (${recipientInfo.userId})`);
                  } catch (error) {
                    console.error(`[${new Date().toISOString()}] Error sending WebRTC signal:`, error);
                  }
                }
              });

              if (!signalSent) {
                console.log(`❌ Recipient ${recipientId} not found in connected users`);
                console.log(`💡 Possible causes:`);
                console.log(`💡   1. User disconnected/logged out`);
                console.log(`💡   2. Wrong user ID being used`);
                console.log(`💡   3. User connected to different server instance`);
                console.log(`💡   4. Browser tab closed or refreshed`);
                
                // Send error back to caller
                ws.send(JSON.stringify({
                  type: 'webrtc-error',
                  error: 'RECIPIENT_OFFLINE',
                  message: 'The user you are trying to call is not currently online',
                  recipientId: recipientId
                }));
                
                console.log(`WebRTC ${message.type} from ${clientInfo.user.name} to ${recipientId}: recipient offline`);
              }
            }
            break;
          }
        }
      } catch (error) {
        console.error('Failed to process message:', data.toString(), error);
      }
    });

    ws.on('close', (code, reason) => {
      const clientInfo = clients.get(ws);
      if (clientInfo) {
        console.log(`[${new Date().toISOString()}] WebSocket connection closed for user ${clientInfo.user.name} [${clientInfo.connId || 'unknown'}] - Code: ${code}, Reason: ${reason || 'No reason provided'}`);
        
        // Update user presence to offline
        if (userPresence.has(clientInfo.userId)) {
          userPresence.set(clientInfo.userId, {
            ...userPresence.get(clientInfo.userId),
            status: 'offline',
            lastSeen: Date.now(),
            currentRoom: null
          });
          
          // Broadcast presence update
          const presenceMessage = JSON.stringify({
            type: 'PRESENCE_UPDATE',
            data: {
              userId: clientInfo.userId,
              status: 'offline',
              timestamp: Date.now()
            }
          });
          
          wss.clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
              client.send(presenceMessage);
            }
          });
        }
        
        clientInfo.rooms.forEach(roomId => {
          if (roomSubscriptions.has(roomId)) {
            roomSubscriptions.get(roomId).delete(ws);
            if (roomSubscriptions.get(roomId).size === 0) {
              roomSubscriptions.delete(roomId);
              console.log(`[${new Date().toISOString()}] Room ${roomId} is now empty and removed.`);
            } else {
              broadcastParticipantList(roomId);
            }
          }
        });
        clients.delete(ws);
        // Clean up client info from WebSocket instance
        delete ws.clientInfo;
      }
    });

    ws.on('error', (error) => {
      const clientInfo = clients.get(ws);
      console.error(`[${new Date().toISOString()}] WebSocket error for user ${clientInfo ? clientInfo.user.name : 'unknown'}:`, error);
    });
  });
  
  // Set up a heartbeat to clean up disconnected clients.
  const interval = setInterval(() => {
    wss.clients.forEach((ws) => {
      const clientInfo = clients.get(ws);
      if (clientInfo) {
        if (!clientInfo.isAlive) {
          console.log(`[${new Date().toISOString()}] Terminating unresponsive connection for user ${clientInfo.user.name}`);
          return ws.terminate();
        }
        clientInfo.isAlive = false;
        // Send ping to check if client is responsive
        try {
          ws.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
        } catch (error) {
          console.error(`[${new Date().toISOString()}] Error sending ping to ${clientInfo.user.name}:`, error);
          ws.terminate();
        }
      }
    });
  }, 120000); // Increased from 60s to 120s (2 minutes) to be more forgiving for idle users

  wss.on('close', () => {
    clearInterval(interval);
  });

  console.log('WebSocket server initialized and attached to the HTTP server.');
}

app.prepare().then(() => {
  console.log('📦 Next.js app prepared successfully');
  const httpsOptions = getHttpsOptions();
  console.log('🔐 HTTPS options:', httpsOptions ? 'Found certificates' : 'No certificates');
  
  // Create HTTP server (redirects to HTTPS if certificates available)
  const httpServer = createHttpServer((req, res) => {
    try {
      // Debug endpoint to check connected WebSocket users
      if (req.url === '/debug/websocket-users') {
        const connectedUsers = [];
        if (typeof clients !== 'undefined') {
          clients.forEach((info, ws) => {
            connectedUsers.push({
              userId: info.userId,
              userName: info.user.name,
              userEmail: info.user.email,
              connectionId: info.connId,
              isAlive: info.isAlive,
              wsState: ws.readyState,
              wsStateText: ws.readyState === 0 ? 'CONNECTING' : 
                          ws.readyState === 1 ? 'OPEN' : 
                          ws.readyState === 2 ? 'CLOSING' : 'CLOSED',
              rooms: Array.from(info.rooms || [])
            });
          });
        }
        
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({
          timestamp: new Date().toISOString(),
          totalConnectedUsers: connectedUsers.length,
          users: connectedUsers
        }, null, 2));
        return;
      }
      
      // In development with HTTPS available, redirect to HTTPS
      if (httpsOptions) {
        const host = req.headers.host?.replace(`:${port}`, `:${httpsPort}`);
        res.writeHead(301, {
          Location: `https://${host}${req.url}`
        });
        res.end();
        return;
      }
      
      const parsedUrl = parse(req.url, true);
      handle(req, res, parsedUrl);
    } catch (err) {
      console.error('Error handling request:', err);
      res.statusCode = 500;
      res.end('Internal Server Error');
    }
  });

  httpServer.listen(port, '0.0.0.0', (err) => {
    if (err) throw err;
    console.log(`> HTTP server ready on http://0.0.0.0:${port}`);
    console.log(`> 🌐 Server accessible on network at http://${getNetworkIP()}:${port}`);
    
    if (httpsOptions) {
      console.log(`> ⚠️  HTTP redirects to HTTPS for video calling support`);
    } else {
      console.log('> ⚠️  HTTPS certificates not found. Video calling may not work.');
      console.log('> Run "npm run generate-certificates" to create HTTPS certificates.');
    }
  });

  httpServer.on('error', (err) => {
    console.error('HTTP Server error:', err);
  });

  // Start HTTPS server if certificates are available
  if (httpsOptions) {
    const httpsServer = createServer(httpsOptions, (req, res) => {
      try {
        // Debug endpoint to check connected WebSocket users
        if (req.url === '/debug/websocket-users') {
          const connectedUsers = [];
          if (typeof clients !== 'undefined') {
            clients.forEach((info, ws) => {
              connectedUsers.push({
                userId: info.userId,
                userName: info.user.name,
                userEmail: info.user.email,
                connectionId: info.connId,
                isAlive: info.isAlive,
                wsState: ws.readyState,
                wsStateText: ws.readyState === 0 ? 'CONNECTING' : 
                            ws.readyState === 1 ? 'OPEN' : 
                            ws.readyState === 2 ? 'CLOSING' : 'CLOSED',
                rooms: Array.from(info.rooms || [])
              });
            });
          }
          
          res.writeHead(200, { 'Content-Type': 'application/json' });
          res.end(JSON.stringify({
            timestamp: new Date().toISOString(),
            totalConnectedUsers: connectedUsers.length,
            users: connectedUsers
          }, null, 2));
          return;
        }
        
        const parsedUrl = parse(req.url, true);
        handle(req, res, parsedUrl);
      } catch (err) {
        console.error('Error handling HTTPS request:', err);
        res.statusCode = 500;
        res.end('Internal Server Error');
      }
    });

    httpsServer.listen(httpsPort, '0.0.0.0', (err) => {
      if (err) {
        console.error('Error starting HTTPS server:', err);
        return;
      }
      
      console.log(`> ✅ HTTPS server ready on https://0.0.0.0:${httpsPort}`);
      console.log(`> 🌐 Server accessible on network at https://${getNetworkIP()}:${httpsPort}`);
      console.log(`> 🎥 Video calling enabled with secure connection!`);
      console.log(`> 🔌 WebSocket endpoint: wss://0.0.0.0:${httpsPort}/_ws`);
    });

    httpsServer.on('error', (err) => {
      console.error('HTTPS Server error:', err);
    });

    // Initialize WebSocket server on HTTPS server
    initializeWebSocketServer(httpsServer);
  } else {
    // Initialize WebSocket server on HTTP server if no HTTPS
    console.log('> ⚠️  Running without HTTPS - video calling will not work');
    initializeWebSocketServer(httpServer);
  }

  // Note: API endpoints moved to Next.js API routes
  // /api/user/online-status/[userId].js and /api/users/online.js
});

CasperSecurity Mini