NodeServer - Real-Time Signaling & Communication Hub

Overview

The NodeServer is a critical Node.js-based WebSocket server that powers real-time communication for the Psyter telemedicine platform and multiple assessment/learning management systems. It handles:

  • Presence Management - Online/offline status, user authentication
  • WebRTC Signaling - Video/audio call setup via SDP/ICE candidate exchange
  • Collaboration Sessions - Multi-party video consultations with time limits
  • Real-time Messaging - Chat, file transfer, typing indicators
  • Push Notifications - Firebase Cloud Messaging (FCM) and Apple Push Notifications (APN)
  • Multi-Tenant Support - Serves multiple client systems (Psyter, QuranLMS, Assessment Systems)

Technology Stack:
- Runtime: Node.js
- WebSocket Library: ws (v7.2.1)
- Database: MS SQL Server via mssql (v6.0.1)
- Push Notifications: Firebase Admin SDK (v8.9.1), apn (v2.2.0)
- HTTPS Server: Native Node.js https module with SSL certificates
- Logging: Winston (v3.2.1) with daily log rotation


Prerequisites

Required Software

  • Node.js: v12.x or v14.x (compatible with dependencies)
  • npm: v6.x or higher
  • SQL Server: Access to Psyter/QuranLMS/Assessment databases
  • SSL Certificates: Per-tenant certificates for HTTPS/WSS

Required Access

  • Database connection credentials for configured tenants
  • Firebase service account JSON files
  • Apple Push Notification certificates and keys
  • SSL certificate files (.pem format)

Setup Instructions

1. Install Dependencies

cd NodeServer
npm install

Key Dependencies:

{
  "ws": "7.2.1",                          // WebSocket server
  "mssql": "6.0.1",                       // SQL Server driver
  "firebase-admin": "8.9.1",              // FCM notifications
  "apn": "2.2.0",                         // Apple Push Notifications
  "winston": "3.2.1",                     // Logging
  "winston-daily-rotate-file": "4.4.1",  // Log rotation
  "yargs": "15.1.0",                      // Command-line args
  "jsonfile": "5.0.0"                     // Config file reading
}

2. Configure SSL Certificates

Place SSL certificates in the ssl/ directory organized by client mode:

ssl/
├── PSYTER_DEV/
│   ├── key_live.pem
│   └── cert_live.pem
├── PSYTER_LIVE/
│   ├── key_live.pem
│   └── cert_live.pem
├── QURAN_DEV/
│   └── ...
└── [Other tenants]/

Certificate Passphrase: All certificates use passphrase 123456789 (⚠️ Change in production!)

3. Configure Database Connections

Database configurations are hardcoded in server.js within the setClientMode() function. Each tenant has its own database settings.

Example (PSYTER_DEV):

dbConfig = {
    user: 'PsyterUser',
    password: 'PsyterPa$$w0Rd',
    server: 'db.innotech-sa.com',
    database: 'Psyter_v1'
};

⚠️ Security Warning: Credentials should be externalized to environment variables or secure configuration management.

4. Configure Firebase Settings

Firebase configurations are also hardcoded per tenant in setClientMode():

fcmAPISettings = {
    ProjectId: "psyterdev",
    ClientEmail: "firebase-adminsdk-uh0r6@psyterdev.iam.gserviceaccount.com",
    PrivateKey: "-----BEGIN PRIVATE KEY-----\n...",
    DatabaseURL: "https://psyterdev.firebaseio.com"
};

5. Update config.json

Create/edit config.json in the root directory:

{
  "enableLog": "true"
}
  • enableLog: Set to "true" to enable logging, "false" to disable

6. Set Client Mode and Start Server

The server requires a --clientmode argument to specify which tenant to serve:

# Development Mode
node server.js --clientmode=3   # PSYTER_DEV (port 3333)

# Production Mode  
node server.js --clientmode=4   # PSYTER_LIVE (port 3223)

# QuranLMS
node server.js --clientmode=2   # QURAN_LMS (port 1443)

