@cliz/inlets
Version:
Cloud Native Tunnel
86 lines (85 loc) • 2.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowController = void 0;
class FlowController {
constructor(defaultMaxWindowSize, onBackpressure) {
this.windows = new Map();
this.defaultMaxWindowSize = 1024 * 1024;
if (defaultMaxWindowSize) {
this.defaultMaxWindowSize = defaultMaxWindowSize;
}
this.onBackpressure = onBackpressure;
}
initializeStream(streamId, maxWindowSize) {
const windowSize = maxWindowSize || this.defaultMaxWindowSize;
this.windows.set(streamId, {
sendWindow: 0,
receiveWindow: windowSize,
maxWindowSize: windowSize,
});
}
canSend(streamId, size) {
const window = this.windows.get(streamId);
if (!window) {
this.initializeStream(streamId);
return this.canSend(streamId, size);
}
return window.sendWindow + size <= window.maxWindowSize;
}
send(streamId, size) {
if (!this.canSend(streamId, size)) {
if (this.onBackpressure) {
this.onBackpressure(streamId, true);
}
return false;
}
const window = this.windows.get(streamId);
if (window) {
window.sendWindow += size;
}
return true;
}
onAck(streamId, ackedSize) {
const window = this.windows.get(streamId);
if (window) {
window.sendWindow = Math.max(0, window.sendWindow - ackedSize);
if (window.sendWindow < window.maxWindowSize * 0.5 && this.onBackpressure) {
this.onBackpressure(streamId, false);
}
}
}
receive(streamId, size) {
const window = this.windows.get(streamId);
if (!window) {
this.initializeStream(streamId);
return this.receive(streamId, size);
}
if (window.receiveWindow < size) {
if (this.onBackpressure) {
this.onBackpressure(streamId, true);
}
return false;
}
window.receiveWindow -= size;
return true;
}
releaseReceiveWindow(streamId, size) {
const window = this.windows.get(streamId);
if (window) {
window.receiveWindow = Math.min(window.maxWindowSize, window.receiveWindow + size);
if (window.receiveWindow > window.maxWindowSize * 0.5 && this.onBackpressure) {
this.onBackpressure(streamId, false);
}
}
}
getWindowState(streamId) {
return this.windows.get(streamId);
}
removeStream(streamId) {
this.windows.delete(streamId);
}
clear() {
this.windows.clear();
}
}
exports.FlowController = FlowController;