|
| 1 | +import {Writer} from '@jsonjoy.com/util/lib/buffers/Writer'; |
| 2 | +import {Nfsv3Encoder} from './Nfsv3Encoder'; |
| 3 | +import {RpcMessageEncoder} from '../../rpc/RpcMessageEncoder'; |
| 4 | +import {RmRecordEncoder} from '../../rm/RmRecordEncoder'; |
| 5 | +import {Nfsv3Proc, Nfsv3Const} from './constants'; |
| 6 | +import {RpcOpaqueAuth} from '../../rpc/messages'; |
| 7 | +import {RpcAcceptStat} from '../../rpc/constants'; |
| 8 | +import type * as msg from './messages'; |
| 9 | +import type {IWriter, IWriterGrowable} from '@jsonjoy.com/util/lib/buffers'; |
| 10 | + |
| 11 | +const MAX_SINGLE_FRAME_SIZE = 0x7fffffff; |
| 12 | +const RM_HEADER_SIZE = 4; |
| 13 | + |
| 14 | +export class FullNfsv3Encoder<W extends IWriter & IWriterGrowable = IWriter & IWriterGrowable> { |
| 15 | + protected readonly nfsEncoder: Nfsv3Encoder<W>; |
| 16 | + protected readonly rpcEncoder: RpcMessageEncoder<W>; |
| 17 | + protected readonly rmEncoder: RmRecordEncoder<W>; |
| 18 | + |
| 19 | + constructor( |
| 20 | + public program: number = 100003, |
| 21 | + public readonly writer: W = new Writer() as any, |
| 22 | + ) { |
| 23 | + this.nfsEncoder = new Nfsv3Encoder(writer); |
| 24 | + this.rpcEncoder = new RpcMessageEncoder(writer); |
| 25 | + this.rmEncoder = new RmRecordEncoder(writer); |
| 26 | + } |
| 27 | + |
| 28 | + public encodeCall( |
| 29 | + xid: number, |
| 30 | + proc: Nfsv3Proc, |
| 31 | + cred: RpcOpaqueAuth, |
| 32 | + verf: RpcOpaqueAuth, |
| 33 | + request: msg.Nfsv3Request, |
| 34 | + ): Uint8Array { |
| 35 | + this.writeCall(xid, proc, cred, verf, request); |
| 36 | + return this.writer.flush(); |
| 37 | + } |
| 38 | + |
| 39 | + public writeCall( |
| 40 | + xid: number, |
| 41 | + proc: Nfsv3Proc, |
| 42 | + cred: RpcOpaqueAuth, |
| 43 | + verf: RpcOpaqueAuth, |
| 44 | + request: msg.Nfsv3Request, |
| 45 | + ): void { |
| 46 | + const writer = this.writer; |
| 47 | + const rmHeaderPosition = writer.x; |
| 48 | + writer.x += RM_HEADER_SIZE; |
| 49 | + this.rpcEncoder.writeCall(xid, Nfsv3Const.PROGRAM, Nfsv3Const.VERSION, proc, cred, verf); |
| 50 | + this.nfsEncoder.writeMessage(request, proc, true); |
| 51 | + this.writeRmHeader(rmHeaderPosition, writer.x); |
| 52 | + } |
| 53 | + |
| 54 | + public encodeAcceptedReply( |
| 55 | + xid: number, |
| 56 | + proc: Nfsv3Proc, |
| 57 | + verf: RpcOpaqueAuth, |
| 58 | + response: msg.Nfsv3Response, |
| 59 | + ): Uint8Array { |
| 60 | + this.writeAcceptedReply(xid, proc, verf, response); |
| 61 | + return this.writer.flush(); |
| 62 | + } |
| 63 | + |
| 64 | + public writeAcceptedReply(xid: number, proc: Nfsv3Proc, verf: RpcOpaqueAuth, response: msg.Nfsv3Response): void { |
| 65 | + const writer = this.writer; |
| 66 | + const rmHeaderPosition = writer.x; |
| 67 | + writer.x += RM_HEADER_SIZE; |
| 68 | + this.rpcEncoder.writeAcceptedReply(xid, verf, RpcAcceptStat.SUCCESS); |
| 69 | + this.nfsEncoder.writeMessage(response, proc, false); |
| 70 | + this.writeRmHeader(rmHeaderPosition, writer.x); |
| 71 | + } |
| 72 | + |
| 73 | + public encodeRejectedReply( |
| 74 | + xid: number, |
| 75 | + rejectStat: number, |
| 76 | + mismatchInfo?: {low: number; high: number}, |
| 77 | + authStat?: number, |
| 78 | + ): Uint8Array { |
| 79 | + this.writeRejectedReply(xid, rejectStat, mismatchInfo, authStat); |
| 80 | + return this.writer.flush(); |
| 81 | + } |
| 82 | + |
| 83 | + public writeRejectedReply( |
| 84 | + xid: number, |
| 85 | + rejectStat: number, |
| 86 | + mismatchInfo?: {low: number; high: number}, |
| 87 | + authStat?: number, |
| 88 | + ): void { |
| 89 | + const writer = this.writer; |
| 90 | + const rmHeaderPosition = writer.x; |
| 91 | + writer.x += RM_HEADER_SIZE; |
| 92 | + this.rpcEncoder.writeRejectedReply(xid, rejectStat, mismatchInfo, authStat); |
| 93 | + this.writeRmHeader(rmHeaderPosition, writer.x); |
| 94 | + } |
| 95 | + |
| 96 | + private writeRmHeader(rmHeaderPosition: number, endPosition: number): void { |
| 97 | + const writer = this.writer; |
| 98 | + const rmEncoder = this.rmEncoder; |
| 99 | + const totalSize = endPosition - rmHeaderPosition - RM_HEADER_SIZE; |
| 100 | + if (totalSize <= MAX_SINGLE_FRAME_SIZE) { |
| 101 | + const currentX = writer.x; |
| 102 | + writer.x = rmHeaderPosition; |
| 103 | + rmEncoder.writeHdr(1, totalSize); |
| 104 | + writer.x = currentX; |
| 105 | + } else { |
| 106 | + const currentX = writer.x; |
| 107 | + writer.x = rmHeaderPosition; |
| 108 | + const data = writer.uint8.subarray(rmHeaderPosition + RM_HEADER_SIZE, currentX); |
| 109 | + writer.reset(); |
| 110 | + rmEncoder.writeRecord(data); |
| 111 | + } |
| 112 | + } |
| 113 | +} |
0 commit comments