From bb0ee69088dcc02e36b265420f9c1392f6fa6318 Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Sat, 14 Jul 2018 19:19:21 +0200
Subject: [PATCH] [enh] upgrade to ws@1.1.5 + abstract it in the code

---
 app/lib/common-libs/websocket.ts         | 38 ++++++++++++++++++++++++
 app/modules/bma/lib/bma.ts               | 15 +++++-----
 app/modules/ws2p/lib/WS2PConnection.ts   |  4 +--
 app/modules/ws2p/lib/WS2PServer.ts       |  3 +-
 package.json                             |  1 +
 test/integration/misc/http-api.ts        | 14 ++++-----
 test/integration/tools/toolbox.ts        |  8 ++---
 test/integration/ws2p/ws2p_connection.ts |  2 +-
 yarn.lock                                |  7 +++++
 9 files changed, 68 insertions(+), 24 deletions(-)
 create mode 100644 app/lib/common-libs/websocket.ts

diff --git a/app/lib/common-libs/websocket.ts b/app/lib/common-libs/websocket.ts
new file mode 100644
index 000000000..a9589d2ab
--- /dev/null
+++ b/app/lib/common-libs/websocket.ts
@@ -0,0 +1,38 @@
+// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
+// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+
+import * as WS from 'ws'
+
+export class WebSocket extends WS {
+  constructor(url: string, options?: { agent: any }) {
+    super(url, {
+      agent: options && options.agent,
+    })
+  }
+}
+
+export class WebSocketServer extends WS.Server {
+  constructor(options: {
+    server?: any,
+    host?: string,
+    port?: number,
+    path?: string
+  }) {
+    super({
+      server: options.server,
+      path: options.path,
+      host: options.host,
+      port: options.port,
+    })
+  }
+}
diff --git a/app/modules/bma/lib/bma.ts b/app/modules/bma/lib/bma.ts
index ee53a3726..575ab3eb0 100644
--- a/app/modules/bma/lib/bma.ts
+++ b/app/modules/bma/lib/bma.ts
@@ -24,9 +24,9 @@ import {UDBinding} from "./controllers/uds"
 import {PeerDTO} from "../../../lib/dto/PeerDTO"
 import {BlockDTO} from "../../../lib/dto/BlockDTO"
 import {OtherConstants} from "../../../lib/other_constants"
+import {WebSocketServer} from "../../../lib/common-libs/websocket"
 
 const es = require('event-stream');
-const WebSocketServer = require('ws').Server;
 
 export const bma = function(server:Server, interfaces:NetworkInterface[]|null, httpLogs:boolean, logger:any): Promise<BmaApi> {
 
@@ -149,16 +149,17 @@ export const bma = function(server:Server, interfaces:NetworkInterface[]|null, h
         }
       }
     })
-    wssHeads.broadcast = (data:any) => wssHeads.clients.forEach((client:any) => client.send(data));
+    const wssHeadsBroadcast = (data:any) => wssHeads.clients.forEach((client:any) => client.send(data));
 
-    wssBlock.broadcast = (data:any) => wssBlock.clients.forEach((client:any) => {
+    const wssBlockBroadcast = (data:any) => wssBlock.clients.forEach((client:any) => {
       try {
         client.send(data);
       } catch (e) {
         logger && logger.error('error on ws: %s', e);
       }
     });
-    wssPeer.broadcast = (data:any) => wssPeer.clients.forEach((client:any) => client.send(data));
+
+    const wssPeerBroadcast = (data:any) => wssPeer.clients.forEach((client:any) => client.send(data));
 
     // Forward current HEAD change
     server
@@ -168,7 +169,7 @@ export const bma = function(server:Server, interfaces:NetworkInterface[]|null, h
             // Broadcast block
             currentBlock = e.block;
             const blockDTO:BlockDTO = BlockDTO.fromJSONObject(currentBlock)
-            wssBlock.broadcast(JSON.stringify(block2HttpBlock(blockDTO)))
+            wssBlockBroadcast(JSON.stringify(block2HttpBlock(blockDTO)))
           } catch (e) {
             logger && logger.error('error on ws mapSync:', e);
           }
@@ -190,11 +191,11 @@ export const bma = function(server:Server, interfaces:NetworkInterface[]|null, h
               signature: peerDTO.signature,
               raw: peerDTO.getRaw()
             }
-            wssPeer.broadcast(JSON.stringify(peerResult));
+            wssPeerBroadcast(JSON.stringify(peerResult));
           }
           // Broadcast heads
           else if (data.ws2p === 'heads' && data.added.length) {
-            wssHeads.broadcast(JSON.stringify(data.added));
+            wssHeadsBroadcast(JSON.stringify(data.added));
           }
         } catch (e) {
           logger && logger.error('error on ws mapSync:', e);
diff --git a/app/modules/ws2p/lib/WS2PConnection.ts b/app/modules/ws2p/lib/WS2PConnection.ts
index dad3bdbee..0f8cf34a7 100644
--- a/app/modules/ws2p/lib/WS2PConnection.ts
+++ b/app/modules/ws2p/lib/WS2PConnection.ts
@@ -20,8 +20,8 @@ import {MembershipDTO} from "../../../lib/dto/MembershipDTO"
 import {TransactionDTO} from "../../../lib/dto/TransactionDTO"
 import {PeerDTO} from "../../../lib/dto/PeerDTO"
 import {WS2PConstants} from './constants';
+import {WebSocket} from "../../../lib/common-libs/websocket"
 
-const ws = require('ws')
 const SocksProxyAgent = require('socks-proxy-agent');
 const nuuid = require('node-uuid');
 const logger = require('../../../lib/logger').NewLogger('ws2p')
@@ -334,7 +334,7 @@ export class WS2PConnection {
           requestTimeout: WS2PConstants.REQUEST_TOR_TIMEOUT
         }
       }
