UNPKG

rsocket-rxjs

Version:
211 lines (210 loc) 8.41 kB
import { getUint64 } from '../../utlities/conversions'; import { Payload } from './payload'; export var FrameType; (function (FrameType) { FrameType[FrameType["SETUP"] = 1] = "SETUP"; FrameType[FrameType["LEASE"] = 2] = "LEASE"; FrameType[FrameType["KEEPALIVE"] = 3] = "KEEPALIVE"; FrameType[FrameType["REQUEST_RESPONSE"] = 4] = "REQUEST_RESPONSE"; FrameType[FrameType["REQUEST_FNF"] = 5] = "REQUEST_FNF"; FrameType[FrameType["REQUEST_STREAM"] = 6] = "REQUEST_STREAM"; FrameType[FrameType["REQUEST_CHANNEL"] = 7] = "REQUEST_CHANNEL"; FrameType[FrameType["REQUEST_N"] = 8] = "REQUEST_N"; FrameType[FrameType["CANCEL"] = 9] = "CANCEL"; FrameType[FrameType["PAYLOAD"] = 10] = "PAYLOAD"; FrameType[FrameType["ERROR"] = 11] = "ERROR"; FrameType[FrameType["METADATA_PUSH"] = 12] = "METADATA_PUSH"; FrameType[FrameType["RESUME"] = 13] = "RESUME"; FrameType[FrameType["RESUME_OK"] = 14] = "RESUME_OK"; FrameType[FrameType["EXT"] = 63] = "EXT"; })(FrameType || (FrameType = {})); export var ErrorCode; (function (ErrorCode) { ErrorCode[ErrorCode["RESERVED"] = 0] = "RESERVED"; ErrorCode[ErrorCode["INVALID_SETUP"] = 1] = "INVALID_SETUP"; ErrorCode[ErrorCode["UNSUPPORTED_SETUP"] = 2] = "UNSUPPORTED_SETUP"; ErrorCode[ErrorCode["REJECTED_SETUP"] = 3] = "REJECTED_SETUP"; ErrorCode[ErrorCode["REJECTED_RESUME"] = 4] = "REJECTED_RESUME"; ErrorCode[ErrorCode["CONNECTION_ERROR"] = 257] = "CONNECTION_ERROR"; ErrorCode[ErrorCode["CONNECTION_CLOSE"] = 258] = "CONNECTION_CLOSE"; ErrorCode[ErrorCode["APPLICATION_ERROR"] = 513] = "APPLICATION_ERROR"; ErrorCode[ErrorCode["REJECTED"] = 514] = "REJECTED"; ErrorCode[ErrorCode["CANCELED"] = 515] = "CANCELED"; ErrorCode[ErrorCode["INVALID"] = 516] = "INVALID"; ErrorCode[ErrorCode["RESERVED_EXT"] = 4294967295] = "RESERVED_EXT"; })(ErrorCode || (ErrorCode = {})); /** * Flyweight around a buffer that gives access to frame type etc... */ export class Frame { /** * * @param buffer Containing frame data */ constructor(buffer) { this.buffer = buffer; this.view = new DataView(buffer.buffer); } streamId() { return this.view.getUint32(0); } type() { return this.view.getUint16(4) >> 10; } metadataPresent() { return ((this.view.getUint16(4) >> 8) & 1) == 1; } resumeEnable() { return ((this.view.getUint16(4)) & 7) == 1; } willHonorLease() { return ((this.view.getUint16(4) >> 6) & 1) == 1; } majorVersion() { return this.view.getUint16(6); } minorVersion() { return this.view.getUint16(8); } timeBetweenKeeaplive() { return this.view.getUint32(10); } maxLifetime() { return this.view.getUint32(14); } /** * Only meaningful if resume enabled! */ tokenLength() { return this.view.getUint16(18); } /** * Only meaningful if resume enabled! */ resumeIdentificationToken() { return new Uint8Array(this.buffer.buffer, 20, this.tokenLength()); } getResumeEnableOffset() { if (this.resumeEnable()) { return 20 + this.tokenLength(); } else { return 18; } } metadataMimeLength() { return this.view.getUint8(this.getResumeEnableOffset()); } metadataMimeType() { const start = this.getResumeEnableOffset() + 1; return new Uint8Array(this.buffer.buffer, start, this.metadataMimeLength()); } dataMimeLength() { return this.view.getUint8(this.getResumeEnableOffset() + 1 + this.metadataMimeLength()); } dataMimeType() { const start = this.getResumeEnableOffset() + 1 + this.metadataMimeLength() + 1; return new Uint8Array(this.buffer.buffer, start, this.dataMimeLength()); } errorCode() { return this.view.getInt32(6); } timeToLive() { return this.view.getUint32(6); } numberOfRequest() { return this.view.getUint32(10); } respondWithKeepalive() { return (((this.view.getUint16(4)) >> 7) & 1) == 1; } lastReceivedPosition() { return getUint64(this.view, 6); } fragmentFollows() { return (((this.view.getUint16(4)) >> 7) & 1) == 1; } initialRequests() { return this.view.getUint32(6); } isStreamComplete() { return (((this.view.getUint16(4)) >> 6) & 1) == 1; } requests() { return this.initialRequests(); } isNext() { return (((this.view.getUint16(4)) >> 5) & 1) == 1; } metadataPushData() { return new Uint8Array(this.buffer.buffer, 6); } canBeIgnored() { return ((this.view.getUint8(4) >> 6) & 1) == 1; } extendedType() { return this.view.getUint32(6); } metadataLength(offset) { if (this.metadataPresent() == false) { return 0; } else { return (this.view.getUint8(offset + 2) | (this.view.getUint8(offset + 1) << 8) | (this.view.getUint8(offset) << 16)); } } payload() { switch (this.type()) { case FrameType.SETUP: const offset = this.getResumeEnableOffset() + 1 + this.metadataMimeLength() + 1 + this.dataMimeLength(); if (this.metadataPresent()) { return new Payload(new Uint8Array(this.buffer.buffer, offset + 3 + this.metadataLength(offset)), new Uint8Array(this.buffer.buffer, offset + 3, this.metadataLength(offset))); } else { return new Payload(new Uint8Array(this.buffer.buffer, offset)); } case FrameType.ERROR: return new Payload(new Uint8Array(this.buffer.buffer, 10)); case FrameType.LEASE: if (this.metadataPresent()) { return new Payload(new Uint8Array(this.buffer.buffer, 14 + 3 + this.metadataLength(14)), new Uint8Array(this.buffer.buffer, 14 + 3, this.metadataLength(3))); } else { return new Payload(new Uint8Array(this.buffer.buffer, 14)); } case FrameType.KEEPALIVE: return new Payload(new Uint8Array(this.buffer.buffer, 14)); case FrameType.REQUEST_RESPONSE: case FrameType.REQUEST_FNF: case FrameType.PAYLOAD: if (this.metadataPresent()) { return new Payload(new Uint8Array(this.buffer.buffer, 6 + 3 + this.metadataLength(6)), new Uint8Array(this.buffer.buffer, 6 + 3, this.metadataLength(6))); } else { return new Payload(new Uint8Array(this.buffer.buffer, 6)); } case FrameType.REQUEST_STREAM: case FrameType.REQUEST_CHANNEL: if (this.metadataPresent()) { return new Payload(new Uint8Array(this.buffer.buffer, 10 + 3 + this.metadataLength(10)), new Uint8Array(this.buffer.buffer, 10 + 3, this.metadataLength(10))); } else { return new Payload(new Uint8Array(this.buffer.buffer, 10)); } case FrameType.REQUEST_N: throw new Error('Frame Type REQUEST_N does not have payload attached!'); case FrameType.CANCEL: throw new Error('Frame Type CANCEL does not have payload attached!'); case FrameType.METADATA_PUSH: throw new Error('Frame Type METADATA_PUSH has no payload attached. Get using metadataPushData()'); case FrameType.EXT: // TODO : As I never used this feature I don't understand it... Probably needs work if (this.metadataPresent()) { return new Payload(new Uint8Array(this.buffer.buffer, 10 + 3 + this.metadataLength(10)), new Uint8Array(this.buffer.buffer, 10 + 3, this.metadataLength(10))); } else { return new Payload(new Uint8Array(this.buffer.buffer, 10)); } } } }