diff --git a/package-lock.json b/package-lock.json index af13fe4c6e..8d32a5e9fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27359,6 +27359,7 @@ "lodash": "^4.17.21", "lru-cache": "^11.0.2", "node-datachannel": "^0.26.0", + "semver": "^7.7.1", "uuid": "^11.1.0", "websocket": "^1.0.34", "ws": "^8.18.1" @@ -27369,6 +27370,7 @@ "@types/heap": "^0.2.34", "@types/k-bucket": "^5.0.1", "@types/lodash": "^4.17.16", + "@types/semver": "^7.5.8", "@types/websocket": "^1.0.10", "@types/ws": "^8.18.0", "jest-leak-detector": "^27.3.1", diff --git a/packages/dht/package.json b/packages/dht/package.json index fb61479866..ecc081b9a1 100644 --- a/packages/dht/package.json +++ b/packages/dht/package.json @@ -52,6 +52,7 @@ "lodash": "^4.17.21", "lru-cache": "^11.0.2", "node-datachannel": "^0.26.0", + "semver": "^7.7.1", "uuid": "^11.1.0", "websocket": "^1.0.34", "ws": "^8.18.1" @@ -62,6 +63,7 @@ "@types/heap": "^0.2.34", "@types/k-bucket": "^5.0.1", "@types/lodash": "^4.17.16", + "@types/semver": "^7.5.8", "@types/websocket": "^1.0.10", "@types/ws": "^8.18.0", "jest-leak-detector": "^27.3.1", diff --git a/packages/dht/protos/DhtRpc.proto b/packages/dht/protos/DhtRpc.proto index 7a36444122..e663555ede 100644 --- a/packages/dht/protos/DhtRpc.proto +++ b/packages/dht/protos/DhtRpc.proto @@ -237,7 +237,7 @@ message HandshakeResponse { enum HandshakeError { DUPLICATE_CONNECTION = 0; INVALID_TARGET_PEER_DESCRIPTOR = 1; - UNSUPPORTED_PROTOCOL_VERSION = 2; + UNSUPPORTED_VERSION = 2; } // Wraps all messages diff --git a/packages/dht/src/connection/Handshaker.ts b/packages/dht/src/connection/Handshaker.ts index f636cf650c..f6b2347392 100644 --- a/packages/dht/src/connection/Handshaker.ts +++ b/packages/dht/src/connection/Handshaker.ts @@ -6,6 +6,7 @@ import { IConnection } from './IConnection' import { LOCAL_PROTOCOL_VERSION, isMaybeSupportedProtocolVersion } from '../helpers/version' import { toNodeId } from '../identifiers' import { PendingConnection } from './PendingConnection' +import semver from 'semver' import { version as applicationVersion } from '../../package.json' const logger = new Logger(module) @@ -36,7 +37,7 @@ export const createOutgoingHandshaker = ( pendingConnection.off('disconnected', managedConnectionDisconnectedListener) } const handshakeFailedListener = (error?: HandshakeError) => { - if (error === HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR || error === HandshakeError.UNSUPPORTED_PROTOCOL_VERSION) { + if (error === HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR || error === HandshakeError.UNSUPPORTED_VERSION) { pendingConnection.close(false) stopHandshaker() } else { @@ -177,7 +178,9 @@ export class Handshaker extends EventEmitter { logger.trace('handshake response received') const handshake = message.body.handshakeResponse const error = !isMaybeSupportedProtocolVersion(handshake.protocolVersion) - ? HandshakeError.UNSUPPORTED_PROTOCOL_VERSION : handshake.error + // All versions before 102.0.0 are not supported + || semver.satisfies(semver.coerce(handshake.applicationVersion)!, '< 102.0.0') + ? HandshakeError.UNSUPPORTED_VERSION : handshake.error if (error !== undefined) { this.emit('handshakeFailed', error) } else { diff --git a/packages/dht/src/connection/webrtc/WebrtcConnector.ts b/packages/dht/src/connection/webrtc/WebrtcConnector.ts index d5ab1170ee..e48bf53f03 100644 --- a/packages/dht/src/connection/webrtc/WebrtcConnector.ts +++ b/packages/dht/src/connection/webrtc/WebrtcConnector.ts @@ -170,7 +170,7 @@ export class WebrtcConnector { }) handshaker.on('handshakeRequest', (_sourceDescriptor: PeerDescriptor, remoteVersion: string) => { if (!isMaybeSupportedProtocolVersion(remoteVersion)) { - rejectHandshake(pendingConnection!, connection, handshaker, HandshakeError.UNSUPPORTED_PROTOCOL_VERSION) + rejectHandshake(pendingConnection!, connection, handshaker, HandshakeError.UNSUPPORTED_VERSION) } else { acceptHandshake(handshaker, pendingConnection, connection) } diff --git a/packages/dht/src/connection/websocket/WebsocketServerConnector.ts b/packages/dht/src/connection/websocket/WebsocketServerConnector.ts index ff9a46847f..6347b50423 100644 --- a/packages/dht/src/connection/websocket/WebsocketServerConnector.ts +++ b/packages/dht/src/connection/websocket/WebsocketServerConnector.ts @@ -133,7 +133,7 @@ export class WebsocketServerConnector { if (this.ongoingConnectRequests.has(nodeId)) { const { pendingConnection, delFunc } = this.ongoingConnectRequests.get(nodeId)! if (!isMaybeSupportedProtocolVersion(remoteProtocolVersion)) { - rejectHandshake(pendingConnection, websocketServerConnection, handshaker, HandshakeError.UNSUPPORTED_PROTOCOL_VERSION) + rejectHandshake(pendingConnection, websocketServerConnection, handshaker, HandshakeError.UNSUPPORTED_VERSION) delFunc() } else if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) { rejectHandshake(pendingConnection, websocketServerConnection, handshaker, HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR) @@ -145,7 +145,7 @@ export class WebsocketServerConnector { const pendingConnection = new PendingConnection(remotePeerDescriptor) if (!isMaybeSupportedProtocolVersion(remoteProtocolVersion)) { - rejectHandshake(pendingConnection, websocketServerConnection, handshaker, HandshakeError.UNSUPPORTED_PROTOCOL_VERSION) + rejectHandshake(pendingConnection, websocketServerConnection, handshaker, HandshakeError.UNSUPPORTED_VERSION) } else if (targetPeerDescriptor && !areEqualPeerDescriptors(this.localPeerDescriptor!, targetPeerDescriptor)) { rejectHandshake(pendingConnection, websocketServerConnection, handshaker, HandshakeError.INVALID_TARGET_PEER_DESCRIPTOR) } else if (this.options.onNewConnection(pendingConnection)) { diff --git a/packages/dht/src/helpers/version.ts b/packages/dht/src/helpers/version.ts index 1b80f668fd..d6c8cdbcdf 100644 --- a/packages/dht/src/helpers/version.ts +++ b/packages/dht/src/helpers/version.ts @@ -6,7 +6,7 @@ export const LOCAL_PROTOCOL_VERSION = '1.1' * * The older version assumes optimistically that it may be supported by the newer * version. It can't know for sure, but the other node will tell if it is not - * supported (e.g. rejecting the handshake with UNSUPPORTED_PROTOCOL_VERSION error). + * supported (e.g. rejecting the handshake with UNSUPPORTED_VERSION error). */ export const isMaybeSupportedProtocolVersion = (remoteVersion: string): boolean => { const localMajor = parseVersion(LOCAL_PROTOCOL_VERSION)!.major diff --git a/packages/dht/test/unit/Handshaker.test.ts b/packages/dht/test/unit/Handshaker.test.ts index d06dbcd32d..ada64fa225 100644 --- a/packages/dht/test/unit/Handshaker.test.ts +++ b/packages/dht/test/unit/Handshaker.test.ts @@ -104,7 +104,7 @@ describe('Handshaker', () => { }) it('onHandshakeFailed unsupported version', () => { - handshaker.emit('handshakeFailed', HandshakeError.UNSUPPORTED_PROTOCOL_VERSION) + handshaker.emit('handshakeFailed', HandshakeError.UNSUPPORTED_VERSION) expect(mockOnHandshakeCompleted).not.toHaveBeenCalled() expect(mockPendingConnectionClose).toHaveBeenCalledTimes(1) })