-      const websocket = (proxySocksAddress !== undefined) ? new ws(address, { agent: SocksProxyAgent("socks://"+proxySocksAddress) }):new ws(address)
+      const websocket = (proxySocksAddress !== undefined) ? new WebSocket(address, { agent: SocksProxyAgent("socks://"+proxySocksAddress) }):new WebSocket(address)
     const onWsOpened:Promise<void> = new Promise(res => {
       websocket.on('open', () => res())
     })
diff --git a/app/modules/ws2p/lib/WS2PServer.ts b/app/modules/ws2p/lib/WS2PServer.ts
index d0eec6b8f..a9091d43e 100644
--- a/app/modules/ws2p/lib/WS2PServer.ts
+++ b/app/modules/ws2p/lib/WS2PServer.ts
@@ -20,8 +20,7 @@ import {WS2PConstants} from "./constants"
 import {WS2PMessageHandler} from "./impl/WS2PMessageHandler"
 import {WS2PStreamer} from "./WS2PStreamer"
 import {WS2PSingleWriteStream} from "./WS2PSingleWriteStream"
-
-const WebSocketServer = require('ws').Server
+import {WebSocketServer} from "../../../lib/common-libs/websocket"
 
 export class WS2PServer extends events.EventEmitter {
 
diff --git a/package.json b/package.json
index 9a6d2ee54..b722a32a9 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
     "url": "https://github.com/duniter/duniter/issues"
   },
   "dependencies": {
+    "@types/ws": "^5.1.2",
     "archiver": "1.3.0",
     "async": "2.2.0",
     "bindings": "1.2.1",
diff --git a/test/integration/misc/http-api.ts b/test/integration/misc/http-api.ts
index c79f927dd..349ebabc3 100644
--- a/test/integration/misc/http-api.ts
+++ b/test/integration/misc/http-api.ts
@@ -11,8 +11,6 @@
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU Affero General Public License for more details.
 
-"use strict";
-
 import {ProverConstants} from "../../../app/modules/prover/lib/constants"
 import {NewTestingServer, TestingServer} from "../tools/toolbox"
 import {TestUser} from "../tools/TestUser"
@@ -24,11 +22,11 @@ import {Underscore} from "../../../app/lib/common-libs/underscore"
 import {BlockDTO} from "../../../app/lib/dto/BlockDTO"
 import {shutDownEngine} from "../tools/shutdown-engine"
 import {expectAnswer, expectError} from "../tools/http-expect"
+import {WebSocket} from "../../../app/lib/common-libs/websocket"
 
 const should    = require('should');
 const assert    = require('assert');
 const rp        = require('request-promise');
-const ws        = require('ws');
 
 ProverConstants.CORES_MAXIMUM_USE_IN_PARALLEL = 1
 
@@ -237,7 +235,7 @@ describe("HTTP API", function() {
   describe("/ws", function() {
 
     it('/block should exist', function(done) {
-      const client = new ws('ws://127.0.0.1:7777/ws/block');
+      const client = new WebSocket('ws://127.0.0.1:7777/ws/block');
       client.on('open', function open() {
         client.terminate();
         done();
@@ -246,7 +244,7 @@ describe("HTTP API", function() {
 
     it('/block should send a block', function(done) {
       let completed = false
-      const client = new ws('ws://127.0.0.1:7777/ws/block');
+      const client = new WebSocket('ws://127.0.0.1:7777/ws/block');
       client.once('message', function message(data:any) {
         const block = JSON.parse(data);
         should(block).have.property('number', 4);
@@ -262,7 +260,7 @@ describe("HTTP API", function() {
 
     it('/block (number 5,6,7) should send a block', async () => {
       server2.writeBlock(await commit({ time: now + 120 * 5 }))
-      const client = new ws('ws://127.0.0.1:7777/ws/block');
+      const client = new WebSocket('ws://127.0.0.1:7777/ws/block');
       let resolve5:any, resolve6:any, resolve7:any
       const p5 = new Promise(res => resolve5 = res)
       const p6 = new Promise(res => resolve6 = res)
@@ -293,7 +291,7 @@ describe("HTTP API", function() {
     })
 
     it('/block should answer to pings', function(done) {
-      const client = new ws('ws://127.0.0.1:7777/ws/block');
+      const client = new WebSocket('ws://127.0.0.1:7777/ws/block');
       client.on('pong', function message() {
         client.terminate();
         done();
@@ -304,7 +302,7 @@ describe("HTTP API", function() {
     });
 
     it('/peer (number 5,6,7) should send a peer document', async () => {
-      const client = new ws('ws://127.0.0.1:30410/ws/peer');
+      const client = new WebSocket('ws://127.0.0.1:30410/ws/peer');
       let resolve5:any, resolve6:any
       const p5 = new Promise(res => resolve5 = res)
       const p6 = new Promise(res => resolve6 = res)
diff --git a/test/integration/tools/toolbox.ts b/test/integration/tools/toolbox.ts
index dca1313dc..677c3b2a8 100644
--- a/test/integration/tools/toolbox.ts
+++ b/test/integration/tools/toolbox.ts
@@ -49,11 +49,11 @@ import {DataErrors} from "../../../app/lib/common-libs/errors"
 import {until} from "./test-until"
 import {sync} from "./test-sync"
 import {expectAnswer, expectError, expectJSON} from "./http-expect"
+import {WebSocketServer} from "../../../app/lib/common-libs/websocket"
 
 const assert      = require('assert');
 const rp          = require('request-promise');
 const es          = require('event-stream');
-const WebSocketServer = require('ws').Server
 const logger      = NewLogger();
 
 require('../../../app/modules/bma').BmaDependency.duniter.methods.noLimit(); // Disables the HTTP limiter
@@ -672,10 +672,10 @@ export async function newWS2PBidirectionnalConnection(currency:string, k1:Key, k
       switch (i) {
         case 1:
           s1 = WS2PConnection.newConnectionFromWebSocketServer(ws, serverHandler, new WS2PPubkeyLocalAuth(currency, k1, ""), new WS2PPubkeyRemoteAuth(currency, k1), {
-            connectionTimeout: 100,
-            requestTimeout: 100
+            connectionTimeout: 1000,
+            requestTimeout: 1000
           });
-          s1.connect().catch((e:any) => console.error('WS2P: newConnectionFromWebSocketServer connection error'))
+          s1.connect().catch((e:any) => console.error('WS2P: newConnectionFromWebSocketServer connection error:', e))
           break;
       }
       resolveBefore({
diff --git a/test/integration/ws2p/ws2p_connection.ts b/test/integration/ws2p/ws2p_connection.ts
index 268e1b8e3..84defd19e 100644
--- a/test/integration/ws2p/ws2p_connection.ts
+++ b/test/integration/ws2p/ws2p_connection.ts
@@ -25,9 +25,9 @@ import {WS2PResponse} from "../../../app/modules/ws2p/lib/impl/WS2PResponse"
 import {WS2PConstants} from "../../../app/modules/ws2p/lib/constants"
 import {assertThrows} from "../../unit-tools"
 import {NewLogger} from "../../../app/lib/logger"
+import {WebSocketServer} from "../../../app/lib/common-libs/websocket"
 
 const assert = require('assert');
-const WebSocketServer = require('ws').Server
 const logger = NewLogger()
 const gtest = "gtest"
 
diff --git a/yarn.lock b/yarn.lock
index 628bef378..f2fb84001 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -67,6 +67,13 @@
   version "8.3.0"
   resolved "https://registry.yarnpkg.com/@types/should/-/should-8.3.0.tgz#e2b460243685dbe377182f39ef38d37f4d157ada"
 
+"@types/ws@^5.1.2":
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/@types/ws/-/ws-5.1.2.tgz#f02d3b1cd46db7686734f3ce83bdf46c49decd64"
+  dependencies:
+    "@types/events" "*"
+    "@types/node" "*"
+
 JSONSelect@0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/JSONSelect/-/JSONSelect-0.4.0.tgz#a08edcc67eb3fcbe99ed630855344a0cf282bb8d"
-- 
GitLab