# Assessment Systems
node server.js --clientmode=6   # ASSESSMENTSYSTEM_DEV (port 5223)

Available Client Modes:

cClient = {
    QURAN_DEV: 1,                    // Port 2333
    QURAN_LMS: 2,                    // Port 1443
    PSYTER_DEV: 3,                   // Port 3333
    PSYTER_LIVE: 4,                  // Port 3223
    ONE2ONE: 5,                      // Port 4223
    ASSESSMENTSYSTEM_DEV: 6,         // Port 5223
    ASSESSMENTSYSTEM_AFU: 7,         // Port 5224
    ASSESSMENTSYSTEM_PSU: 8,         // Port 5225
    ASSESSMENTSYSTEM_KSU: 9,         // Port 5226
    ASSESSMENTSYSTEM_MBRU: 10,       // Port 5227
    ASSESSMENTSYSTEM_TAIF: 11,       // Port 5228
    NARAAKUM_DEV: 12                 // Port 6223
};

7. Verify Server Startup

Look for these log messages:

Server is up and running
WebSocket server is up and running
APN is initialized
Sql connection is established
FCM is initialized

Running the Application

Development Mode

node server.js --clientmode=3

Production Mode (Using PM2)

# Install PM2
npm install -g pm2

# Start server
pm2 start server.js --name "psyter-nodeserver" -- --clientmode=4

# View logs
pm2 logs psyter-nodeserver

# Restart
pm2 restart psyter-nodeserver

# Stop
pm2 stop psyter-nodeserver

Using the Restart Script (Linux)

chmod +x restart.sh
./restart.sh

Note: The restart.sh script is hardcoded for QuranLive (clientmode=2). Modify it for other tenants.


Project Structure

NodeServer/
├── server.js               # Main server file (~3000 lines)
├── package.json            # Dependencies
├── package-lock.json       # Dependency lock file
├── config.json             # Runtime configuration
├── restart.sh              # Linux restart script
├── ssl/                    # SSL certificates per tenant
│   ├── PSYTER_DEV/
│   ├── PSYTER_LIVE/
│   ├── QURAN_DEV/
│   └── [other tenants]/
└── node_modules/           # Installed dependencies

server.js Architecture

The server.js file is monolithic (~3000 LOC) and contains:

1. Constants & Enums (Lines 1-150)
- cClient - Tenant identifiers
- cCommand - WebSocket command types (66 commands)
- cReason - Response reason codes
- cStatus - User presence states
- cConnectionMode - Presence vs Collaboration modes
- cCollaborationMode - Audio/video/both
- cClientPlatform - Web/Android/iOS identification

2. Configuration & Initialization (Lines 150-250)
- Database connection setup per tenant
- Firebase Admin SDK initialization
- SSL certificate loading
- WebSocket server creation
- APN provider setup

3. Connection Handling (Lines 250-400)
- WebSocket connection lifecycle
- Query parameter parsing (connectionMode, userId, collaborationKey, etc.)
- Client authentication routing

4. Presence Mode Functions (Lines 400-2200)
- PAuthenticate - User login via communication key/username
- PSignIn/PSignOut - Online/offline status
- PStatus - Status updates (online, away, DND)
- PChat - Chat message routing
- PCollaboration - Call invitation handling
- PReject/PNoAnswer - Call rejection flows
- PSendToUser - Direct user messaging
- PBroadCast - Status broadcasts to friend lists

5. Collaboration Mode Functions (Lines 2200-2800)
- CInitiate - WebRTC session initialization
- CCreateCollaboration - Multi-party call setup
- CSendCommand - SDP/ICE candidate exchange
- CLeaveCollaboration - User leaving call
- CEndCollaboration - Call termination
- CTimeLimit - Session time management
- CConsumptionInsert - Database logging of call duration

6. Messaging Functions (Lines 2800-2968)
- PSendMessage - Store and route chat messages
- PGetNewMessageCount - Unread message counts
- PGetUserConversationsList - Conversation list pagination
- PGetUserConversationMessageList - Message history
- PUpdateMessageStatus - Read receipts

