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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 7x 7x 7x 7x 7x 7x 147x 147x 147x 147x 147x 147x 87x 84x 84x 84x 84x 84x 83x 83x 83x 83x 83x 60x 59x 59x 59x 42x 42x 42x 42x 5x 5x 5x 5x 42x 42x 17x 16x 16x 16x 6x 6x 6x 6x 6x 10x 10x 10x 16x 1x 1x 3x 3x 209x 209x 209x 209x 208x 208x 208x 208x 208x 208x | import {Reader} from '@jsonjoy.com/buffers/lib/Reader';
import {RpcMsgType, RpcReplyStat, RpcAcceptStat, RpcRejectStat} from './constants';
import {RpcDecodingError} from './errors';
import {
RpcOpaqueAuth,
RpcCallMessage,
RpcAcceptedReplyMessage,
RpcRejectedReplyMessage,
type RpcMessage,
RpcMismatchInfo,
} from './messages';
const EMPTY_BUFFER = new Uint8Array(0);
const EMPTY_READER = new Reader(EMPTY_BUFFER);
export class RpcMessageDecoder {
public decodeMessage(reader: Reader): RpcMessage | undefined {
const startPos = reader.x;
try {
Iif (reader.size() < 8) return undefined;
const xid = reader.u32();
const msgType = reader.u32();
if (msgType === 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);
Iif (!cred) return (reader.x = startPos), undefined;
const verf = this.readOpaqueAuth(reader);
Iif (!verf) return (reader.x = startPos), undefined;
const params = reader.size() > 0 ? reader.cut(reader.size()) : undefined;
return new RpcCallMessage(xid, rpcvers, prog, vers, proc, cred, verf, params);
} else if (msgType === RpcMsgType.REPLY) {
Iif (reader.size() < 4) return (reader.x = startPos), undefined;
const replyStat = reader.u32();
if (replyStat === RpcReplyStat.MSG_ACCEPTED) {
const verf = this.readOpaqueAuth(reader);
Iif (!verf || reader.size() < 4) return (reader.x = startPos), undefined;
const acceptStat = reader.u32();
let mismatchInfo: RpcMismatchInfo | undefined;
if (acceptStat === RpcAcceptStat.PROG_MISMATCH) {
Iif (reader.size() < 8) return (reader.x = startPos), undefined;
const low = reader.u32();
const high = reader.u32();
mismatchInfo = new RpcMismatchInfo(low, high);
}
const results = reader.size() > 0 ? reader.cut(reader.size()) : undefined;
return new RpcAcceptedReplyMessage(xid, verf, acceptStat, mismatchInfo, results);
} else if (replyStat === RpcReplyStat.MSG_DENIED) {
Iif (reader.size() < 4) return (reader.x = startPos), undefined;
const rejectStat = reader.u32();
let mismatchInfo: RpcMismatchInfo | undefined;
let authStat: number | undefined;
if (rejectStat === RpcRejectStat.RPC_MISMATCH) {
Iif (reader.size() < 8) return (reader.x = startPos), undefined;
const low = reader.u32();
const high = reader.u32();
mismatchInfo = new RpcMismatchInfo(low, high);
Iif (!mismatchInfo) return (reader.x = startPos), undefined;
} else Eif (rejectStat === RpcRejectStat.AUTH_ERROR) {
Iif (reader.size() < 4) return (reader.x = startPos), undefined;
authStat = reader.u32();
}
return new RpcRejectedReplyMessage(xid, rejectStat, mismatchInfo, authStat);
} else {
throw new RpcDecodingError('Invalid reply_stat');
}
} else {
throw new RpcDecodingError('Invalid msg_type');
}
} catch (err) {
Iif (err instanceof RangeError) {
reader.x = startPos;
return undefined;
}
throw err;
}
}
private readOpaqueAuth(reader: Reader): RpcOpaqueAuth | undefined {
Iif (reader.size() < 8) return undefined;
const flavor = reader.u32();
const length = reader.u32();
if (length > 400) throw new RpcDecodingError('Auth body too large');
const paddedLength = (length + 3) & ~3;
Iif (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 RpcOpaqueAuth(flavor, body);
}
}
|