'use strict' ; export class FlowController { maxSendOffset : number ; maxReceiveOffset : number ; maxReceiveWindowSize : number ; maxReceiveWindowSizeLimit : number ; writtenOffset : number ; consumedOffset : number ; highestReceivedOffset : number ; lastWindowUpdateAt : number ; constructor ( windowSize , windowSizeLimit ) { this . maxSendOffset = 16 * 1024 ; this . maxReceiveOffset = 16 * 1024 ; this . maxReceiveWindowSize = windowSize ; this . maxReceiveWindowSizeLimit = windowSizeLimit ; this . writtenOffset = 0 ; this . consumedOffset = 0 ; this . highestReceivedOffset = 0 ; this . lastWindowUpdateAt = 0 ; } updateMaxSendOffset ( byteOffset ) { if ( byteOffset > this . maxSendOffset ) { this . maxSendOffset = byteOffset ; return true ; } return false ; } shouldUpdateWindow ( ) { return ( this . maxReceiveOffset - this . consumedOffset ) < ( this . maxReceiveWindowSize / 2 ) ; } updateWindowOffset ( rtt ) { const time = Date . now ( ) ; this . _autoTuning ( rtt , time ) ; this . lastWindowUpdateAt = time ; this . maxReceiveOffset = this . consumedOffset + this . maxReceiveWindowSize ; return this . maxReceiveOffset ; } _autoTuning ( rtt , now ) { if ( this . lastWindowUpdateAt > 0 && this . maxReceiveWindowSize < this . maxReceiveWindowSizeLimit && ( now - this . lastWindowUpdateAt <= rtt * 2 ) ) { this . maxReceiveWindowSize = Math . min ( this . maxReceiveWindowSize * 2 , this . maxReceiveWindowSizeLimit ) ; } } } export class ConnectionFlowController extends FlowController { lastBlockedAt : number ; lastBlockedStreamId : number ; constructor ( windowSize , windowSizeLimit ) { super ( windowSize , windowSizeLimit ) ; this . lastBlockedAt = 0 ; this . lastBlockedStreamId = 0 ; } updateBlockedFrame ( streamId , rcvTime ) { this . lastBlockedAt = rcvTime ; this . lastBlockedStreamId = streamId ; } } export class StreamFlowController extends FlowController { cfc : ConnectionFlowController ; constructor ( windowSize , windowSizeLimit , cfc ) { super ( windowSize , windowSizeLimit ) ; this . cfc = cfc ; } updateWrittenOffset ( byteLen ) { this . writtenOffset += byteLen ; this . cfc . writtenOffset += byteLen ; } updateConsumedOffset ( consumedOffset ) { if ( consumedOffset > this . consumedOffset ) { this . cfc . consumedOffset -= this . consumedOffset ; this . consumedOffset = consumedOffset ; this . cfc . consumedOffset += consumedOffset ; } } updateHighestReceived ( byteOffset ) { if ( byteOffset > this . highestReceivedOffset ) { this . cfc . highestReceivedOffset -= this . highestReceivedOffset ; this . highestReceivedOffset = byteOffset ; this . cfc . highestReceivedOffset += byteOffset ; } } isBlocked ( ) { return this . highestReceivedOffset > this . maxReceiveOffset ; } willBlocked ( byteLen ) { return byteLen > 0 && ( this . maxSendOffset - this . writtenOffset < byteLen ) ; } }