7. Utility Functions
- logInfo - Winston logging with rotation
- SendFCMNotification - Firebase push notifications
- CleanSocketConnectionList - Connection cleanup
- UniqueToken - Collaboration key generation


Key Features

1. Presence Management

Authentication Methods:
- Communication Key: Mobile app-based verification code
- Username/Password: Direct credentials
- Client Key: Web portal authentication
- Re-authentication: Resume session after disconnect

User Status:
- OFFLINE (1), ONLINE (2), AWAY (3), DO_NOT_DISTURB (4), INVISIBLE (5)
- NETWORK_POOR (6), NETWORK_OK (7)

Connection Example:

wss://server:3333/?connectionMode=1&communicationKey=ABC123&deviceId=device1&clientPlatform=2

2. WebRTC Signaling

Call Flow:
1. Initiator: Sends C_CREATE_COLLABORATION with participant list
2. Server: Generates unique collaborationKey, broadcasts to participants
3. Participant: Receives P_ACCEPT_COLLABORATION via FCM/WebSocket
4. Both: Connect via connectionMode=2&collaborationKey=XYZ
5. Exchange: C_SDP (offers/answers) and C_ICECANDIDATE messages
6. Termination: C_END_COLLABORATION or C_LEAVE_COLLABORATION

Supported Commands:
- C_SDP - Session Description Protocol exchange
- C_ICECANDIDATE - ICE candidate exchange
- C_HOLD_COLLABORATION / C_UNHOLD_COLLABORATION - Call hold
- C_CAMERA_ON / C_CAMERA_OFF - Video toggle
- C_AUDIO_ON / C_AUDIO_OFF - Audio toggle
- C_TYPING_ON / C_TYPING_OFF - Typing indicators

3. Multi-Party Collaboration

Features:
- Initiator + Participants: One initiator, multiple participants
- Time Limits: Configurable session duration with automatic timeout
- Consumption Tracking: Call duration logged to database via Mobile_Package_ConsumptionDetail_Update
- Scheduled Sessions: Supports pre-booked appointments with bookingId

Time Limit Flow:

Client → C_TIME_LIMIT (60 seconds)
Server → Starts countdown timer
Server → [60s later] → C_TIMEOUT_COLLABORATION
Server → Calls CConsumptionInsert() to log duration

4. Push Notifications

Firebase Cloud Messaging (Android):
- Topic-based subscriptions: patient_{id}, doctor_{id}, student_{id}, staff_{id}
- Payload includes full command structure for offline users

Apple Push Notifications (iOS):
- VoIP notifications for incoming calls
- Topic: com.innotech-sa.Quran-University.voip
- Custom payload with collaboration data

Notification Triggers:
- Incoming collaboration requests
- Chat messages (when user offline)
- Call rejection/no answer
- Unreachable user

5. Real-Time Messaging

Database Integration:

Message_InsertMessage
Message_GetNewMessagesCount
Message_GetUserConversationsList
Message_GetUserConversationMessages
Message_UpdateMessageStatus

Features:
- Text and file attachments (images, documents)
- Read receipts (Sent, Delivered, Read)
- Pagination support for conversation lists and message history
- Offline message delivery via FCM

6. Multi-Tenant Support

Tenant Isolation:
- Separate database per tenant
- Separate Firebase project per tenant
- Separate SSL certificates
- Process title identifies running instance: NODE_PSYTER_DEV, PsyterLive, QuranLive


API Reference

WebSocket Connection URL

Format:

wss://<server>:<port>/?<queryParams>

Required Query Parameters:

Parameter Type Description Example
connectionMode Int 1=Presence, 2=Collaboration 1
communicationKey String Verification code (Presence auth) ABC123
userName String Username (alternative auth) patient@example.com
password String Password (alternative auth) password123
clientKey String Client authentication key (Web) KEY_ABC
collaborationKey String Session ID (Collaboration mode) uuid-1234
fromUserId Int User ID (Collaboration mode) 42
deviceId String Device identifier device_android_123
clientPlatform Int 1=Web, 2=Android, 3=iOS 2
reConnect Int 1=Re-authentication 1
authenticateOnly Int 1=Auth without presence 1

WebSocket Message Structure

Client → Server:

{
  "ConnectionMode": 1,
  "Command": 5,
  "Message": "Hello",
  "FromUser": { "Id": 42, "Fullname": "John Doe" },
  "ToUserList": [{ "Id": 43 }],
  "CollaborationKey": "uuid-1234",
  "ClientId": 123456789,
  "ClientInitiationTime": "2025-11-10 12:00:00"
}

Server → Client:

{
  "Message": "...",
  "CollaborationKey": "uuid-1234",
  "ConnectionMode": 1,
  "Command": 5,
  "Reason": 1,
  "FromUser": { "Id": 42, "Fullname": "John Doe" },
  "ToUserList": [{ "Id": 43 }],
  "ClientInitiationTime": "2025-11-10 12:00:00",
  "ServerIntimationTime": "2025-11-10 12:00:05"
}

Command Reference

Presence Commands (P_*):

Command ID Description
P_AUTHENTICATE 1 Initial authentication
P_SIGNIN 2 User logged in
P_SIGNOUT 3 User logged out
P_CHAT 5 Chat message
P_STATUS 6 Status change
P_ACCEPT_COLLABORATION 7 Accept call
P_REJECT_COLLABORATION 8 Reject call
P_NO_ANSWER 10 Missed call
P_CLOSE_CALL 11 Call ended
P_NETWORK_POOR 27 Network degraded
P_NETWORK_OK 28 Network restored
P_SEND_MESSAGE 55 Send chat message
P_RECIEVE_MESSAGE 56 Receive chat message
P_GET_NEW_MESSAGE_COUNT 57 Unread count
P_GET_MESSAGE_CONVERSATION_LIST 58 Conversation list
P_GET_CONVERSATION_MESSAGE_LIST 59 Message history
P_UPDATE_MESSAGE_STATUS 60 Read receipt
P_OTHER_PARTY_JOINED 66 Participant joined

Collaboration Commands (C_*):

Command ID Description
C_INITIATE 12 Join collaboration session
C_CREATE_COLLABORATION 13 Start new call
C_JOINED_COLLABORATION 14 Participant joined
C_SDP 16 WebRTC SDP exchange
C_ICECANDIDATE 17 WebRTC ICE candidate
C_LEAVE_COLLABORATION 18 Leave call
C_END_COLLABORATION 19 End call
C_HOLD_COLLABORATION 21 Put call on hold
C_UNHOLD_COLLABORATION 22 Resume call
C_CAMERA_ON 23 Enable video
C_CAMERA_OFF 24 Disable video
C_AUDIO_ON 32 Unmute audio
C_AUDIO_OFF 33 Mute audio
C_NETWORK_POOR 25 Network issue
C_TIME_LIMIT 50 Session time limit
C_TIMEOUT_COLLABORATION 54 Session expired
C_REINITIATE 34 Reconnect to session

Reason Codes

Reason ID Description
SUCCESS 1 Operation successful
ERROR 2 Generic error
INVALID_REQUEST 3 Malformed request
INVALID_USER 4 User not found/invalid credentials
DATABASE_NOT_AVAILABLE 5 DB connection failure
RECONNECT 6 Client should reconnect
ALREADY_LOGGED_IN 7 Duplicate login (Assessment Systems)
REJECT_COLLABORATION 8 Call rejected
NO_ANSWER 9 Call not answered
ALREADY_IN_COLLABORATION 11 User already in call
CLOSE_COLLABORATION 13 Collaboration ended
TIMEOUT 16 Session timeout

Database Stored Procedures

The server calls these SQL Server stored procedures:

Authentication & User Management

  • COB_Authenticate - Client key authentication
  • COB_Authenticate_Get_User_List - User authentication and friend list
  • COB_Get_User_List - All users
  • COB_Get_Related_User_List - User’s friends/contacts
  • COB_Manage_User_Friend - Add/remove friend
  • COB_Update_Password - Change password
  • COB_Create_User - Register new user

Collaboration & Sessions

  • Mobile_Package_ConsumptionDetail_Update - Log call duration (Assessment Systems)
  • SP_ManageCareProvidersServiceCount - Update provider service count (Psyter)
  • SP_GetBookingDetailsById - Fetch booking details

Messaging

  • Message_InsertMessage - Save new message
  • Message_GetNewMessagesCount - Unread count
  • Message_GetUserConversationsList - Conversation list
  • Message_GetUserConversationMessages - Message history
  • Message_UpdateMessageStatus - Update read status

Logging

Log Configuration

Winston Logger Settings:
- Log Directory: /var/www/html/node/pro/log/{CLIENT_MODE}/
- File Pattern: {CLIENT_MODE}_YYYY-MM-DD.txt
- Rotation: Daily
- Levels: Info, Error
- Console Output: Enabled with colorization

Example Log Entry:

2025-11-10 14:32:15: -#----- Active Connections ( 42 ) -----#-
2025-11-10 14:32:15: INFO  -->  CLIENT  -->  cCommand.P_CHAT  -->  Sender = John Doe (42)

Log Types

  • INFO - Normal operations, command processing
  • ERROR - Exceptions, database errors, notification failures

Disabling Logs

Edit config.json:

{
  "enableLog": "false"
}

The server polls this file every 10 seconds.


Common Issues & Troubleshooting

Issue 1: “Cannot read property ‘length’ of undefined”

Cause: Client disconnected abruptly, lists not cleaned up
Solution: Server has heartbeat mechanism (30-minute ping), should auto-clean. Check CleanSocketConnectionList() function.

Issue 2: Database Connection Errors

Symptoms: cReason.DATABASE_NOT_AVAILABLE errors
Solutions:
- Verify SQL Server is accessible from Node.js server
- Check firewall rules (SQL Server port 1433)
- Confirm credentials in setClientMode()
- Check database exists and user has permissions

Issue 3: Firebase Notifications Not Delivered

Symptoms: No push notifications when user offline
Solutions:
- Verify Firebase service account credentials
- Check topic naming: patient_{id}~, doctor_{id}~, etc.
- Ensure mobile apps subscribe to correct topics
- Check Firebase Console for delivery errors

Issue 4: SSL Certificate Errors

Symptoms: ENOENT: no such file or directory on startup
Solutions:
- Ensure SSL files exist in ssl/{CLIENT_MODE}/ directory
- Verify filenames: key_live.pem and cert_live.pem
- Check file permissions (readable by Node.js process)

Issue 5: Port Already in Use

Symptoms: EADDRINUSE: address already in use
Solutions:

# Find process using port
netstat -ano | findstr :3333  # Windows
lsof -i :3333                 # Linux/Mac

# Kill process
taskkill /PID <PID> /F        # Windows
kill -9 <PID>                 # Linux/Mac

Issue 6: Collaboration Not Starting

Symptoms: C_UNINITIATE or timeout
Solutions:
- Verify both users are authenticated (Presence mode)
- Check collaborationKey is generated and shared correctly
- Ensure users connect with connectionMode=2
- Review logs for INVALID_USER or ALREADY_IN_COLLABORATION

Issue 7: Messages Not Persisting

Symptoms: Chat works real-time but not saved
Solutions:
- Check Message_InsertMessage stored procedure exists
- Verify database user has EXECUTE permission
- Review SQL Server logs for errors
- Confirm CatMessageStatus values are valid


Security Considerations

