-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFullNfsv3Encoder.ts
More file actions
113 lines (103 loc) · 3.65 KB
/
FullNfsv3Encoder.ts
File metadata and controls
113 lines (103 loc) · 3.65 KB
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import {Writer} from '@jsonjoy.com/util/lib/buffers/Writer';
import {Nfsv3Encoder} from './Nfsv3Encoder';
import {RpcMessageEncoder} from '../../rpc/RpcMessageEncoder';
import {RmRecordEncoder} from '../../rm/RmRecordEncoder';
import {Nfsv3Proc, Nfsv3Const} from './constants';
import {RpcOpaqueAuth} from '../../rpc/messages';
import {RpcAcceptStat} from '../../rpc/constants';
import type * as msg from './messages';
import type {IWriter, IWriterGrowable} from '@jsonjoy.com/util/lib/buffers';
const MAX_SINGLE_FRAME_SIZE = 0x7fffffff;
const RM_HEADER_SIZE = 4;
export class FullNfsv3Encoder<W extends IWriter & IWriterGrowable = IWriter & IWriterGrowable> {
protected readonly nfsEncoder: Nfsv3Encoder<W>;
protected readonly rpcEncoder: RpcMessageEncoder<W>;
protected readonly rmEncoder: RmRecordEncoder<W>;
constructor(
public program: number = 100003,
public readonly writer: W = new Writer() as any,
) {
this.nfsEncoder = new Nfsv3Encoder(writer);
this.rpcEncoder = new RpcMessageEncoder(writer);
this.rmEncoder = new RmRecordEncoder(writer);
}
public encodeCall(
xid: number,
proc: Nfsv3Proc,
cred: RpcOpaqueAuth,
verf: RpcOpaqueAuth,
request: msg.Nfsv3Request,
): Uint8Array {
this.writeCall(xid, proc, cred, verf, request);
return this.writer.flush();
}
public writeCall(
xid: number,
proc: Nfsv3Proc,
cred: RpcOpaqueAuth,
verf: RpcOpaqueAuth,
request: msg.Nfsv3Request,
): void {
const writer = this.writer;
const rmHeaderPosition = writer.x;
writer.x += RM_HEADER_SIZE;
this.rpcEncoder.writeCall(xid, Nfsv3Const.PROGRAM, Nfsv3Const.VERSION, proc, cred, verf);
this.nfsEncoder.writeMessage(request, proc, true);
this.writeRmHeader(rmHeaderPosition, writer.x);
}
public encodeAcceptedReply(
xid: number,
proc: Nfsv3Proc,
verf: RpcOpaqueAuth,
response: msg.Nfsv3Response,
): Uint8Array {
this.writeAcceptedReply(xid, proc, verf, response);
return this.writer.flush();
}
public writeAcceptedReply(xid: number, proc: Nfsv3Proc, verf: RpcOpaqueAuth, response: msg.Nfsv3Response): void {
const writer = this.writer;
const rmHeaderPosition = writer.x;
writer.x += RM_HEADER_SIZE;
this.rpcEncoder.writeAcceptedReply(xid, verf, RpcAcceptStat.SUCCESS);
this.nfsEncoder.writeMessage(response, proc, false);
this.writeRmHeader(rmHeaderPosition, writer.x);
}
public encodeRejectedReply(
xid: number,
rejectStat: number,
mismatchInfo?: {low: number; high: number},
authStat?: number,
): Uint8Array {
this.writeRejectedReply(xid, rejectStat, mismatchInfo, authStat);
return this.writer.flush();
}
public writeRejectedReply(
xid: number,
rejectStat: number,
mismatchInfo?: {low: number; high: number},
authStat?: number,
): void {
const writer = this.writer;
const rmHeaderPosition = writer.x;
writer.x += RM_HEADER_SIZE;
this.rpcEncoder.writeRejectedReply(xid, rejectStat, mismatchInfo, authStat);
this.writeRmHeader(rmHeaderPosition, writer.x);
}
private writeRmHeader(rmHeaderPosition: number, endPosition: number): void {
const writer = this.writer;
const rmEncoder = this.rmEncoder;
const totalSize = endPosition - rmHeaderPosition - RM_HEADER_SIZE;
if (totalSize <= MAX_SINGLE_FRAME_SIZE) {
const currentX = writer.x;
writer.x = rmHeaderPosition;
rmEncoder.writeHdr(1, totalSize);
writer.x = currentX;
} else {
const currentX = writer.x;
writer.x = rmHeaderPosition;
const data = writer.uint8.subarray(rmHeaderPosition + RM_HEADER_SIZE, currentX);
writer.reset();
rmEncoder.writeRecord(data);
}
}
}