From 678bcd0de52abdd8dc26d3f6ebe05292803813e9 Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Sat, 5 Aug 2023 16:12:39 +0200 Subject: [PATCH 1/2] client: add support for multiple same-type messages over devp2p --- .../client/src/net/protocol/boundprotocol.ts | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/client/src/net/protocol/boundprotocol.ts b/packages/client/src/net/protocol/boundprotocol.ts index 6421a670adc..f67fbfd84c3 100644 --- a/packages/client/src/net/protocol/boundprotocol.ts +++ b/packages/client/src/net/protocol/boundprotocol.ts @@ -1,3 +1,5 @@ +import { Lock } from '@ethereumjs/util' + import { Event } from '../../types' import type { Config } from '../../config' @@ -161,26 +163,39 @@ export class BoundProtocol { */ async request(name: string, args: any[]): Promise { const message = this.send(name, args) - const resolver: any = { - timeout: null, - resolve: null, - reject: null, - } + let lock if ( typeof message.response === 'number' && this.resolvers.get(message.response) !== undefined ) { - throw new Error(`Only one active request allowed per message type (${name})`) + const res = this.resolvers.get(message.response) + lock = res.lock + await res.lock.acquire() + } + const resolver: any = { + timeout: null, + resolve: null, + reject: null, + lock: lock ?? new Lock(), } this.resolvers.set(message.response!, resolver) + if (lock === undefined) { + await resolver.lock.acquire() + } return new Promise((resolve, reject) => { resolver.timeout = setTimeout(() => { resolver.timeout = null this.resolvers.delete(message.response!) reject(new Error(`Request timed out after ${this.timeout}ms`)) }, this.timeout) - resolver.resolve = resolve - resolver.reject = reject + resolver.resolve = function (e: any) { + resolver.lock.release() + resolve(e) + } + resolver.reject = function (e: any) { + resolver.lock.release() + reject(e) + } }) } From 95a3eb760925b2cdf95a69d7ccc0c5d68bf5da5d Mon Sep 17 00:00:00 2001 From: Jochem Brouwer Date: Sat, 5 Aug 2023 19:33:08 +0200 Subject: [PATCH 2/2] client/net/sync/boundprotocol: fix timeout deadlock --- packages/client/src/net/protocol/boundprotocol.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/client/src/net/protocol/boundprotocol.ts b/packages/client/src/net/protocol/boundprotocol.ts index f67fbfd84c3..b7a9b7df8cd 100644 --- a/packages/client/src/net/protocol/boundprotocol.ts +++ b/packages/client/src/net/protocol/boundprotocol.ts @@ -183,11 +183,6 @@ export class BoundProtocol { await resolver.lock.acquire() } return new Promise((resolve, reject) => { - resolver.timeout = setTimeout(() => { - resolver.timeout = null - this.resolvers.delete(message.response!) - reject(new Error(`Request timed out after ${this.timeout}ms`)) - }, this.timeout) resolver.resolve = function (e: any) { resolver.lock.release() resolve(e) @@ -196,6 +191,11 @@ export class BoundProtocol { resolver.lock.release() reject(e) } + resolver.timeout = setTimeout(() => { + resolver.timeout = null + this.resolvers.delete(message.response!) + resolver.reject(new Error(`Request timed out after ${this.timeout}ms`)) + }, this.timeout) }) }