⚠️ Critical Security Issues Identified:

  1. Hardcoded Credentials - Database passwords and Firebase private keys are in source code
    - Impact: Credential exposure in version control
    - Recommendation: Use environment variables or Azure Key Vault

  2. SSL Certificate Passphrase - Hardcoded as 123456789
    - Impact: Weak encryption protection
    - Recommendation: Use strong passphrase, externalize to secure config

  3. No Input Validation - User input not sanitized before SQL queries
    - Impact: Potential SQL injection via stored procedure parameters
    - Recommendation: Validate all user inputs, use parameterized queries (already using request.input(), good!)

  4. No Rate Limiting - WebSocket connections not throttled
    - Impact: Vulnerable to DDoS attacks
    - Recommendation: Implement connection limits per IP

  5. Unencrypted Database Connections - No SSL/TLS for SQL Server
    - Impact: Credentials/data transmitted in plaintext internally
    - Recommendation: Enable SQL Server encryption

  6. Global Error Handlers - uncaughtException and unhandledRejection catch-all
    - Impact: Errors may be swallowed, process doesn’t crash
    - Recommendation: Log and restart process on critical errors


Performance Considerations

Connection Limits

  • Current: No hard limits configured
  • WebSocket Library Default: ~10,000 concurrent connections (OS dependent)
  • Database Pooling: mssql default pool size is 10

Recommendations:
- Monitor active connection count (ccCount variable)
- Implement Redis pub/sub for horizontal scaling (multiple Node instances)
- Use database connection pooling configuration

Memory Management

  • Heartbeat Interval: 30 minutes (ping/pong)
  • Cleanup Functions: CleanSocketConnectionList() runs on each disconnect
  • In-Memory Lists:
  • userList - All authenticated users
  • pUserConnectionList - Presence connections
  • cUserConnectionList - Collaboration connections
  • collaborationList - Active sessions

Risk: Memory leak if cleanup fails; monitor with process.memoryUsage()

Database Query Optimization

  • Most queries use stored procedures (efficient)
  • No connection pooling configuration (uses defaults)
  • Consider caching user lists with Redis for high-traffic scenarios

Deployment Guide

Linux Server Deployment

1. Install Node.js:

curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs

2. Clone/Copy Project:

cd /var/www/html/node/pro
git clone <repository> NodeServer
cd NodeServer
npm install --production

3. Create Log Directory:

sudo mkdir -p /var/www/html/node/pro/log/PSYTER_LIVE
sudo chown -R $USER:$USER /var/www/html/node/pro/log

4. Install PM2:

sudo npm install -g pm2

5. Start Server:

pm2 start server.js --name psyter-live -- --clientmode=4
pm2 save
pm2 startup

6. Configure Firewall:

sudo ufw allow 3223/tcp  # PSYTER_LIVE port

Windows Server Deployment

1. Install Node.js:
- Download from https://nodejs.org/
- Run installer, select “Add to PATH”

2. Install Dependencies:

cd C:\NodeServer
npm install

3. Install PM2 (Windows Service):

npm install -g pm2
npm install -g pm2-windows-service
pm2-service-install

4. Start Server:

pm2 start server.js --name psyter-live -- --clientmode=4
pm2 save

Health Check Endpoint

⚠️ Missing: Server has no HTTP health check endpoint

Recommendation: Add Express.js for health checks:

const express = require('express');
const app = express();

app.get('/health', (req, res) => {
  res.json({
    status: 'healthy',
    connections: ccCount,
    uptime: process.uptime()
  });
});

app.listen(3334, () => console.log('Health check on port 3334'));


Monitoring & Maintenance

Key Metrics to Monitor

  • Active Connections: ccCount variable
  • Process Memory: process.memoryUsage().heapUsed
  • Database Connection State: SQL connection health
  • Log File Size: Daily rotation in /var/www/html/node/pro/log/

PM2 Monitoring

pm2 monit                    # Real-time monitoring
pm2 logs psyter-live         # View logs
pm2 restart psyter-live      # Restart process
pm2 stop psyter-live         # Stop process
pm2 delete psyter-live       # Remove from PM2

