@streamr/dht 102.0.0-beta.1 → 102.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/google/protobuf/any.d.ts +180 -0
- package/dist/generated/google/protobuf/any.js +155 -0
- package/dist/generated/google/protobuf/any.js.map +1 -0
- package/dist/generated/google/protobuf/empty.d.ts +31 -0
- package/dist/generated/google/protobuf/empty.js +32 -0
- package/dist/generated/google/protobuf/empty.js.map +1 -0
- package/dist/generated/google/protobuf/timestamp.d.ts +155 -0
- package/dist/generated/google/protobuf/timestamp.js +136 -0
- package/dist/generated/google/protobuf/timestamp.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.d.ts +361 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js +285 -0
- package/dist/generated/packages/dht/protos/DhtRpc.client.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.d.ts +999 -0
- package/dist/generated/packages/dht/protos/DhtRpc.js +677 -0
- package/dist/generated/packages/dht/protos/DhtRpc.js.map +1 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.d.ts +162 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js +3 -0
- package/dist/generated/packages/dht/protos/DhtRpc.server.js.map +1 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.d.ts +87 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js +66 -0
- package/dist/generated/packages/proto-rpc/protos/ProtoRpc.js.map +1 -0
- package/dist/package.json +7 -7
- package/package.json +7 -7
- package/src/connection/Connection.ts +0 -28
- package/src/connection/ConnectionLockRpcLocal.ts +0 -78
- package/src/connection/ConnectionLockRpcRemote.ts +0 -64
- package/src/connection/ConnectionLockStates.ts +0 -131
- package/src/connection/ConnectionManager.ts +0 -661
- package/src/connection/ConnectionsView.ts +0 -8
- package/src/connection/ConnectorFacade.ts +0 -217
- package/src/connection/Handshaker.ts +0 -209
- package/src/connection/IConnection.ts +0 -40
- package/src/connection/ManagedConnection.ts +0 -113
- package/src/connection/OutputBuffer.ts +0 -28
- package/src/connection/PendingConnection.ts +0 -68
- package/src/connection/connectivityChecker.ts +0 -108
- package/src/connection/connectivityRequestHandler.ts +0 -116
- package/src/connection/simulator/Simulator.ts +0 -369
- package/src/connection/simulator/SimulatorConnection.ts +0 -137
- package/src/connection/simulator/SimulatorConnector.ts +0 -98
- package/src/connection/simulator/SimulatorTransport.ts +0 -15
- package/src/connection/simulator/pings.ts +0 -42
- package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -242
- package/src/connection/webrtc/IWebrtcConnection.ts +0 -24
- package/src/connection/webrtc/NodeWebrtcConnection.ts +0 -245
- package/src/connection/webrtc/WebrtcConnector.ts +0 -234
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +0 -108
- package/src/connection/webrtc/WebrtcConnectorRpcRemote.ts +0 -60
- package/src/connection/webrtc/iceServerAsString.ts +0 -15
- package/src/connection/websocket/AbstractWebsocketClientConnection.ts +0 -122
- package/src/connection/websocket/AutoCertifierClientFacade.ts +0 -89
- package/src/connection/websocket/BrowserWebsocketClientConnection.ts +0 -44
- package/src/connection/websocket/NodeWebsocketClientConnection.ts +0 -39
- package/src/connection/websocket/WebsocketClientConnector.ts +0 -119
- package/src/connection/websocket/WebsocketClientConnectorRpcLocal.ts +0 -38
- package/src/connection/websocket/WebsocketClientConnectorRpcRemote.ts +0 -19
- package/src/connection/websocket/WebsocketServer.ts +0 -164
- package/src/connection/websocket/WebsocketServerConnection.ts +0 -109
- package/src/connection/websocket/WebsocketServerConnector.ts +0 -290
- package/src/dht/DhtNode.ts +0 -683
- package/src/dht/DhtNodeRpcLocal.ts +0 -84
- package/src/dht/DhtNodeRpcRemote.ts +0 -107
- package/src/dht/ExternalApiRpcLocal.ts +0 -58
- package/src/dht/ExternalApiRpcRemote.ts +0 -41
- package/src/dht/PeerManager.ts +0 -305
- package/src/dht/contact/Contact.ts +0 -19
- package/src/dht/contact/ContactList.ts +0 -43
- package/src/dht/contact/RandomContactList.ts +0 -56
- package/src/dht/contact/RingContactList.ts +0 -143
- package/src/dht/contact/RpcRemote.ts +0 -72
- package/src/dht/contact/SortedContactList.ts +0 -173
- package/src/dht/contact/getClosestNodes.ts +0 -24
- package/src/dht/contact/ringIdentifiers.ts +0 -62
- package/src/dht/discovery/DiscoverySession.ts +0 -129
- package/src/dht/discovery/PeerDiscovery.ts +0 -244
- package/src/dht/discovery/RingDiscoverySession.ts +0 -148
- package/src/dht/recursive-operation/RecursiveOperationManager.ts +0 -251
- package/src/dht/recursive-operation/RecursiveOperationRpcLocal.ts +0 -34
- package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +0 -43
- package/src/dht/recursive-operation/RecursiveOperationSession.ts +0 -231
- package/src/dht/recursive-operation/RecursiveOperationSessionRpcLocal.ts +0 -35
- package/src/dht/recursive-operation/RecursiveOperationSessionRpcRemote.ts +0 -30
- package/src/dht/routing/DuplicateDetector.ts +0 -34
- package/src/dht/routing/Router.ts +0 -246
- package/src/dht/routing/RouterRpcLocal.ts +0 -78
- package/src/dht/routing/RouterRpcRemote.ts +0 -80
- package/src/dht/routing/RoutingSession.ts +0 -243
- package/src/dht/routing/RoutingTablesCache.ts +0 -60
- package/src/dht/routing/getPreviousPeer.ts +0 -6
- package/src/dht/store/LocalDataStore.ts +0 -84
- package/src/dht/store/StoreManager.ts +0 -170
- package/src/dht/store/StoreRpcLocal.ts +0 -89
- package/src/dht/store/StoreRpcRemote.ts +0 -32
- package/src/exports.ts +0 -33
- package/src/helpers/AddressTools.ts +0 -28
- package/src/helpers/Connectivity.ts +0 -19
- package/src/helpers/browser/isBrowserEnvironment.ts +0 -1
- package/src/helpers/browser/isBrowserEnvironment_override.ts +0 -3
- package/src/helpers/createPeerDescriptor.ts +0 -57
- package/src/helpers/createPeerDescriptorSignaturePayload.ts +0 -28
- package/src/helpers/debugHelpers.ts +0 -9
- package/src/helpers/errors.ts +0 -49
- package/src/helpers/offering.ts +0 -15
- package/src/helpers/protoClasses.ts +0 -57
- package/src/helpers/protoToString.ts +0 -21
- package/src/helpers/version.ts +0 -32
- package/src/identifiers.ts +0 -29
- package/src/rpc-protocol/DhtCallContext.ts +0 -14
- package/src/rpc-protocol/DhtRpcOptions.ts +0 -10
- package/src/transport/ITransport.ts +0 -37
- package/src/transport/ListeningRpcCommunicator.ts +0 -32
- package/src/transport/RoutingRpcCommunicator.ts +0 -66
- package/src/types/ServiceID.ts +0 -1
- package/src/types/textencoding.d.ts +0 -6
- package/test/benchmark/Find.test.ts +0 -72
- package/test/benchmark/KademliaCorrectness.test.ts +0 -114
- package/test/benchmark/RingCorrectness.test.ts +0 -157
- package/test/benchmark/SortedContactListBenchmark.test.ts +0 -108
- package/test/benchmark/WebsocketServerMemoryLeak.test.ts +0 -41
- package/test/benchmark/hybrid-network-simulation/RingContactList.test.ts +0 -71
- package/test/end-to-end/GeoIpLayer0.test.ts +0 -55
- package/test/end-to-end/Layer0-Layer1.test.ts +0 -93
- package/test/end-to-end/Layer0.test.ts +0 -76
- package/test/end-to-end/Layer0MixedConnectionTypes.test.ts +0 -110
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +0 -137
- package/test/end-to-end/Layer0Webrtc.test.ts +0 -85
- package/test/end-to-end/Layer1-Scale-WebSocket.test.ts +0 -82
- package/test/end-to-end/Layer1-Scale-Webrtc.test.ts +0 -76
- package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +0 -52
- package/test/end-to-end/WebsocketConnectionRequest.test.ts +0 -69
- package/test/end-to-end/memory-leak.test.ts +0 -80
- package/test/integration/ConnectionLocking.test.ts +0 -192
- package/test/integration/ConnectionManager.test.ts +0 -528
- package/test/integration/ConnectivityChecking.test.ts +0 -53
- package/test/integration/DhtJoinPeerDiscovery.test.ts +0 -49
- package/test/integration/DhtNode.test.ts +0 -66
- package/test/integration/DhtNodeExternalAPI.test.ts +0 -48
- package/test/integration/DhtNodeRpcRemote.test.ts +0 -66
- package/test/integration/DhtRpc.test.ts +0 -121
- package/test/integration/Find.test.ts +0 -45
- package/test/integration/GeoIpConnectivityChecking.test.ts +0 -72
- package/test/integration/Layer1-scale.test.ts +0 -189
- package/test/integration/Mock-Layer1-Layer0.test.ts +0 -85
- package/test/integration/MultipleEntryPointJoining.test.ts +0 -105
- package/test/integration/ReplicateData.test.ts +0 -104
- package/test/integration/RouteMessage.test.ts +0 -230
- package/test/integration/RouterRpcRemote.test.ts +0 -77
- package/test/integration/SimultaneousConnections.test.ts +0 -316
- package/test/integration/Store.test.ts +0 -85
- package/test/integration/StoreAndDelete.test.ts +0 -77
- package/test/integration/StoreOnDhtWithThreeNodes.test.ts +0 -59
- package/test/integration/StoreOnDhtWithTwoNodes.test.ts +0 -51
- package/test/integration/StoreRpcRemote.test.ts +0 -54
- package/test/integration/WebrtcConnectionManagement.test.ts +0 -191
- package/test/integration/WebrtcConnectorRpc.test.ts +0 -125
- package/test/integration/Websocket.test.ts +0 -65
- package/test/integration/WebsocketClientConnectorRpc.test.ts +0 -69
- package/test/integration/WebsocketConnectionManagement.test.ts +0 -191
- package/test/integration/rpc-connections-over-webrtc.test.ts +0 -123
- package/test/kademlia-simulation/data/nodeids.json +0 -13002
- package/test/kademlia-simulation/data/orderedneighbors.json +0 -1001
- package/test/types/global.d.ts +0 -1
- package/test/unit/AddressTools.test.ts +0 -44
- package/test/unit/AutoCertifierClientFacade.test.ts +0 -58
- package/test/unit/ConnectionManager.test.ts +0 -65
- package/test/unit/ConnectivityHelpers.test.ts +0 -61
- package/test/unit/DiscoverySession.test.ts +0 -87
- package/test/unit/DuplicateDetector.test.ts +0 -31
- package/test/unit/Handshaker.test.ts +0 -169
- package/test/unit/ListeningRpcCommunicator.test.ts +0 -52
- package/test/unit/LocalDataStore.test.ts +0 -108
- package/test/unit/ManagedConnection.test.ts +0 -58
- package/test/unit/PeerManager.test.ts +0 -93
- package/test/unit/PendingConnection.test.ts +0 -57
- package/test/unit/ProtobufMessage.test.ts +0 -21
- package/test/unit/RandomContactList.test.ts +0 -58
- package/test/unit/RecursiveOperationManager.test.ts +0 -161
- package/test/unit/RecursiveOperationSession.test.ts +0 -68
- package/test/unit/Router.test.ts +0 -137
- package/test/unit/RoutingSession.test.ts +0 -86
- package/test/unit/SortedContactList.test.ts +0 -115
- package/test/unit/StoreManager.test.ts +0 -146
- package/test/unit/StoreRpcLocal.test.ts +0 -167
- package/test/unit/WebrtcConnection.test.ts +0 -29
- package/test/unit/WebrtcConnector.test.ts +0 -56
- package/test/unit/WebsocketClientConnector.test.ts +0 -101
- package/test/unit/WebsocketServer.test.ts +0 -66
- package/test/unit/WebsocketServerConnector.test.ts +0 -102
- package/test/unit/connectivityRequestHandler.test.ts +0 -104
- package/test/unit/createPeerDescriptor.test.ts +0 -69
- package/test/unit/customMatchers.test.ts +0 -34
- package/test/unit/getClosestNodes.test.ts +0 -30
- package/test/unit/version.test.ts +0 -18
- package/test/unit/webrtcReplaceInternalIpWithExternalIp.test.ts +0 -18
- package/test/utils/FakeConnectorFacade.ts +0 -41
- package/test/utils/FakeRpcCommunicator.ts +0 -23
- package/test/utils/FakeTransport.ts +0 -79
- package/test/utils/customMatchers.ts +0 -71
- package/test/utils/mock/MockConnection.ts +0 -26
- package/test/utils/mock/MockConnectionsView.ts +0 -18
- package/test/utils/mock/MockRouter.ts +0 -62
- package/test/utils/mock/MockRpcCommunicator.ts +0 -7
- package/test/utils/mock/MockTransport.ts +0 -26
- package/test/utils/mock/mockDataEntry.ts +0 -38
- package/test/utils/topology.ts +0 -79
- package/test/utils/utils.ts +0 -268
- package/tsconfig.browser.json +0 -17
- package/tsconfig.jest.json +0 -25
- package/tsconfig.json +0 -3
- package/tsconfig.node.json +0 -24
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import EventEmitter from 'eventemitter3'
|
|
2
|
-
import { createRandomConnectionId } from '../Connection'
|
|
3
|
-
import { ConnectionEvents, ConnectionID, ConnectionType, IConnection } from '../IConnection'
|
|
4
|
-
import { Logger } from '@streamr/utils'
|
|
5
|
-
|
|
6
|
-
export interface Socket {
|
|
7
|
-
binaryType: string
|
|
8
|
-
readyState: number
|
|
9
|
-
close(code?: number, reason?: string): void
|
|
10
|
-
send(data: string | Buffer | ArrayBuffer | ArrayBufferView): void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// https://kapeli.com/cheat_sheets/WebSocket_Status_Codes.docset/Contents/Resources/Documents/index
|
|
14
|
-
// Browsers send this automatically when closing a tab
|
|
15
|
-
export const GOING_AWAY = 1001
|
|
16
|
-
// The GOING_AWAY is a reserved code and we shouldn't send that from the application. Therefore
|
|
17
|
-
// we have a custom counterpart
|
|
18
|
-
export const CUSTOM_GOING_AWAY = 3001
|
|
19
|
-
// https://github.com/websockets/ws/blob/master/doc/ws.md#ready-state-constants
|
|
20
|
-
const OPEN = 1
|
|
21
|
-
|
|
22
|
-
const logger = new Logger(module)
|
|
23
|
-
|
|
24
|
-
export abstract class AbstractWebsocketClientConnection extends EventEmitter<ConnectionEvents> implements IConnection {
|
|
25
|
-
|
|
26
|
-
public readonly connectionId: ConnectionID
|
|
27
|
-
protected abstract socket?: Socket
|
|
28
|
-
public connectionType = ConnectionType.WEBSOCKET_CLIENT
|
|
29
|
-
protected destroyed = false
|
|
30
|
-
|
|
31
|
-
constructor() {
|
|
32
|
-
super()
|
|
33
|
-
this.connectionId = createRandomConnectionId()
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// TODO explicit default value for "selfSigned" or make it required
|
|
37
|
-
public abstract connect(address: string, allowSelfSignedCertificate: boolean): void
|
|
38
|
-
|
|
39
|
-
protected abstract stopListening(): void
|
|
40
|
-
|
|
41
|
-
public send(data: Uint8Array): void {
|
|
42
|
-
if (!this.destroyed) {
|
|
43
|
-
if (this.socket && this.socket.readyState === OPEN) {
|
|
44
|
-
logger.trace(`Sending data with size ${data.byteLength}`)
|
|
45
|
-
this.socket?.send(data)
|
|
46
|
-
} else {
|
|
47
|
-
// Could this throw for faster feedback on RPC calls?
|
|
48
|
-
// Currently this log line is seen if a connection is closing but the disconnected event has not been emitted yet.
|
|
49
|
-
logger.debug('Tried to send data on a non-open connection', {
|
|
50
|
-
id: this.connectionId,
|
|
51
|
-
readyState: this.socket!.readyState,
|
|
52
|
-
destroyed: this.destroyed
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
logger.debug('Tried to send() on stopped connection')
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public async close(gracefulLeave: boolean): Promise<void> {
|
|
61
|
-
this.emit('disconnected', gracefulLeave, undefined, 'close() called')
|
|
62
|
-
this.removeAllListeners()
|
|
63
|
-
if (!this.destroyed) {
|
|
64
|
-
logger.trace(`Closing socket for connection ${this.connectionId}`)
|
|
65
|
-
this.socket?.close(gracefulLeave ? CUSTOM_GOING_AWAY : undefined)
|
|
66
|
-
} else {
|
|
67
|
-
logger.debug('Tried to close() a stopped connection', { id: this.connectionId })
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public destroy(): void {
|
|
72
|
-
logger.trace('destroy() a connection')
|
|
73
|
-
if (!this.destroyed) {
|
|
74
|
-
this.removeAllListeners()
|
|
75
|
-
if (this.socket) {
|
|
76
|
-
this.stopListening()
|
|
77
|
-
this.socket.close()
|
|
78
|
-
this.socket = undefined
|
|
79
|
-
}
|
|
80
|
-
this.destroyed = true
|
|
81
|
-
} else {
|
|
82
|
-
logger.debug('Tried to destroy() a stopped connection')
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
protected onOpen(): void {
|
|
87
|
-
if (!this.destroyed) {
|
|
88
|
-
logger.trace('WebSocket Client Connected')
|
|
89
|
-
if (this.socket && this.socket.readyState === OPEN) {
|
|
90
|
-
this.emit('connected')
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
protected onMessage(message: Uint8Array): void {
|
|
96
|
-
this.emit('data', message)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
protected onClose(code: number, reason: string): void {
|
|
100
|
-
if (!this.destroyed) {
|
|
101
|
-
logger.trace('Websocket Closed')
|
|
102
|
-
this.doDisconnect(code, reason)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
protected onError(error: Error): void {
|
|
107
|
-
if (!this.destroyed) {
|
|
108
|
-
logger.trace('WebSocket Client error: ' + error?.message, { error })
|
|
109
|
-
this.emit('error', error.name)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
protected doDisconnect(code?: number, reason?: string): void {
|
|
114
|
-
this.destroyed = true
|
|
115
|
-
this.stopListening()
|
|
116
|
-
this.socket = undefined
|
|
117
|
-
const gracefulLeave = (code === GOING_AWAY) || (code === CUSTOM_GOING_AWAY)
|
|
118
|
-
this.emit('disconnected', gracefulLeave, code, reason)
|
|
119
|
-
this.removeAllListeners()
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AutoCertifierClient,
|
|
3
|
-
HasSessionRequest,
|
|
4
|
-
HasSessionResponse,
|
|
5
|
-
CertifiedSubdomain,
|
|
6
|
-
SERVICE_ID as AUTO_CERTIFIER_SERVICE_ID,
|
|
7
|
-
HasSession
|
|
8
|
-
} from '@streamr/autocertifier-client'
|
|
9
|
-
import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator'
|
|
10
|
-
import { Logger, waitForEvent3 } from '@streamr/utils'
|
|
11
|
-
import { ITransport } from '../../transport/ITransport'
|
|
12
|
-
|
|
13
|
-
const START_TIMEOUT = 60 * 1000
|
|
14
|
-
|
|
15
|
-
const defaultAutoCertifierClientFactory = (
|
|
16
|
-
configFile: string,
|
|
17
|
-
autoCertifierUrl: string,
|
|
18
|
-
autoCertifierRpcCommunicator: ListeningRpcCommunicator,
|
|
19
|
-
wsServerPort: number
|
|
20
|
-
) => new AutoCertifierClient(
|
|
21
|
-
configFile,
|
|
22
|
-
wsServerPort,
|
|
23
|
-
autoCertifierUrl,
|
|
24
|
-
(_serviceId: string, rpcMethodName: string, method: HasSession) => {
|
|
25
|
-
autoCertifierRpcCommunicator.registerRpcMethod(
|
|
26
|
-
HasSessionRequest,
|
|
27
|
-
HasSessionResponse,
|
|
28
|
-
rpcMethodName,
|
|
29
|
-
method
|
|
30
|
-
)
|
|
31
|
-
}
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
export interface IAutoCertifierClient {
|
|
35
|
-
start(): Promise<void>
|
|
36
|
-
stop(): void
|
|
37
|
-
on(eventName: string, cb: (subdomain: CertifiedSubdomain) => void): void
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
interface AutoCertifierClientFacadeOptions {
|
|
41
|
-
url: string
|
|
42
|
-
configFile: string
|
|
43
|
-
transport: ITransport
|
|
44
|
-
wsServerPort: number
|
|
45
|
-
// TODO: setHost and updateCertificate could be passed in a single onCertificateUpdated function.
|
|
46
|
-
setHost: (host: string) => void
|
|
47
|
-
updateCertificate: (certificate: string, privateKey: string) => void
|
|
48
|
-
// TOD: could just pass the client?
|
|
49
|
-
createClientFactory?: () => IAutoCertifierClient
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const logger = new Logger(module)
|
|
53
|
-
|
|
54
|
-
export class AutoCertifierClientFacade {
|
|
55
|
-
|
|
56
|
-
private autoCertifierClient: IAutoCertifierClient
|
|
57
|
-
private readonly rpcCommunicator: ListeningRpcCommunicator
|
|
58
|
-
private readonly options: AutoCertifierClientFacadeOptions
|
|
59
|
-
|
|
60
|
-
constructor(options: AutoCertifierClientFacadeOptions) {
|
|
61
|
-
this.options = options
|
|
62
|
-
this.rpcCommunicator = new ListeningRpcCommunicator(AUTO_CERTIFIER_SERVICE_ID, options.transport)
|
|
63
|
-
this.autoCertifierClient = options.createClientFactory ? options.createClientFactory()
|
|
64
|
-
: defaultAutoCertifierClientFactory(
|
|
65
|
-
options.configFile,
|
|
66
|
-
options.url,
|
|
67
|
-
this.rpcCommunicator,
|
|
68
|
-
options.wsServerPort
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async start(): Promise<void> {
|
|
73
|
-
this.autoCertifierClient.on('updatedCertificate', (subdomain: CertifiedSubdomain) => {
|
|
74
|
-
this.options.setHost(subdomain.fqdn)
|
|
75
|
-
this.options.updateCertificate(subdomain.certificate, subdomain.privateKey)
|
|
76
|
-
logger.trace(`Updated certificate`)
|
|
77
|
-
})
|
|
78
|
-
await Promise.all([
|
|
79
|
-
waitForEvent3(this.autoCertifierClient as any, 'updatedCertificate', START_TIMEOUT),
|
|
80
|
-
this.autoCertifierClient.start()
|
|
81
|
-
])
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
stop(): void {
|
|
85
|
-
this.autoCertifierClient.stop()
|
|
86
|
-
this.rpcCommunicator.destroy()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@streamr/utils'
|
|
2
|
-
import { ICloseEvent, IMessageEvent, w3cwebsocket as Websocket } from 'websocket'
|
|
3
|
-
import { AbstractWebsocketClientConnection } from './AbstractWebsocketClientConnection'
|
|
4
|
-
|
|
5
|
-
const logger = new Logger(module)
|
|
6
|
-
|
|
7
|
-
const BINARY_TYPE = 'arraybuffer'
|
|
8
|
-
|
|
9
|
-
export class WebsocketClientConnection extends AbstractWebsocketClientConnection {
|
|
10
|
-
|
|
11
|
-
protected socket?: Websocket
|
|
12
|
-
|
|
13
|
-
// TODO explicit default value for "selfSigned" or make it required
|
|
14
|
-
public connect(address: string, selfSigned?: boolean): void {
|
|
15
|
-
if (!this.destroyed) {
|
|
16
|
-
this.socket = new Websocket(address, undefined, undefined, undefined, { rejectUnauthorized: !selfSigned })
|
|
17
|
-
this.socket.binaryType = BINARY_TYPE
|
|
18
|
-
this.socket.onerror = (error: Error) => this.onError(error)
|
|
19
|
-
this.socket.onopen = () => this.onOpen()
|
|
20
|
-
this.socket.onclose = (event: ICloseEvent) => this.onClose(event.code, event.reason)
|
|
21
|
-
this.socket.onmessage = (message: IMessageEvent) => {
|
|
22
|
-
if (!this.destroyed) {
|
|
23
|
-
if (typeof message.data === 'string') {
|
|
24
|
-
logger.debug('Received string data, only binary data is supported')
|
|
25
|
-
} else {
|
|
26
|
-
this.onMessage(new Uint8Array(message.data))
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
} else {
|
|
31
|
-
logger.debug('Tried to connect() a stopped connection')
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
protected stopListening(): void {
|
|
36
|
-
if (this.socket) {
|
|
37
|
-
this.socket.onopen = undefined as unknown as (() => void)
|
|
38
|
-
this.socket.onclose = undefined as unknown as (() => void)
|
|
39
|
-
this.socket.onerror = undefined as unknown as (() => void)
|
|
40
|
-
this.socket.onmessage = undefined as unknown as (() => void)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Logger, binaryToUtf8 } from '@streamr/utils'
|
|
2
|
-
import { WebSocket } from 'ws'
|
|
3
|
-
import { AbstractWebsocketClientConnection } from './AbstractWebsocketClientConnection'
|
|
4
|
-
|
|
5
|
-
const logger = new Logger(module)
|
|
6
|
-
|
|
7
|
-
const BINARY_TYPE = 'nodebuffer'
|
|
8
|
-
|
|
9
|
-
export class WebsocketClientConnection extends AbstractWebsocketClientConnection {
|
|
10
|
-
|
|
11
|
-
protected socket?: WebSocket
|
|
12
|
-
|
|
13
|
-
// TODO explicit default value for "selfSigned" or make it required
|
|
14
|
-
public connect(address: string, selfSigned?: boolean): void {
|
|
15
|
-
if (!this.destroyed) {
|
|
16
|
-
this.socket = new WebSocket(address, { rejectUnauthorized: !selfSigned })
|
|
17
|
-
this.socket.binaryType = BINARY_TYPE
|
|
18
|
-
this.socket.on('error', (error: Error) => this.onError(error))
|
|
19
|
-
this.socket.on('open', () => this.onOpen())
|
|
20
|
-
this.socket.on('close', (code: number, reason: Buffer) => this.onClose(code, binaryToUtf8(reason)))
|
|
21
|
-
this.socket.on('message', (message: Buffer, isBinary: boolean) => {
|
|
22
|
-
if (!this.destroyed) {
|
|
23
|
-
if (isBinary === false) {
|
|
24
|
-
logger.debug('Received string data, only binary data is supported')
|
|
25
|
-
} else {
|
|
26
|
-
this.onMessage(new Uint8Array(message))
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
} else {
|
|
31
|
-
logger.debug('Tried to connect() a stopped connection', { id: this.connectionId })
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
protected stopListening(): void {
|
|
36
|
-
this.socket?.removeAllListeners()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { WebsocketClientConnection } from './NodeWebsocketClientConnection'
|
|
2
|
-
import { ConnectionType } from '../IConnection'
|
|
3
|
-
import { ListeningRpcCommunicator } from '../../transport/ListeningRpcCommunicator'
|
|
4
|
-
import { WebsocketClientConnectorRpcLocal } from './WebsocketClientConnectorRpcLocal'
|
|
5
|
-
import {
|
|
6
|
-
ConnectivityMethod,
|
|
7
|
-
PeerDescriptor,
|
|
8
|
-
WebsocketConnectionRequest
|
|
9
|
-
} from '../../../generated/packages/dht/protos/DhtRpc'
|
|
10
|
-
import { WebsocketServer } from './WebsocketServer'
|
|
11
|
-
import { createOutgoingHandshaker } from '../Handshaker'
|
|
12
|
-
import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
|
|
13
|
-
import { expectedConnectionType } from '../../helpers/Connectivity'
|
|
14
|
-
import { Empty } from '../../../generated/google/protobuf/empty'
|
|
15
|
-
import { DhtAddress, toNodeId } from '../../identifiers'
|
|
16
|
-
import { GeoIpLocator } from '@streamr/geoip-location'
|
|
17
|
-
import { PendingConnection } from '../PendingConnection'
|
|
18
|
-
|
|
19
|
-
export type Action = 'connectivityRequest' | 'connectivityProbe'
|
|
20
|
-
|
|
21
|
-
export const connectivityMethodToWebsocketUrl = (ws: ConnectivityMethod, action?: Action): string => {
|
|
22
|
-
return (ws.tls ? 'wss://' : 'ws://') + ws.host + ':' + ws.port + ((action !== undefined) ? '?action=' + action : '')
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface WebsocketClientConnectorOptions {
|
|
26
|
-
onNewConnection: (connection: PendingConnection) => boolean
|
|
27
|
-
hasConnection: (nodeId: DhtAddress) => boolean
|
|
28
|
-
rpcCommunicator: ListeningRpcCommunicator
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export class WebsocketClientConnector {
|
|
32
|
-
|
|
33
|
-
public static readonly WEBSOCKET_CONNECTOR_SERVICE_ID = 'system/websocket-connector'
|
|
34
|
-
private readonly websocketServer?: WebsocketServer
|
|
35
|
-
private geoIpLocator?: GeoIpLocator
|
|
36
|
-
|
|
37
|
-
private localPeerDescriptor?: PeerDescriptor
|
|
38
|
-
private connectingConnections: Map<DhtAddress, PendingConnection> = new Map()
|
|
39
|
-
private abortController = new AbortController()
|
|
40
|
-
private readonly options: WebsocketClientConnectorOptions
|
|
41
|
-
|
|
42
|
-
constructor(options: WebsocketClientConnectorOptions) {
|
|
43
|
-
this.options = options
|
|
44
|
-
|
|
45
|
-
this.registerLocalRpcMethods()
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private registerLocalRpcMethods() {
|
|
49
|
-
const rpcLocal = new WebsocketClientConnectorRpcLocal({
|
|
50
|
-
connect: (targetPeerDescriptor: PeerDescriptor) => this.connect(targetPeerDescriptor),
|
|
51
|
-
hasConnection: (nodeId: DhtAddress): boolean => (this.connectingConnections.has(nodeId)
|
|
52
|
-
|| this.options.hasConnection(nodeId))
|
|
53
|
-
,
|
|
54
|
-
onNewConnection: (connection: PendingConnection) => this.options.onNewConnection(connection),
|
|
55
|
-
abortSignal: this.abortController.signal
|
|
56
|
-
})
|
|
57
|
-
this.options.rpcCommunicator.registerRpcNotification(
|
|
58
|
-
WebsocketConnectionRequest,
|
|
59
|
-
'requestConnection',
|
|
60
|
-
async (req: WebsocketConnectionRequest, context: ServerCallContext): Promise<Empty> => {
|
|
61
|
-
if (!this.abortController.signal.aborted) {
|
|
62
|
-
return rpcLocal.requestConnection(req, context)
|
|
63
|
-
} else {
|
|
64
|
-
return {}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public isPossibleToFormConnection(targetPeerDescriptor: PeerDescriptor): boolean {
|
|
71
|
-
const connectionType = expectedConnectionType(this.localPeerDescriptor!, targetPeerDescriptor)
|
|
72
|
-
return connectionType === ConnectionType.WEBSOCKET_CLIENT
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public connect(targetPeerDescriptor: PeerDescriptor): PendingConnection {
|
|
76
|
-
const nodeId = toNodeId(targetPeerDescriptor)
|
|
77
|
-
const existingConnection = this.connectingConnections.get(nodeId)
|
|
78
|
-
if (existingConnection) {
|
|
79
|
-
return existingConnection
|
|
80
|
-
}
|
|
81
|
-
const socket = new WebsocketClientConnection()
|
|
82
|
-
|
|
83
|
-
const url = connectivityMethodToWebsocketUrl(targetPeerDescriptor.websocket!)
|
|
84
|
-
|
|
85
|
-
const pendingConnection = new PendingConnection(targetPeerDescriptor)
|
|
86
|
-
createOutgoingHandshaker(this.localPeerDescriptor!, pendingConnection, socket, targetPeerDescriptor)
|
|
87
|
-
this.connectingConnections.set(nodeId, pendingConnection)
|
|
88
|
-
|
|
89
|
-
const delFunc = () => {
|
|
90
|
-
if (this.connectingConnections.has(nodeId)) {
|
|
91
|
-
this.connectingConnections.delete(nodeId)
|
|
92
|
-
}
|
|
93
|
-
socket.off('disconnected', delFunc)
|
|
94
|
-
pendingConnection.off('disconnected', delFunc)
|
|
95
|
-
pendingConnection.off('connected', delFunc)
|
|
96
|
-
}
|
|
97
|
-
socket.on('disconnected', delFunc)
|
|
98
|
-
pendingConnection.on('disconnected', delFunc)
|
|
99
|
-
pendingConnection.on('connected', delFunc)
|
|
100
|
-
|
|
101
|
-
socket.connect(url, false)
|
|
102
|
-
|
|
103
|
-
return pendingConnection
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public setLocalPeerDescriptor(peerDescriptor: PeerDescriptor): void {
|
|
107
|
-
this.localPeerDescriptor = peerDescriptor
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
public async destroy(): Promise<void> {
|
|
111
|
-
this.abortController.abort()
|
|
112
|
-
|
|
113
|
-
const requests = Array.from(this.connectingConnections.values())
|
|
114
|
-
await Promise.allSettled(requests.map((conn) => conn.close(true)))
|
|
115
|
-
|
|
116
|
-
await this.websocketServer?.stop()
|
|
117
|
-
this.geoIpLocator?.stop()
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
|
|
2
|
-
import {
|
|
3
|
-
PeerDescriptor,
|
|
4
|
-
WebsocketConnectionRequest
|
|
5
|
-
} from '../../../generated/packages/dht/protos/DhtRpc'
|
|
6
|
-
import { IWebsocketClientConnectorRpc } from '../../../generated/packages/dht/protos/DhtRpc.server'
|
|
7
|
-
import { DhtCallContext } from '../../rpc-protocol/DhtCallContext'
|
|
8
|
-
import { Empty } from '../../../generated/google/protobuf/empty'
|
|
9
|
-
import { toNodeId, DhtAddress } from '../../identifiers'
|
|
10
|
-
import { PendingConnection } from '../PendingConnection'
|
|
11
|
-
|
|
12
|
-
interface WebsocketClientConnectorRpcLocalOptions {
|
|
13
|
-
connect: (targetPeerDescriptor: PeerDescriptor) => PendingConnection
|
|
14
|
-
hasConnection: (nodeId: DhtAddress) => boolean
|
|
15
|
-
onNewConnection: (connection: PendingConnection) => boolean
|
|
16
|
-
abortSignal: AbortSignal
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class WebsocketClientConnectorRpcLocal implements IWebsocketClientConnectorRpc {
|
|
20
|
-
|
|
21
|
-
private readonly options: WebsocketClientConnectorRpcLocalOptions
|
|
22
|
-
|
|
23
|
-
constructor(options: WebsocketClientConnectorRpcLocalOptions) {
|
|
24
|
-
this.options = options
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
public async requestConnection(_request: WebsocketConnectionRequest, context: ServerCallContext): Promise<Empty> {
|
|
28
|
-
if (this.options.abortSignal.aborted) {
|
|
29
|
-
return {}
|
|
30
|
-
}
|
|
31
|
-
const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
|
|
32
|
-
if (!this.options.hasConnection(toNodeId(senderPeerDescriptor))) {
|
|
33
|
-
const connection = this.options.connect(senderPeerDescriptor)
|
|
34
|
-
this.options.onNewConnection(connection)
|
|
35
|
-
}
|
|
36
|
-
return {}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
WebsocketConnectionRequest
|
|
3
|
-
} from '../../../generated/packages/dht/protos/DhtRpc'
|
|
4
|
-
import { Logger } from '@streamr/utils'
|
|
5
|
-
import { RpcRemote } from '../../dht/contact/RpcRemote'
|
|
6
|
-
import { WebsocketClientConnectorRpcClient } from '../../../generated/packages/dht/protos/DhtRpc.client'
|
|
7
|
-
import { toNodeId } from '../../identifiers'
|
|
8
|
-
|
|
9
|
-
const logger = new Logger(module)
|
|
10
|
-
|
|
11
|
-
export class WebsocketClientConnectorRpcRemote extends RpcRemote<WebsocketClientConnectorRpcClient> {
|
|
12
|
-
|
|
13
|
-
async requestConnection(): Promise<void> {
|
|
14
|
-
logger.trace(`Requesting WebSocket connection from ${toNodeId(this.getLocalPeerDescriptor())}`)
|
|
15
|
-
const request: WebsocketConnectionRequest = {}
|
|
16
|
-
const options = this.formDhtRpcOptions()
|
|
17
|
-
return this.getClient().requestConnection(request, options)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { createServer as createHttpServer, Server as HttpServer, IncomingMessage, ServerResponse } from 'http'
|
|
2
|
-
import { createServer as createHttpsServer, Server as HttpsServer } from 'https'
|
|
3
|
-
import EventEmitter from 'eventemitter3'
|
|
4
|
-
import WebSocket from 'ws'
|
|
5
|
-
import { WebsocketServerConnection } from './WebsocketServerConnection'
|
|
6
|
-
import { Logger, asAbortable } from '@streamr/utils'
|
|
7
|
-
import { createSelfSignedCertificate } from '@streamr/autocertifier-client'
|
|
8
|
-
import { WebsocketServerStartError } from '../../helpers/errors'
|
|
9
|
-
import { PortRange, TlsCertificate } from '../ConnectionManager'
|
|
10
|
-
import { range } from 'lodash'
|
|
11
|
-
import fs from 'fs'
|
|
12
|
-
import { v4 as uuid } from 'uuid'
|
|
13
|
-
import { parse } from 'url'
|
|
14
|
-
import { IConnection } from '../IConnection'
|
|
15
|
-
|
|
16
|
-
const logger = new Logger(module)
|
|
17
|
-
|
|
18
|
-
interface WebsocketServerOptions {
|
|
19
|
-
portRange: PortRange
|
|
20
|
-
enableTls: boolean
|
|
21
|
-
tlsCertificate?: TlsCertificate
|
|
22
|
-
maxMessageSize?: number
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface Events {
|
|
26
|
-
connected: ((connection: IConnection) => void)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export class WebsocketServer extends EventEmitter<Events> {
|
|
30
|
-
|
|
31
|
-
private httpServer?: HttpServer | HttpsServer
|
|
32
|
-
private wsServer?: WebSocket.Server
|
|
33
|
-
private readonly abortController = new AbortController()
|
|
34
|
-
private readonly options: WebsocketServerOptions
|
|
35
|
-
|
|
36
|
-
constructor(options: WebsocketServerOptions) {
|
|
37
|
-
super()
|
|
38
|
-
this.options = options
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public async start(): Promise<number> {
|
|
42
|
-
const ports = range(this.options.portRange.min, this.options.portRange.max + 1)
|
|
43
|
-
for (const port of ports) {
|
|
44
|
-
try {
|
|
45
|
-
await asAbortable(this.startServer(port, this.options.enableTls), this.abortController.signal)
|
|
46
|
-
return port
|
|
47
|
-
} catch (err) {
|
|
48
|
-
if (err.originalError?.code === 'EADDRINUSE') {
|
|
49
|
-
logger.debug(`failed to start WebSocket server on port: ${port} reattempting on next port`)
|
|
50
|
-
} else {
|
|
51
|
-
throw new WebsocketServerStartError(err)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
throw new WebsocketServerStartError(
|
|
56
|
-
`Failed to start WebSocket server on any port in range: ${this.options.portRange.min}-${this.options.portRange.min}`
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// If tlsCertificate has been given the tls boolean is ignored
|
|
61
|
-
// TODO: could be simplified?
|
|
62
|
-
private startServer(port: number, tls: boolean): Promise<void> {
|
|
63
|
-
const requestListener = (request: IncomingMessage, response: ServerResponse<IncomingMessage>) => {
|
|
64
|
-
logger.trace('Received request for ' + request.url)
|
|
65
|
-
response.writeHead(404)
|
|
66
|
-
response.end()
|
|
67
|
-
}
|
|
68
|
-
return new Promise((resolve, reject) => {
|
|
69
|
-
if (this.options.tlsCertificate) {
|
|
70
|
-
this.httpServer = createHttpsServer({
|
|
71
|
-
key: fs.readFileSync(this.options.tlsCertificate.privateKeyFileName),
|
|
72
|
-
cert: fs.readFileSync(this.options.tlsCertificate.certFileName)
|
|
73
|
-
}, requestListener)
|
|
74
|
-
} else if (!tls) {
|
|
75
|
-
this.httpServer = createHttpServer(requestListener)
|
|
76
|
-
} else {
|
|
77
|
-
// TODO use options option or named constant?
|
|
78
|
-
const certificate = createSelfSignedCertificate('streamr-self-signed-' + uuid(), 1000)
|
|
79
|
-
this.httpServer = createHttpsServer({
|
|
80
|
-
key: certificate.serverKey,
|
|
81
|
-
cert: certificate.serverCert
|
|
82
|
-
}, requestListener)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function originIsAllowed() {
|
|
86
|
-
return true
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.wsServer = this.createWsServer()
|
|
90
|
-
|
|
91
|
-
this.wsServer.on('connection', (ws: WebSocket, request: IncomingMessage) => {
|
|
92
|
-
logger.trace(`New connection from ${request.socket.remoteAddress}`)
|
|
93
|
-
if (!originIsAllowed()) {
|
|
94
|
-
// Make sure we only accept requests from an allowed origin
|
|
95
|
-
ws.close()
|
|
96
|
-
logger.trace('IConnection from origin ' + request.headers.origin + ' rejected.')
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
this.emit('connected', new WebsocketServerConnection(ws, parse(request.url!), request.socket.remoteAddress!))
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
this.httpServer.on('upgrade', (request, socket, head) => {
|
|
103
|
-
logger.trace('Received upgrade request for ' + request.url)
|
|
104
|
-
this.wsServer!.handleUpgrade(request, socket, head, (ws: WebSocket) => {
|
|
105
|
-
this.wsServer!.emit('connection', ws, request)
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
this.httpServer.once('error', (err: Error) => {
|
|
110
|
-
reject(new WebsocketServerStartError('Starting Websocket server failed', err))
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
this.httpServer.once('listening', () => {
|
|
114
|
-
logger.debug('Websocket server is listening on port ' + port)
|
|
115
|
-
resolve()
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
// Listen only to IPv4 network interfaces, default value listens to IPv6 as well
|
|
120
|
-
this.httpServer.listen(port, '0.0.0.0')
|
|
121
|
-
} catch (e) {
|
|
122
|
-
reject(new WebsocketServerStartError('Websocket server threw an exception', e))
|
|
123
|
-
}
|
|
124
|
-
})
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
public updateCertificate(cert: string, key: string): void {
|
|
128
|
-
(this.httpServer! as HttpsServer).setSecureContext({
|
|
129
|
-
cert,
|
|
130
|
-
key
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
public stop(): Promise<void> {
|
|
135
|
-
this.abortController.abort()
|
|
136
|
-
this.removeAllListeners()
|
|
137
|
-
return new Promise((resolve, _reject) => {
|
|
138
|
-
this.wsServer!.close()
|
|
139
|
-
for (const ws of this.wsServer!.clients) {
|
|
140
|
-
ws.terminate()
|
|
141
|
-
}
|
|
142
|
-
this.httpServer?.once('close', () => {
|
|
143
|
-
// removeAllListeners is maybe not needed?
|
|
144
|
-
this.httpServer?.removeAllListeners()
|
|
145
|
-
resolve()
|
|
146
|
-
})
|
|
147
|
-
this.httpServer?.close()
|
|
148
|
-
// the close method "Stops the server from accepting new connections and closes all
|
|
149
|
-
// connections connected to this server which are not sending a request or waiting for a
|
|
150
|
-
// response." (https://nodejs.org/api/http.html#serverclosecallback)
|
|
151
|
-
// i.e. we need to call closeAllConnections() to close the rest of the connections
|
|
152
|
-
// (in practice this closes the active websocket connections)
|
|
153
|
-
this.httpServer?.closeAllConnections()
|
|
154
|
-
})
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private createWsServer(): WebSocket.Server {
|
|
158
|
-
const maxPayload = this.options.maxMessageSize ?? 1048576
|
|
159
|
-
return this.wsServer = new WebSocket.Server({
|
|
160
|
-
noServer: true,
|
|
161
|
-
maxPayload
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
}
|