@jsprismarine/raknet
Version:
Basic RakNet implementation written in TypeScript
101 lines (98 loc) • 14 kB
JavaScript
import BinaryStream from '@jsprismarine/jsbinaryutils';
import { BitFlags } from './BitFlags.es.js';
import { FrameReliability } from './FrameReliability.es.js';
import assert from 'assert';
const MAX_FRAME_BYTE_LENGTH = 23;
class Frame {
reliability = FrameReliability.UNRELIABLE;
reliableIndex = null;
sequenceIndex = null;
orderIndex = null;
orderChannel;
fragmentSize = 0;
fragmentId;
fragmentIndex;
content;
fromBinary(stream) {
const header = stream.readByte();
this.reliability = (header & 224) >> 5;
const length = Math.ceil(stream.readShort() / 8);
if (this.isReliable()) {
this.reliableIndex = stream.readTriadLE();
}
if (this.isSequenced()) {
this.sequenceIndex = stream.readTriadLE();
}
if (this.isOrdered()) {
this.orderIndex = stream.readTriadLE();
this.orderChannel = stream.readByte();
}
if ((header & BitFlags.SPLIT) > 0) {
this.fragmentSize = stream.readInt();
this.fragmentId = stream.readShort();
this.fragmentIndex = stream.readInt();
}
this.content = stream.read(length);
return this;
}
toBinary() {
const stream = new BinaryStream();
const fragmented = this.isFragmented();
stream.writeByte(this.reliability << 5 | (fragmented ? BitFlags.SPLIT : 0));
stream.writeUnsignedShort(this.content.byteLength << 3);
if (this.isReliable()) {
assert(typeof this.reliableIndex === "number", "Invalid ReliableIndex for reliable Frame");
stream.writeUnsignedTriadLE(this.reliableIndex);
}
if (this.isSequenced()) {
assert(typeof this.sequenceIndex === "number", "Invalid SequenceIndex for sequenced Frame");
stream.writeUnsignedTriadLE(this.sequenceIndex);
}
if (this.isOrdered()) {
assert(typeof this.orderIndex === "number", "Invalid OrderIndex for ordered Frame");
stream.writeUnsignedTriadLE(this.orderIndex);
assert(typeof this.orderChannel === "number", "Invalid OrderChannel for ordered FrameSet");
stream.writeByte(this.orderChannel);
}
if (fragmented) {
stream.writeUnsignedInt(this.fragmentSize);
stream.writeUnsignedShort(this.fragmentId);
stream.writeUnsignedInt(this.fragmentIndex);
}
stream.write(this.content);
return stream;
}
getByteLength() {
return 3 + this.content.byteLength + (this.isReliable() ? 3 : 0) + (this.isSequenced() ? 3 : 0) + (this.isOrdered() ? 4 : 0) + (this.isFragmented() ? 10 : 0);
}
isReliable() {
return [
FrameReliability.RELIABLE,
FrameReliability.RELIABLE_ORDERED,
FrameReliability.RELIABLE_SEQUENCED,
FrameReliability.RELIABLE_WITH_ACK_RECEIPT,
FrameReliability.RELIABLE_ORDERED_WITH_ACK_RECEIPT
].includes(this.reliability);
}
isSequenced() {
return [FrameReliability.RELIABLE_SEQUENCED, FrameReliability.UNRELIABLE_SEQUENCED].includes(this.reliability);
}
isOrdered() {
return [
FrameReliability.UNRELIABLE_SEQUENCED,
FrameReliability.RELIABLE_ORDERED,
FrameReliability.RELIABLE_SEQUENCED,
FrameReliability.RELIABLE_ORDERED_WITH_ACK_RECEIPT
].includes(this.reliability);
}
isOrderedExclusive() {
return [FrameReliability.RELIABLE_ORDERED, FrameReliability.RELIABLE_ORDERED_WITH_ACK_RECEIPT].includes(
this.reliability
);
}
isFragmented() {
return this.fragmentSize > 0;
}
}
export { MAX_FRAME_BYTE_LENGTH, Frame as default };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnJhbWUuZXMuanMiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm90b2NvbC9GcmFtZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQmluYXJ5U3RyZWFtIGZyb20gJ0Bqc3ByaXNtYXJpbmUvanNiaW5hcnl1dGlscyc7XG5pbXBvcnQgQml0RmxhZ3MgZnJvbSAnLi9CaXRGbGFncyc7XG5pbXBvcnQgRnJhbWVSZWxpYWJpbGl0eSBmcm9tICcuL0ZyYW1lUmVsaWFiaWxpdHknO1xuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG4vLyBodHRwczovL2dpdGh1Yi5jb20vZmFjZWJvb2thcmNoaXZlL1Jha05ldC9ibG9iLzFhMTY5ODk1YTkwMGM5ZmM0ODQxYzU1NmUxNjUxNDE4MmI3NWZhZjgvU291cmNlL1JlbGlhYmlsaXR5TGF5ZXIuY3BwI0wxMzNcbi8vIEl0J3MgdGhlIG1heGltdW0gbnVtYmVyIG9mIGJ5dGVzIGEgZnJhbWVzZXQgY2FuIHRha2UuIChzcGxpdHRlZCByZWxpYWJsZSBzZXF1ZW5jZWQpLlxuZXhwb3J0IGNvbnN0IE1BWF9GUkFNRV9CWVRFX0xFTkdUSCA9IDIzO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGcmFtZSB7XG4gICAgcHVibGljIHJlbGlhYmlsaXR5ID0gRnJhbWVSZWxpYWJpbGl0eS5VTlJFTElBQkxFO1xuXG4gICAgcHVibGljIHJlbGlhYmxlSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gICAgcHVibGljIHNlcXVlbmNlSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gICAgcHVibGljIG9yZGVySW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIHB1YmxpYyBvcmRlckNoYW5uZWwhOiBOb25OdWxsYWJsZTxudW1iZXI+O1xuXG4gICAgcHVibGljIGZyYWdtZW50U2l6ZSA9IDA7XG4gICAgcHVibGljIGZyYWdtZW50SWQhOiBudW1iZXI7XG4gICAgcHVibGljIGZyYWdtZW50SW5kZXghOiBudW1iZXI7XG5cbiAgICBwdWJsaWMgY29udGVudCE6IEJ1ZmZlcjtcblxuICAgIHB1YmxpYyBmcm9tQmluYXJ5KHN0cmVhbTogQmluYXJ5U3RyZWFtKTogRnJhbWUge1xuICAgICAgICBjb25zdCBoZWFkZXIgPSBzdHJlYW0ucmVhZEJ5dGUoKTtcbiAgICAgICAgdGhpcy5yZWxpYWJpbGl0eSA9IChoZWFkZXIgJiAweGUwKSA+PiA1O1xuXG4gICAgICAgIC8vIExlbmd0aCBmcm9tIGJpdHMgdG8gYnl0ZXNcbiAgICAgICAgY29uc3QgbGVuZ3RoID0gTWF0aC5jZWlsKHN0cmVhbS5yZWFkU2hvcnQoKSAvIDgpO1xuXG4gICAgICAgIGlmICh0aGlzLmlzUmVsaWFibGUoKSkge1xuICAgICAgICAgICAgdGhpcy5yZWxpYWJsZUluZGV4ID0gc3RyZWFtLnJlYWRUcmlhZExFKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pc1NlcXVlbmNlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLnNlcXVlbmNlSW5kZXggPSBzdHJlYW0ucmVhZFRyaWFkTEUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlzT3JkZXJlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLm9yZGVySW5kZXggPSBzdHJlYW0ucmVhZFRyaWFkTEUoKTtcbiAgICAgICAgICAgIHRoaXMub3JkZXJDaGFubmVsID0gc3RyZWFtLnJlYWRCeXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKGhlYWRlciAmIEJpdEZsYWdzLlNQTElUKSA+IDApIHtcbiAgICAgICAgICAgIHRoaXMuZnJhZ21lbnRTaXplID0gc3RyZWFtLnJlYWRJbnQoKTtcbiAgICAgICAgICAgIHRoaXMuZnJhZ21lbnRJZCA9IHN0cmVhbS5yZWFkU2hvcnQoKTtcbiAgICAgICAgICAgIHRoaXMuZnJhZ21lbnRJbmRleCA9IHN0cmVhbS5yZWFkSW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNvbnRlbnQgPSBzdHJlYW0ucmVhZChsZW5ndGgpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgdG9CaW5hcnkoKTogQmluYXJ5U3RyZWFtIHtcbiAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IEJpbmFyeVN0cmVhbSgpO1xuICAgICAgICBjb25zdCBmcmFnbWVudGVkID0gdGhpcy5pc0ZyYWdtZW50ZWQoKTtcblxuICAgICAgICBzdHJlYW0ud3JpdGVCeXRlKCh0aGlzLnJlbGlhYmlsaXR5IDw8IDUpIHwgKGZyYWdtZW50ZWQgPyBCaXRGbGFncy5TUExJVCA6IDApKTtcbiAgICAgICAgc3RyZWFtLndyaXRlVW5zaWduZWRTaG9ydCh0aGlzLmNvbnRlbnQuYnl0ZUxlbmd0aCA8PCAzKTtcblxuICAgICAgICBpZiAodGhpcy5pc1JlbGlhYmxlKCkpIHtcbiAgICAgICAgICAgIGFzc2VydCh0eXBlb2YgdGhpcy5yZWxpYWJsZUluZGV4ID09PSAnbnVtYmVyJywgJ0ludmFsaWQgUmVsaWFibGVJbmRleCBmb3IgcmVsaWFibGUgRnJhbWUnKTtcbiAgICAgICAgICAgIHN0cmVhbS53cml0ZVVuc2lnbmVkVHJpYWRMRSh0aGlzLnJlbGlhYmxlSW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNTZXF1ZW5jZWQoKSkge1xuICAgICAgICAgICAgYXNzZXJ0KHR5cGVvZiB0aGlzLnNlcXVlbmNlSW5kZXggPT09ICdudW1iZXInLCAnSW52YWxpZCBTZXF1ZW5jZUluZGV4IGZvciBzZXF1ZW5jZWQgRnJhbWUnKTtcbiAgICAgICAgICAgIHN0cmVhbS53cml0ZVVuc2lnbmVkVHJpYWRMRSh0aGlzLnNlcXVlbmNlSW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNPcmRlcmVkKCkpIHtcbiAgICAgICAgICAgIGFzc2VydCh0eXBlb2YgdGhpcy5vcmRlckluZGV4ID09PSAnbnVtYmVyJywgJ0ludmFsaWQgT3JkZXJJbmRleCBmb3Igb3JkZXJlZCBGcmFtZScpO1xuICAgICAgICAgICAgc3RyZWFtLndyaXRlVW5zaWduZWRUcmlhZExFKHRoaXMub3JkZXJJbmRleCk7XG4gICAgICAgICAgICBhc3NlcnQodHlwZW9mIHRoaXMub3JkZXJDaGFubmVsID09PSAnbnVtYmVyJywgJ0ludmFsaWQgT3JkZXJDaGFubmVsIGZvciBvcmRlcmVkIEZyYW1lU2V0Jyk7XG4gICAgICAgICAgICBzdHJlYW0ud3JpdGVCeXRlKHRoaXMub3JkZXJDaGFubmVsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmcmFnbWVudGVkKSB7XG4gICAgICAgICAgICBzdHJlYW0ud3JpdGVVbnNpZ25lZEludCh0aGlzLmZyYWdtZW50U2l6ZSk7XG4gICAgICAgICAgICBzdHJlYW0ud3JpdGVVbnNpZ25lZFNob3J0KHRoaXMuZnJhZ21lbnRJZCk7XG4gICAgICAgICAgICBzdHJlYW0ud3JpdGVVbnNpZ25lZEludCh0aGlzLmZyYWdtZW50SW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RyZWFtLndyaXRlKHRoaXMuY29udGVudCk7XG4gICAgICAgIHJldHVybiBzdHJlYW07XG4gICAgfVxuXG4gICAgcHVibGljIGdldEJ5dGVMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDMgK1xuICAgICAgICAgICAgdGhpcy5jb250ZW50LmJ5dGVMZW5ndGggK1xuICAgICAgICAgICAgKHRoaXMuaXNSZWxpYWJsZSgpID8gMyA6IDApICtcbiAgICAgICAgICAgICh0aGlzLmlzU2VxdWVuY2VkKCkgPyAzIDogMCkgK1xuICAgICAgICAgICAgKHRoaXMuaXNPcmRlcmVkKCkgPyA0IDogMCkgK1xuICAgICAgICAgICAgKHRoaXMuaXNGcmFnbWVudGVkKCkgPyAxMCA6IDApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzUmVsaWFibGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFLFxuICAgICAgICAgICAgRnJhbWVSZWxpYWJpbGl0eS5SRUxJQUJMRV9PUkRFUkVELFxuICAgICAgICAgICAgRnJhbWVSZWxpYWJpbGl0eS5SRUxJQUJMRV9TRVFVRU5DRUQsXG4gICAgICAgICAgICBGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFX1dJVEhfQUNLX1JFQ0VJUFQsXG4gICAgICAgICAgICBGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFX09SREVSRURfV0lUSF9BQ0tfUkVDRUlQVFxuICAgICAgICBdLmluY2x1ZGVzKHRoaXMucmVsaWFiaWxpdHkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1NlcXVlbmNlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIFtGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFX1NFUVVFTkNFRCwgRnJhbWVSZWxpYWJpbGl0eS5VTlJFTElBQkxFX1NFUVVFTkNFRF0uaW5jbHVkZXModGhpcy5yZWxpYWJpbGl0eSk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzT3JkZXJlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIEZyYW1lUmVsaWFiaWxpdHkuVU5SRUxJQUJMRV9TRVFVRU5DRUQsXG4gICAgICAgICAgICBGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFX09SREVSRUQsXG4gICAgICAgICAgICBGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFX1NFUVVFTkNFRCxcbiAgICAgICAgICAgIEZyYW1lUmVsaWFiaWxpdHkuUkVMSUFCTEVfT1JERVJFRF9XSVRIX0FDS19SRUNFSVBUXG4gICAgICAgIF0uaW5jbHVkZXModGhpcy5yZWxpYWJpbGl0eSk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzT3JkZXJlZEV4Y2x1c2l2ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIFtGcmFtZVJlbGlhYmlsaXR5LlJFTElBQkxFX09SREVSRUQsIEZyYW1lUmVsaWFiaWxpdHkuUkVMSUFCTEVfT1JERVJFRF9XSVRIX0FDS19SRUNFSVBUXS5pbmNsdWRlcyhcbiAgICAgICAgICAgIHRoaXMucmVsaWFiaWxpdHlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNGcmFnbWVudGVkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5mcmFnbWVudFNpemUgPiAwO1xuICAgIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQU9PLE1BQU0scUJBQXdCLEdBQUE7QUFFckMsTUFBcUIsS0FBTSxDQUFBO0FBQUEsRUFDaEIsY0FBYyxnQkFBaUIsQ0FBQSxVQUFBO0FBQUEsRUFFL0IsYUFBK0IsR0FBQSxJQUFBO0FBQUEsRUFFL0IsYUFBK0IsR0FBQSxJQUFBO0FBQUEsRUFFL0IsVUFBNEIsR0FBQSxJQUFBO0FBQUEsRUFDNUIsWUFBQTtBQUFBLEVBRUEsWUFBZSxHQUFBLENBQUE7QUFBQSxFQUNmLFVBQUE7QUFBQSxFQUNBLGFBQUE7QUFBQSxFQUVBLE9BQUE7QUFBQSxFQUVBLFdBQVcsTUFBNkIsRUFBQTtBQUMzQyxJQUFNLE1BQUEsTUFBQSxHQUFTLE9BQU8sUUFBUyxFQUFBO0FBQy9CLElBQUssSUFBQSxDQUFBLFdBQUEsR0FBQSxDQUFlLFNBQVMsR0FBUyxLQUFBLENBQUE7QUFHdEMsSUFBQSxNQUFNLFNBQVMsSUFBSyxDQUFBLElBQUEsQ0FBSyxNQUFPLENBQUEsU0FBQSxLQUFjLENBQUMsQ0FBQTtBQUUvQyxJQUFJLElBQUEsSUFBQSxDQUFLLFlBQWMsRUFBQTtBQUNuQixNQUFLLElBQUEsQ0FBQSxhQUFBLEdBQWdCLE9BQU8sV0FBWSxFQUFBO0FBQUE7QUFHNUMsSUFBSSxJQUFBLElBQUEsQ0FBSyxhQUFlLEVBQUE7QUFDcEIsTUFBSyxJQUFBLENBQUEsYUFBQSxHQUFnQixPQUFPLFdBQVksRUFBQTtBQUFBO0FBRzVDLElBQUksSUFBQSxJQUFBLENBQUssV0FBYSxFQUFBO0FBQ2xCLE1BQUssSUFBQSxDQUFBLFVBQUEsR0FBYSxPQUFPLFdBQVksRUFBQTtBQUNyQyxNQUFLLElBQUEsQ0FBQSxZQUFB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