Log Analysis

# Search for errors
grep ERROR /var/www/html/node/pro/log/PSYTER_LIVE/*.txt

# Count connections over time
grep "Active Connections" /var/www/html/node/pro/log/PSYTER_LIVE/*.txt | wc -l

# Find authentication failures
grep "INVALID_USER" /var/www/html/node/pro/log/PSYTER_LIVE/*.txt

Development Workflow

Local Development

1. Mock Database (Optional):
If you don’t have access to the actual databases, comment out SQL calls and return mock data:

// In PAuthenticate function
// Comment out SQL query, return mock user
var mockUser = [{
  Id: 1,
  Fullname: "Test User",
  Email: "test@example.com",
  // ... other fields
}];
PAuthenticateSuccess(command, client, data, mockUser, []);

2. Run Server:

node server.js --clientmode=3

3. Test WebSocket Connection:

Use a WebSocket client like Smart WebSocket Client or:

const WebSocket = require('ws');
const ws = new WebSocket('wss://localhost:3333/?connectionMode=1&communicationKey=TEST123&deviceId=dev1&clientPlatform=1', {
  rejectUnauthorized: false // For self-signed certs
});

ws.on('open', () => {
  console.log('Connected');
});

ws.on('message', (data) => {
  console.log('Received:', data);
});

Code Formatting

ESLint Configuration (Not Present):
Recommend adding:

npm install --save-dev eslint
npx eslint --init

Recommended .eslintrc.json:

{
  "env": {
    "node": true,
    "es6": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaVersion": 2018
  },
  "rules": {
    "indent": ["error", 4],
    "linebreak-style": ["error", "unix"],
    "quotes": ["error", "single"],
    "semi": ["error", "always"]
  }
}


Testing

⚠️ No automated tests present

1. Install Testing Framework:

npm install --save-dev mocha chai sinon

2. Create Test Directory:

NodeServer/
├── test/
│   ├── authentication.test.js
│   ├── collaboration.test.js
│   ├── messaging.test.js
│   └── utils.test.js

3. Example Test (authentication.test.js):

const { expect } = require('chai');
const WebSocket = require('ws');

describe('Authentication', () => {
  let ws;

  before((done) => {
    // Start server
    require('../server.js');
    setTimeout(done, 1000);
  });

  it('should authenticate with valid communication key', (done) => {
    ws = new WebSocket('wss://localhost:3333/?connectionMode=1&communicationKey=VALID_KEY');
    ws.on('message', (data) => {
      const msg = JSON.parse(data);
      expect(msg.Command).to.equal(1); // P_AUTHENTICATE
      expect(msg.Reason).to.equal(1);  // SUCCESS
      done();
    });
  });

  after(() => {
    if (ws) ws.close();
  });
});

Manual Testing Checklist

Presence Mode:
- [ ] User authentication (communication key)
- [ ] User authentication (username/password)
- [ ] User sign out
- [ ] Status change broadcast
- [ ] Chat message delivery
- [ ] Friend list retrieval
- [ ] Network status updates

Collaboration Mode:
- [ ] Create collaboration (1-to-1)
- [ ] Create collaboration (multi-party)
- [ ] SDP/ICE candidate exchange
- [ ] Video/audio toggle
- [ ] Call hold/unhold
- [ ] Leave collaboration
- [ ] End collaboration
- [ ] Time limit enforcement
- [ ] Timeout handling

Messaging:
- [ ] Send text message
- [ ] Send file attachment
- [ ] Receive message (online user)
- [ ] Receive message (offline via FCM)
- [ ] Read receipts
- [ ] Conversation list pagination
- [ ] Message history pagination


Migration & Upgrade Path

1. Externalize Configuration
- Move database credentials to .env file
- Use dotenv package
- Configure per environment (dev, staging, prod)

2. Add TypeScript
- Improve maintainability with type safety
- Better IDE support
- Catch errors at compile time

3. Modularize Code
- Split server.js into separate files:

src/
├── index.js
├── config/
│   ├── database.js
│   ├── firebase.js
│   └── ssl.js
├── handlers/
│   ├── presence.js
│   ├── collaboration.js
│   └── messaging.js
├── utils/
│   ├── logger.js
│   ├── notifications.js
│   └── helpers.js
└── models/
    ├── user.js
    └── collaboration.js

4. Add Database ORM
- Consider using Sequelize or TypeORM
- Better query building and validation
- Migration management

5. Implement Horizontal Scaling
- Use Redis for pub/sub between multiple Node instances
- Share session state across instances
- Load balancer configuration (NGINX)

6. Add Monitoring
- Prometheus metrics export
- Grafana dashboards
- Error tracking (Sentry)


API Client Examples

JavaScript (Browser)

class PsyterWebSocket {
  constructor(url, userId, communicationKey) {
    this.ws = new WebSocket(
      `${url}?connectionMode=1&communicationKey=${communicationKey}&deviceId=web_${Date.now()}&clientPlatform=1`
    );

    this.ws.onmessage = (event) => {
      const msg = JSON.parse(event.data);
      this.handleMessage(msg);
    };
  }

  handleMessage(msg) {
    switch(msg.Command) {
      case 1: // P_AUTHENTICATE
        console.log('Authenticated:', msg.FromUser);
        break;
      case 2: // P_SIGNIN
        console.log('User online:', msg.FromUser);
        break;
      case 5: // P_CHAT
        console.log('Chat message:', msg.Message);
        break;
    }
  }

  sendChat(toUserId, message) {
    this.ws.send(JSON.stringify({
      ConnectionMode: 1,
      Command: 5,
      Message: message,
      FromUser: this.currentUser,
      ToUserList: [{ Id: toUserId }]
    }));
  }
}

// Usage
const client = new PsyterWebSocket('wss://server:3333', 42, 'ABC123');

Android (Java)

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
    .url("wss://server:3333/?connectionMode=1&communicationKey=ABC123&deviceId=android_1&clientPlatform=2")
    .build();

WebSocket ws = client.newWebSocket(request, new WebSocketListener() {
    @Override
    public void onMessage(WebSocket webSocket, String text) {
        JSONObject msg = new JSONObject(text);
        int command = msg.getInt("Command");
        // Handle message
    }
});

// Send chat
JSONObject chatMsg = new JSONObject();
chatMsg.put("ConnectionMode", 1);
chatMsg.put("Command", 5);
chatMsg.put("Message", "Hello");
ws.send(chatMsg.toString());

Contribution Guidelines

Code Style

  • Indentation: 4 spaces
  • Naming: camelCase for variables/functions, PascalCase for constants
  • Comments: Explain complex logic, not obvious code
  • Function Length: Keep under 50 lines when possible

Pull Request Process

  1. Create feature branch from main
  2. Implement changes with meaningful commit messages
  3. Add/update tests (when test framework added)
  4. Update README if adding features
  5. Submit PR with description of changes

Commit Message Format

type(scope): subject

- Detailed explanation if needed
- Can span multiple lines

Examples:
feat(messaging): add typing indicator support
fix(auth): resolve token expiration issue
docs(readme): update deployment guide

License & Credits

Author: Muhammad Mansoor Umer Chaudhry
Package Name: cn.signaling-server
Version: 0.0.0 (Should be updated!)


Support & Contact

For issues or questions:
1. Check logs in /var/www/html/node/pro/log/
2. Review this README’s troubleshooting section
3. Contact platform maintainers


Changelog

Current Version (0.0.0):
- Multi-tenant WebSocket signaling server
- Presence management
- WebRTC collaboration
- Firebase/APN push notifications
- Real-time messaging
- Database integration

Future Roadmap:
- [ ] Externalized configuration
- [ ] TypeScript migration
- [ ] Automated testing
- [ ] Health check endpoint
- [ ] Horizontal scaling with Redis
- [ ] Performance metrics
- [ ] Security hardening