All files / server/routes/simulation ws-inbound-limiter.ts

100% Statements 12/12
100% Branches 3/3
100% Functions 2/2
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29                      85x 85x 85x   85x 85x       329x 329x 329x 329x 148x 148x      
/**
 * Token bucket for the messages of one WebSocket connection. Legitimate
 * clients stay far below the limit (an analog slider sends at most a few
 * hundred updates per second); a flooding client loses the excess messages
 * instead of turning each one into a write to the sketch's stdin.
 */
export class InboundMessageLimiter {
  private tokens: number;
  private refilledAt: number;
 
  constructor(
    private readonly perSecond: number,
    private readonly burst: number,
    private readonly now: () => number = Date.now,
  ) {
    this.tokens = burst;
    this.refilledAt = now();
  }
 
  tryTake(): boolean {
    const now = this.now();
    this.tokens = Math.min(this.burst, this.tokens + ((now - this.refilledAt) * this.perSecond) / 1000);
    this.refilledAt = now;
    if (this.tokens < 1) return false;
    this.tokens -= 1;
    return true;
  }
}