@@ -4,7 +4,6 @@ import { anySignal } from 'any-signal'
44import { CID } from 'multiformats/cid'
55import { sha256 } from 'multiformats/hashes/sha2'
66import { codes } from '../errors.js'
7- import { DEFAULT_DATA_LIMIT , DEFAULT_DURATION_LIMIT } from './constants.js'
87import type { Limit } from './pb/index.js'
98import type { Stream } from '@libp2p/interface/connection'
109import type { Source } from 'it-stream-types'
@@ -13,6 +12,8 @@ import type { Uint8ArrayList } from 'uint8arraylist'
1312const log = logger ( 'libp2p:circuit-relay:utils' )
1413
1514async function * countStreamBytes ( source : Source < Uint8Array | Uint8ArrayList > , limit : { remaining : bigint } ) : AsyncGenerator < Uint8Array | Uint8ArrayList , void , unknown > {
15+ const limitBytes = limit . remaining
16+
1617 for await ( const buf of source ) {
1718 const len = BigInt ( buf . byteLength )
1819
@@ -29,15 +30,15 @@ async function * countStreamBytes (source: Source<Uint8Array | Uint8ArrayList>,
2930 log . error ( err )
3031 }
3132
32- throw new Error ( ' data limit exceeded' )
33+ throw new CodeError ( ` data limit of ${ limitBytes } bytes exceeded` , codes . ERR_TRANSFER_LIMIT_EXCEEDED )
3334 }
3435
3536 limit . remaining -= len
3637 yield buf
3738 }
3839}
3940
40- const doRelay = ( src : Stream , dst : Stream , abortSignal : AbortSignal , limit : Required < Limit > ) : void => {
41+ export function createLimitedRelay ( src : Stream , dst : Stream , abortSignal : AbortSignal , limit ?: Limit ) : void {
4142 function abortStreams ( err : Error ) : void {
4243 src . abort ( err )
4344 dst . abort ( err )
@@ -47,25 +48,33 @@ const doRelay = (src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Requ
4748 const abortController = new AbortController ( )
4849 const signal = anySignal ( [ abortSignal , abortController . signal ] )
4950
50- const timeout = setTimeout ( ( ) => {
51- abortController . abort ( )
52- } , limit . duration )
51+ let timeout : ReturnType < typeof setTimeout > | undefined
52+
53+ if ( limit ?. duration != null ) {
54+ timeout = setTimeout ( ( ) => {
55+ abortController . abort ( )
56+ } , limit . duration )
57+ }
5358
5459 let srcDstFinished = false
5560 let dstSrcFinished = false
5661
57- const dataLimit = {
58- remaining : limit . data
62+ let dataLimit : { remaining : bigint } | undefined
63+
64+ if ( limit ?. data != null ) {
65+ dataLimit = {
66+ remaining : limit . data
67+ }
5968 }
6069
6170 queueMicrotask ( ( ) => {
6271 const onAbort = ( ) : void => {
63- dst . abort ( new CodeError ( ' duration limit exceeded' , codes . ERR_TIMEOUT ) )
72+ dst . abort ( new CodeError ( ` duration limit of ${ limit ?. duration } ms exceeded` , codes . ERR_TRANSFER_LIMIT_EXCEEDED ) )
6473 }
6574
6675 signal . addEventListener ( 'abort' , onAbort , { once : true } )
6776
68- void dst . sink ( countStreamBytes ( src . source , dataLimit ) )
77+ void dst . sink ( dataLimit == null ? src . source : countStreamBytes ( src . source , dataLimit ) )
6978 . catch ( err => {
7079 log . error ( 'error while relaying streams src -> dst' , err )
7180 abortStreams ( err )
@@ -83,12 +92,12 @@ const doRelay = (src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Requ
8392
8493 queueMicrotask ( ( ) => {
8594 const onAbort = ( ) : void => {
86- src . abort ( new CodeError ( ' duration limit exceeded' , codes . ERR_TIMEOUT ) )
95+ src . abort ( new CodeError ( ` duration limit of ${ limit ?. duration } ms exceeded` , codes . ERR_TRANSFER_LIMIT_EXCEEDED ) )
8796 }
8897
8998 signal . addEventListener ( 'abort' , onAbort , { once : true } )
9099
91- void src . sink ( countStreamBytes ( dst . source , dataLimit ) )
100+ void src . sink ( dataLimit == null ? dst . source : countStreamBytes ( dst . source , dataLimit ) )
92101 . catch ( err => {
93102 log . error ( 'error while relaying streams dst -> src' , err )
94103 abortStreams ( err )
@@ -105,16 +114,6 @@ const doRelay = (src: Stream, dst: Stream, abortSignal: AbortSignal, limit: Requ
105114 } )
106115}
107116
108- export function createLimitedRelay ( source : Stream , destination : Stream , abortSignal : AbortSignal , limit ?: Limit ) : void {
109- const dataLimit = limit ?. data ?? BigInt ( DEFAULT_DATA_LIMIT )
110- const durationLimit = limit ?. duration ?? DEFAULT_DURATION_LIMIT
111-
112- doRelay ( source , destination , abortSignal , {
113- data : dataLimit ,
114- duration : durationLimit
115- } )
116- }
117-
118117/**
119118 * Convert a namespace string into a cid
120119 */
0 commit comments