UNPKG

@jsonjoy.com/json-pack

Version:

High-performance JSON serialization library

110 lines 5.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RpcMessageDecoder = void 0; const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader"); const errors_1 = require("./errors"); const messages_1 = require("./messages"); const EMPTY_BUFFER = new Uint8Array(0); const EMPTY_READER = new Reader_1.Reader(EMPTY_BUFFER); class RpcMessageDecoder { decodeMessage(reader) { const startPos = reader.x; try { if (reader.size() < 8) return undefined; const xid = reader.u32(); const msgType = reader.u32(); if (msgType === 0 /* RpcMsgType.CALL */) { if (reader.size() < 20) return (reader.x = startPos), undefined; const rpcvers = reader.u32(); // if (rpcvers !== RPC_VERSION) throw new RpcDecodingError(`Unsupported RPC version: ${rpcvers}`); const prog = reader.u32(); const vers = reader.u32(); const proc = reader.u32(); const cred = this.readOpaqueAuth(reader); if (!cred) return (reader.x = startPos), undefined; const verf = this.readOpaqueAuth(reader); if (!verf) return (reader.x = startPos), undefined; const params = reader.size() > 0 ? reader.cut(reader.size()) : undefined; return new messages_1.RpcCallMessage(xid, rpcvers, prog, vers, proc, cred, verf, params); } else if (msgType === 1 /* RpcMsgType.REPLY */) { if (reader.size() < 4) return (reader.x = startPos), undefined; const replyStat = reader.u32(); if (replyStat === 0 /* RpcReplyStat.MSG_ACCEPTED */) { const verf = this.readOpaqueAuth(reader); if (!verf || reader.size() < 4) return (reader.x = startPos), undefined; const acceptStat = reader.u32(); let mismatchInfo; if (acceptStat === 2 /* RpcAcceptStat.PROG_MISMATCH */) { if (reader.size() < 8) return (reader.x = startPos), undefined; const low = reader.u32(); const high = reader.u32(); mismatchInfo = new messages_1.RpcMismatchInfo(low, high); } const results = reader.size() > 0 ? reader.cut(reader.size()) : undefined; return new messages_1.RpcAcceptedReplyMessage(xid, verf, acceptStat, mismatchInfo, results); } else if (replyStat === 1 /* RpcReplyStat.MSG_DENIED */) { if (reader.size() < 4) return (reader.x = startPos), undefined; const rejectStat = reader.u32(); let mismatchInfo; let authStat; if (rejectStat === 0 /* RpcRejectStat.RPC_MISMATCH */) { if (reader.size() < 8) return (reader.x = startPos), undefined; const low = reader.u32(); const high = reader.u32(); mismatchInfo = new messages_1.RpcMismatchInfo(low, high); if (!mismatchInfo) return (reader.x = startPos), undefined; } else if (rejectStat === 1 /* RpcRejectStat.AUTH_ERROR */) { if (reader.size() < 4) return (reader.x = startPos), undefined; authStat = reader.u32(); } return new messages_1.RpcRejectedReplyMessage(xid, rejectStat, mismatchInfo, authStat); } else { throw new errors_1.RpcDecodingError('Invalid reply_stat'); } } else { throw new errors_1.RpcDecodingError('Invalid msg_type'); } } catch (err) { if (err instanceof RangeError) { reader.x = startPos; return undefined; } throw err; } } readOpaqueAuth(reader) { if (reader.size() < 8) return undefined; const flavor = reader.u32(); const length = reader.u32(); if (length > 400) throw new errors_1.RpcDecodingError('Auth body too large'); const paddedLength = (length + 3) & ~3; if (reader.size() < paddedLength) return undefined; const body = length > 0 ? reader.cut(length) : EMPTY_READER; const padding = paddedLength - length; if (padding > 0) reader.skip(padding); return new messages_1.RpcOpaqueAuth(flavor, body); } } exports.RpcMessageDecoder = RpcMessageDecoder; //# sourceMappingURL=RpcMessageDecoder.js.map