@@ -431,9 +431,8 @@ class RPCServer {
431431 yield await handler ( inputVal , cancel , meta , ctx ) ;
432432 break ;
433433 }
434- for await ( const _ of input ) {
435- // Noop so that stream can close after flushing
436- }
434+ // Noop so that stream can close after flushing
435+ for await ( const _ of input ) ;
437436 } ;
438437 this . registerDuplexStreamHandler ( method , wrapperDuplex , timeout ) ;
439438 }
@@ -498,51 +497,47 @@ class RPCServer {
498497
499498 const prom = ( async ( ) => {
500499 const id = await this . idGen ( ) ;
501- const headTransformStream = middleware . binaryToJsonMessageStream (
500+ const transformStream = middleware . binaryToJsonHeaderMessageStream (
502501 utils . parseJSONRPCRequest ,
503502 ) ;
504503 // Transparent transform used as a point to cancel the input stream from
505504 const passthroughTransform = new TransformStream <
506505 Uint8Array ,
507506 Uint8Array
508507 > ( ) ;
509- const inputStream = passthroughTransform . readable ;
510508 const inputStreamEndProm = rpcStream . readable
511509 . pipeTo ( passthroughTransform . writable )
512510 // Ignore any errors here, we only care that it ended
513511 . catch ( ( ) => { } ) ;
514- void inputStream
515- // Allow us to re-use the readable after reading the first message
516- . pipeTo ( headTransformStream . writable , {
517- preventClose : true ,
518- preventCancel : true ,
519- } )
520- // Ignore any errors here, we only care that it ended
521- . catch ( ( ) => { } ) ;
522512 const cleanUp = async ( reason : any ) => {
523- await inputStream . cancel ( reason ) ;
513+ // Release resources
514+ await transformStream . readable . cancel ( reason ) ;
515+ await transformStream . writable . abort ( reason ) ;
516+ await passthroughTransform . readable . cancel ( reason ) ;
524517 await rpcStream . writable . abort ( reason ) ;
525518 await inputStreamEndProm ;
519+ // Stop the timer
526520 timer . cancel ( cleanupReason ) ;
527521 await timer . catch ( ( ) => { } ) ;
528522 } ;
529- // Read a single empty value to consume the first message
530- const reader = headTransformStream . readable . getReader ( ) ;
523+ passthroughTransform . readable
524+ . pipeTo ( transformStream . writable )
525+ . catch ( ( ) => { } ) ;
526+ const reader = transformStream . readable . getReader ( ) ;
531527 // Allows timing out when waiting for the first message
532528 let headerMessage :
533- | ReadableStreamDefaultReadResult < JSONRPCRequest >
534- | undefined
535- | void ;
529+ | ReadableStreamDefaultReadResult < JSONRPCRequest | Uint8Array >
530+ | undefined ;
536531 try {
537532 headerMessage = await Promise . race ( [
538533 reader . read ( ) ,
539534 timer . then (
540535 ( ) => undefined ,
541- ( ) => { } ,
536+ ( ) => undefined ,
542537 ) ,
543538 ] ) ;
544539 } catch ( e ) {
545- const newErr = new errors . ErrorRPCHandlerFailed (
540+ const err = new errors . ErrorRPCHandlerFailed (
546541 'Stream failed waiting for header' ,
547542 { cause : e } ,
548543 ) ;
@@ -553,49 +548,61 @@ class RPCServer {
553548 new events . RPCErrorEvent ( {
554549 detail : new errors . ErrorRPCOutputStreamError (
555550 'Stream failed waiting for header' ,
556- { cause : newErr } ,
551+ { cause : err } ,
557552 ) ,
558553 } ) ,
559554 ) ;
560555 return ;
561556 }
562557 // Downgrade back to the raw stream
563- await reader . cancel ( ) ;
558+ reader . releaseLock ( ) ;
564559 // There are 2 conditions where we just end here
565560 // 1. The timeout timer resolves before the first message
566561 // 2. the stream ends before the first message
567562 if ( headerMessage == null ) {
568- const newErr = new errors . ErrorRPCTimedOut (
563+ const err = new errors . ErrorRPCTimedOut (
569564 'Timed out waiting for header' ,
570565 { cause : new errors . ErrorRPCStreamEnded ( ) } ,
571566 ) ;
572- await cleanUp ( newErr ) ;
567+ await cleanUp ( err ) ;
573568 this . dispatchEvent (
574569 new events . RPCErrorEvent ( {
575570 detail : new errors . ErrorRPCTimedOut (
576571 'Timed out waiting for header' ,
577572 {
578- cause : newErr ,
573+ cause : err ,
579574 } ,
580575 ) ,
581576 } ) ,
582577 ) ;
583578 return ;
584579 }
585580 if ( headerMessage . done ) {
586- const newErr = new errors . ErrorMissingHeader ( 'Missing header' ) ;
587- await cleanUp ( newErr ) ;
581+ const err = new errors . ErrorMissingHeader ( 'Missing header' ) ;
582+ await cleanUp ( err ) ;
588583 this . dispatchEvent (
589584 new events . RPCErrorEvent ( {
590585 detail : new errors . ErrorRPCOutputStreamError ( ) ,
591586 } ) ,
592587 ) ;
593588 return ;
594589 }
590+ if ( headerMessage . value instanceof Uint8Array ) {
591+ const err = new errors . ErrorRPCParse ( 'Invalid message type' ) ;
592+ await cleanUp ( err ) ;
593+ this . dispatchEvent (
594+ new events . RPCErrorEvent ( {
595+ detail : new errors . ErrorRPCParse ( ) ,
596+ } ) ,
597+ ) ;
598+ return ;
599+ }
595600 const method = headerMessage . value . method ;
596601 const handler = this . handlerMap . get ( method ) ;
597602 if ( handler == null ) {
598- await cleanUp ( new errors . ErrorRPCHandlerFailed ( 'Missing handler' ) ) ;
603+ await cleanUp (
604+ new errors . ErrorRPCHandlerFailed ( `Missing handler for ${ method } ` ) ,
605+ ) ;
599606 return ;
600607 }
601608 if ( abortController . signal . aborted ) {
@@ -617,13 +624,17 @@ class RPCServer {
617624 timer . refresh ( ) ;
618625 }
619626 }
620-
621627 this . logger . info ( `Handling stream with method (${ method } )` ) ;
622628 let handlerResult : [ JSONObject | undefined , ReadableStream < Uint8Array > ] ;
623629 const headerWriter = rpcStream . writable . getWriter ( ) ;
624630 try {
631+ // The as keyword is used here as the middleware will only return the
632+ // first message as a JSONMessage, and others as raw Uint8Arrays.
625633 handlerResult = await handler (
626- [ headerMessage . value , inputStream ] ,
634+ [
635+ headerMessage . value ,
636+ transformStream . readable as ReadableStream < Uint8Array > ,
637+ ] ,
627638 rpcStream . cancel ,
628639 rpcStream . meta ,
629640 { signal : abortController . signal , timer } ,
0 commit comments