From c34d5381fe94d40fbd33d5710cf65d290190a74e Mon Sep 17 00:00:00 2001
From: Joao Siebel <joaos_desenv@imdt.com.br>
Date: Thu, 26 Nov 2020 11:19:59 -0300
Subject: [PATCH] Add flag to enable/disable custom heartbeat functions

---
 .../imports/startup/server/index.js           | 99 ++++++++++---------
 .../private/config/settings.yml               |  1 +
 2 files changed, 53 insertions(+), 47 deletions(-)

diff --git a/bigbluebutton-html5/imports/startup/server/index.js b/bigbluebutton-html5/imports/startup/server/index.js
index fa6e73c59c..ce0b3500e9 100755
--- a/bigbluebutton-html5/imports/startup/server/index.js
+++ b/bigbluebutton-html5/imports/startup/server/index.js
@@ -23,60 +23,65 @@ Meteor.startup(() => {
   const CDN_URL = APP_CONFIG.cdn;
   let heapDumpMbThreshold = 100;
 
-  // https://github.com/sockjs/sockjs-node/blob/1ef08901f045aae7b4df0f91ef598d7a11e82897/lib/transport/websocket.js#L74-L82
-  const newHeartbeat = function heartbeat() {
-    const currentTime = new Date().getTime();
-
-    // Skipping heartbeat, because websocket is sending data
-    if (currentTime - this.ws.lastSentFrameTimestamp < 10000) {
-      Logger.info('Skipping heartbeat, because websocket is sending data', {
-        currentTime,
-        lastSentFrameTimestamp: this.ws.lastSentFrameTimestamp,
-        userId: this.session.connection._meteorSession.userId,
-      });
-      return;
-    }
+  const { customHeartbeat } = APP_CONFIG;
+
+  if (customHeartbeat) {
+    Logger.warn('Custom heartbeat functions are enabled');
+    // https://github.com/sockjs/sockjs-node/blob/1ef08901f045aae7b4df0f91ef598d7a11e82897/lib/transport/websocket.js#L74-L82
+    const newHeartbeat = function heartbeat() {
+      const currentTime = new Date().getTime();
+
+      // Skipping heartbeat, because websocket is sending data
+      if (currentTime - this.ws.lastSentFrameTimestamp < 10000) {
+        Logger.info('Skipping heartbeat, because websocket is sending data', {
+          currentTime,
+          lastSentFrameTimestamp: this.ws.lastSentFrameTimestamp,
+          userId: this.session.connection._meteorSession.userId,
+        });
+        return;
+      }
 
-    const supportsHeartbeats = this.ws.ping(null, () => clearTimeout(this.hto_ref));
-    if (supportsHeartbeats) {
-      this.hto_ref = setTimeout(() => {
-        Logger.info('Heartbeat timeout', { userId: this.session.connection._meteorSession.userId, sentAt: currentTime, now: new Date().getTime() });
-      }, Meteor.server.options.heartbeatTimeout);
-    } else {
-      Logger.error('Unexpected error supportsHeartbeats=false');
-    }
-  };
+      const supportsHeartbeats = this.ws.ping(null, () => clearTimeout(this.hto_ref));
+      if (supportsHeartbeats) {
+        this.hto_ref = setTimeout(() => {
+          Logger.info('Heartbeat timeout', { userId: this.session.connection._meteorSession.userId, sentAt: currentTime, now: new Date().getTime() });
+        }, Meteor.server.options.heartbeatTimeout);
+      } else {
+        Logger.error('Unexpected error supportsHeartbeats=false');
+      }
+    };
 
-  // https://github.com/davhani/hagty/blob/6a5c78e9ae5a5e4ade03e747fb4cc8ea2df4be0c/faye-websocket/lib/faye/websocket/api.js#L84-L88
-  const newSend = function send(data) {
-    this.lastSentFrameTimestamp = new Date().getTime();
+    // https://github.com/davhani/hagty/blob/6a5c78e9ae5a5e4ade03e747fb4cc8ea2df4be0c/faye-websocket/lib/faye/websocket/api.js#L84-L88
+    const newSend = function send(data) {
+      this.lastSentFrameTimestamp = new Date().getTime();
 
-    // Call https://github.com/meteor/meteor/blob/1e7e56eec8414093cd0c1c70750b894069fc972a/packages/ddp-common/heartbeat.js#L80-L88
-    this.meteorHeartbeat._seenPacket = true;
-    if (this.meteorHeartbeat._heartbeatTimeoutHandle) {
-      this.meteorHeartbeat._clearHeartbeatTimeoutTimer();
-    }
+      // Call https://github.com/meteor/meteor/blob/1e7e56eec8414093cd0c1c70750b894069fc972a/packages/ddp-common/heartbeat.js#L80-L88
+      this.meteorHeartbeat._seenPacket = true;
+      if (this.meteorHeartbeat._heartbeatTimeoutHandle) {
+        this.meteorHeartbeat._clearHeartbeatTimeoutTimer();
+      }
 
-    if (this.readyState > 1/* API.OPEN = 1 */) return false;
-    if (!(data instanceof Buffer)) data = String(data);
-    return this._driver.messages.write(data);
-  };
+      if (this.readyState > 1/* API.OPEN = 1 */) return false;
+      if (!(data instanceof Buffer)) data = String(data);
+      return this._driver.messages.write(data);
+    };
 
-  Meteor.setInterval(() => {
-    for (const session of Meteor.server.sessions.values()) {
-      const { socket } = session;
-      const recv = socket._session.recv;
+    Meteor.setInterval(() => {
+      for (const session of Meteor.server.sessions.values()) {
+        const { socket } = session;
+        const recv = socket._session.recv;
 
-      if (session.bbbFixApplied || !recv || !recv.ws) {
-        continue;
-      }
+        if (session.bbbFixApplied || !recv || !recv.ws) {
+          continue;
+        }
 
-      recv.ws.meteorHeartbeat = session.heartbeat;
-      recv.__proto__.heartbeat = newHeartbeat;
-      recv.ws.__proto__.send = newSend;
-      session.bbbFixApplied = true;
-    }
-  }, 5000);
+        recv.ws.meteorHeartbeat = session.heartbeat;
+        recv.__proto__.heartbeat = newHeartbeat;
+        recv.ws.__proto__.send = newSend;
+        session.bbbFixApplied = true;
+      }
+    }, 5000);
+  }
 
   const memoryMonitoringSettings = Meteor.settings.private.memoryMonitoring;
   if (memoryMonitoringSettings.stat.enabled) {
diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml
index a8d5253345..afb701efad 100755
--- a/bigbluebutton-html5/private/config/settings.yml
+++ b/bigbluebutton-html5/private/config/settings.yml
@@ -36,6 +36,7 @@ public:
     # can generate excessive overhead to the server. We recommend
     # this value to be kept under 12.
     breakoutRoomLimit: 8
+    customHeartbeat: false
     defaultSettings:
       application:
         animations: true
-- 
GitLab