1
- import * as lp from 'it-length-prefixed '
2
- import { pipe } from 'it-pipe '
1
+ import { TimeoutError } from '@libp2p/interface '
2
+ import { pbStream } from 'it-protobuf-stream '
3
3
import { Message , MessageType } from '../message/dht.js'
4
4
import { AddProviderHandler } from './handlers/add-provider.js'
5
5
import { FindNodeHandler } from './handlers/find-node.js'
@@ -30,6 +30,7 @@ export interface RPCInit {
30
30
metricsPrefix : string
31
31
datastorePrefix : string
32
32
peerInfoMapper : PeerInfoMapper
33
+ incomingMessageTimeout ?: number
33
34
}
34
35
35
36
export interface RPCComponents extends GetValueHandlerComponents , PutValueHandlerComponents , FindNodeHandlerComponents , GetProvidersHandlerComponents {
@@ -38,21 +39,22 @@ export interface RPCComponents extends GetValueHandlerComponents, PutValueHandle
38
39
39
40
export class RPC {
40
41
private readonly handlers : Record < string , DHTMessageHandler >
41
- private readonly routingTable : RoutingTable
42
42
private readonly log : Logger
43
43
private readonly metrics : {
44
44
operations ?: CounterGroup
45
45
errors ?: CounterGroup
46
46
}
47
47
48
+ private readonly incomingMessageTimeout : number
49
+
48
50
constructor ( components : RPCComponents , init : RPCInit ) {
49
51
this . metrics = {
50
52
operations : components . metrics ?. registerCounterGroup ( `${ init . metricsPrefix } _inbound_rpc_requests_total` ) ,
51
53
errors : components . metrics ?. registerCounterGroup ( `${ init . metricsPrefix } _inbound_rpc_errors_total` )
52
54
}
53
55
54
56
this . log = components . logger . forComponent ( `${ init . logPrefix } :rpc` )
55
- this . routingTable = init . routingTable
57
+ this . incomingMessageTimeout = init . incomingMessageTimeout ?? 10_000
56
58
this . handlers = {
57
59
[ MessageType . GET_VALUE . toString ( ) ] : new GetValueHandler ( components , init ) ,
58
60
[ MessageType . PUT_VALUE . toString ( ) ] : new PutValueHandler ( components , init ) ,
@@ -92,34 +94,46 @@ export class RPC {
92
94
* Handle incoming streams on the dht protocol
93
95
*/
94
96
onIncomingStream ( data : IncomingStreamData ) : void {
95
- let message = 'unknown'
97
+ const message = 'unknown'
96
98
97
99
Promise . resolve ( ) . then ( async ( ) => {
98
100
const { stream, connection } = data
99
- const peerId = connection . remotePeer
100
-
101
- const self = this
102
-
103
- await pipe (
104
- stream ,
105
- ( source ) => lp . decode ( source ) ,
106
- async function * ( source ) {
107
- for await ( const msg of source ) {
108
- // handle the message
109
- const desMessage = Message . decode ( msg )
110
- message = desMessage . type
111
- self . log ( 'incoming %s from %p' , desMessage . type , peerId )
112
- const res = await self . handleMessage ( peerId , desMessage )
113
-
114
- // Not all handlers will return a response
115
- if ( res != null ) {
116
- yield Message . encode ( res )
117
- }
101
+
102
+ const abortListener = ( ) : void => {
103
+ stream . abort ( new TimeoutError ( ) )
104
+ }
105
+
106
+ let signal = AbortSignal . timeout ( this . incomingMessageTimeout )
107
+ signal . addEventListener ( 'abort' , abortListener )
108
+
109
+ const messages = pbStream ( stream ) . pb ( Message )
110
+
111
+ try {
112
+ while ( true ) {
113
+ const message = await messages . read ( {
114
+ signal
115
+ } )
116
+
117
+ // handle the message
118
+ this . log ( 'incoming %s from %p' , message . type , connection . remotePeer )
119
+ const res = await this . handleMessage ( connection . remotePeer , message )
120
+
121
+ // Not all handlers will return a response
122
+ if ( res != null ) {
123
+ await messages . write ( res , {
124
+ signal
125
+ } )
118
126
}
119
- } ,
120
- ( source ) => lp . encode ( source ) ,
121
- stream
122
- )
127
+
128
+ // we have received a message so reset the timeout controller to
129
+ // allow the remote to send another
130
+ signal . removeEventListener ( 'abort' , abortListener )
131
+ signal = AbortSignal . timeout ( this . incomingMessageTimeout )
132
+ signal . addEventListener ( 'abort' , abortListener )
133
+ }
134
+ } catch ( err : any ) {
135
+ stream . abort ( err )
136
+ }
123
137
} )
124
138
. catch ( err => {
125
139
this . log . error ( 'error handling %s RPC message from %p - %e' , message , data . connection . remotePeer , err )
0 commit comments