Skip to content

Commit 4ba906c

Browse files
authored
Merge pull request #61 from jsonjoy-com/nfs
NFSv3
2 parents 10967f4 + 76edcd0 commit 4ba906c

20 files changed

+11401
-4
lines changed

src/nfs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# NFS (Network File System)
2+
3+
## Resources
4+
5+
- [NFSv3 RFC 1813](./v3/__tests__/rfc1813.txt)

src/nfs/v3/FullNfsv3Encoder.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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

Comments
 (0)