Skip to content

Commit ee28006

Browse files
committed
feat: 🎸 add MOUNT and MNL protocol data structurs
1 parent 4ba906c commit ee28006

File tree

12 files changed

+1176
-9
lines changed

12 files changed

+1176
-9
lines changed

src/nfs/v3/README.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# NFSv3 Protocol Implementation
2+
3+
This directory contains a complete implementation of the NFSv3 protocol (RFC 1813), including:
4+
5+
- **NFSv3**: Core NFS version 3 protocol operations
6+
- **MOUNT**: Mount protocol (Appendix I of RFC 1813)
7+
- **NLM**: Network Lock Manager protocol version 4 (Appendix II of RFC 1813)
8+
19
## `FullNfsv3Encoder`
210

311
`FullNfsv3Encoder` encoder that combines all three protocol layers (RM, RPC, and NFS)
@@ -16,9 +24,7 @@ const encoder = new FullNfsv3Encoder();
1624

1725
// Create NFS request
1826
const fhData = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
19-
const request = new msg.Nfsv3GetattrRequest(
20-
new structs.Nfsv3Fh(new Reader(fhData))
21-
);
27+
const request = new msg.Nfsv3GetattrRequest(new structs.Nfsv3Fh(new Reader(fhData)));
2228

2329
// Create RPC authentication
2430
const cred = {
@@ -32,11 +38,11 @@ const verf = {
3238

3339
// Encode the complete NFS call (RM + RPC + NFS layers)
3440
const encoded = encoder.encodeCall(
35-
12345, // XID
36-
Nfsv3Proc.GETATTR, // Procedure
37-
cred, // Credentials
38-
verf, // Verifier
39-
request // NFS request
41+
12345, // XID
42+
Nfsv3Proc.GETATTR, // Procedure
43+
cred, // Credentials
44+
verf, // Verifier
45+
request, // NFS request
4046
);
4147

4248
// Send the encoded data over TCP

src/nfs/v3/__demos__/tcp-server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {Nfsv3Decoder} from '../Nfsv3Decoder';
55

66
/* tslint:disable:no-console */
77

8-
const PORT = 2049;
8+
const PORT = Number(process.env.PORT) || 2049;
99
const HOST = '127.0.0.1';
1010

1111
const toHex = (buffer: Uint8Array | Buffer): string => {

src/nfs/v3/locks/NlmDecoder.ts

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
import {Reader} from '@jsonjoy.com/buffers/lib/Reader';
2+
import {XdrDecoder} from '../../../xdr/XdrDecoder';
3+
import {NlmProc, Nlm4Stat} from './constants';
4+
import {Nfsv3DecodingError} from '../errors';
5+
import * as msg from './messages';
6+
import * as structs from './structs';
7+
8+
export class NlmDecoder {
9+
protected readonly xdr: XdrDecoder;
10+
11+
constructor(reader: Reader = new Reader()) {
12+
this.xdr = new XdrDecoder(reader);
13+
}
14+
15+
public decodeMessage(reader: Reader, proc: NlmProc, isRequest: boolean): msg.NlmMessage | undefined {
16+
this.xdr.reader = reader;
17+
const startPos = reader.x;
18+
try {
19+
if (isRequest) {
20+
return this.decodeRequest(proc);
21+
} else {
22+
return this.decodeResponse(proc);
23+
}
24+
} catch (err) {
25+
if (err instanceof RangeError) {
26+
reader.x = startPos;
27+
return undefined;
28+
}
29+
throw err;
30+
}
31+
}
32+
33+
private decodeRequest(proc: NlmProc): msg.NlmRequest | undefined {
34+
switch (proc) {
35+
case NlmProc.NULL:
36+
return undefined;
37+
case NlmProc.TEST:
38+
return this.decodeTestRequest();
39+
case NlmProc.LOCK:
40+
return this.decodeLockRequest();
41+
case NlmProc.CANCEL:
42+
return this.decodeCancelRequest();
43+
case NlmProc.UNLOCK:
44+
return this.decodeUnlockRequest();
45+
case NlmProc.GRANTED:
46+
return this.decodeGrantedRequest();
47+
case NlmProc.SHARE:
48+
return this.decodeShareRequest();
49+
case NlmProc.UNSHARE:
50+
return this.decodeUnshareRequest();
51+
case NlmProc.NM_LOCK:
52+
return this.decodeNmLockRequest();
53+
case NlmProc.FREE_ALL:
54+
return this.decodeFreeAllRequest();
55+
default:
56+
throw new Nfsv3DecodingError(`Unknown NLM procedure: ${proc}`);
57+
}
58+
}
59+
60+
private decodeResponse(proc: NlmProc): msg.NlmResponse | undefined {
61+
switch (proc) {
62+
case NlmProc.NULL:
63+
return undefined;
64+
case NlmProc.TEST:
65+
return this.decodeTestResponse();
66+
case NlmProc.LOCK:
67+
case NlmProc.CANCEL:
68+
case NlmProc.UNLOCK:
69+
case NlmProc.GRANTED:
70+
case NlmProc.NM_LOCK:
71+
return this.decodeResponse4();
72+
case NlmProc.SHARE:
73+
case NlmProc.UNSHARE:
74+
return this.decodeShareResponse();
75+
default:
76+
throw new Nfsv3DecodingError(`Unknown NLM procedure: ${proc}`);
77+
}
78+
}
79+
80+
private readCookie(): Reader {
81+
const data = this.xdr.readVarlenOpaque();
82+
return new Reader(data);
83+
}
84+
85+
private readNetobj(): Reader {
86+
const data = this.xdr.readVarlenOpaque();
87+
return new Reader(data);
88+
}
89+
90+
private readNlm4Holder(): structs.Nlm4Holder {
91+
const xdr = this.xdr;
92+
const exclusive = xdr.readBoolean();
93+
const svid = xdr.readInt();
94+
const oh = this.readNetobj();
95+
const offset = xdr.readUnsignedHyper();
96+
const length = xdr.readUnsignedHyper();
97+
return new structs.Nlm4Holder(exclusive, svid, oh, offset, length);
98+
}
99+
100+
private readNlm4Lock(): structs.Nlm4Lock {
101+
const xdr = this.xdr;
102+
const callerName = xdr.readString();
103+
const fh = this.readNetobj();
104+
const oh = this.readNetobj();
105+
const svid = xdr.readInt();
106+
const offset = xdr.readUnsignedHyper();
107+
const length = xdr.readUnsignedHyper();
108+
return new structs.Nlm4Lock(callerName, fh, oh, svid, offset, length);
109+
}
110+
111+
private readNlm4Share(): structs.Nlm4Share {
112+
const xdr = this.xdr;
113+
const callerName = xdr.readString();
114+
const fh = this.readNetobj();
115+
const oh = this.readNetobj();
116+
const mode = xdr.readUnsignedInt();
117+
const access = xdr.readUnsignedInt();
118+
return new structs.Nlm4Share(callerName, fh, oh, mode, access);
119+
}
120+
121+
private readTestArgs(): msg.Nlm4TestArgs {
122+
const cookie = this.readCookie();
123+
const exclusive = this.xdr.readBoolean();
124+
const lock = this.readNlm4Lock();
125+
return new msg.Nlm4TestArgs(cookie, exclusive, lock);
126+
}
127+
128+
private readLockArgs(): msg.Nlm4LockArgs {
129+
const xdr = this.xdr;
130+
const cookie = this.readCookie();
131+
const block = xdr.readBoolean();
132+
const exclusive = xdr.readBoolean();
133+
const lock = this.readNlm4Lock();
134+
const reclaim = xdr.readBoolean();
135+
const state = xdr.readInt();
136+
return new msg.Nlm4LockArgs(cookie, block, exclusive, lock, reclaim, state);
137+
}
138+
139+
private readCancelArgs(): msg.Nlm4CancelArgs {
140+
const xdr = this.xdr;
141+
const cookie = this.readCookie();
142+
const block = xdr.readBoolean();
143+
const exclusive = xdr.readBoolean();
144+
const lock = this.readNlm4Lock();
145+
return new msg.Nlm4CancelArgs(cookie, block, exclusive, lock);
146+
}
147+
148+
private readUnlockArgs(): msg.Nlm4UnlockArgs {
149+
const cookie = this.readCookie();
150+
const lock = this.readNlm4Lock();
151+
return new msg.Nlm4UnlockArgs(cookie, lock);
152+
}
153+
154+
private readShareArgs(): msg.Nlm4ShareArgs {
155+
const cookie = this.readCookie();
156+
const share = this.readNlm4Share();
157+
const reclaim = this.xdr.readBoolean();
158+
return new msg.Nlm4ShareArgs(cookie, share, reclaim);
159+
}
160+
161+
private decodeTestRequest(): msg.Nlm4TestRequest {
162+
const args = this.readTestArgs();
163+
return new msg.Nlm4TestRequest(args);
164+
}
165+
166+
private decodeTestResponse(): msg.Nlm4TestResponse {
167+
const xdr = this.xdr;
168+
const cookie = this.readCookie();
169+
const stat = xdr.readUnsignedInt() as Nlm4Stat;
170+
const holder = stat === Nlm4Stat.NLM4_DENIED ? this.readNlm4Holder() : undefined;
171+
return new msg.Nlm4TestResponse(cookie, stat, holder);
172+
}
173+
174+
private decodeLockRequest(): msg.Nlm4LockRequest {
175+
const args = this.readLockArgs();
176+
return new msg.Nlm4LockRequest(args);
177+
}
178+
179+
private decodeResponse4(): msg.Nlm4Response {
180+
const cookie = this.readCookie();
181+
const stat = this.xdr.readUnsignedInt() as Nlm4Stat;
182+
return new msg.Nlm4Response(cookie, stat);
183+
}
184+
185+
private decodeCancelRequest(): msg.Nlm4CancelRequest {
186+
const args = this.readCancelArgs();
187+
return new msg.Nlm4CancelRequest(args);
188+
}
189+
190+
private decodeUnlockRequest(): msg.Nlm4UnlockRequest {
191+
const args = this.readUnlockArgs();
192+
return new msg.Nlm4UnlockRequest(args);
193+
}
194+
195+
private decodeGrantedRequest(): msg.Nlm4GrantedRequest {
196+
const args = this.readTestArgs();
197+
return new msg.Nlm4GrantedRequest(args);
198+
}
199+
200+
private decodeShareRequest(): msg.Nlm4ShareRequest {
201+
const args = this.readShareArgs();
202+
return new msg.Nlm4ShareRequest(args);
203+
}
204+
205+
private decodeShareResponse(): msg.Nlm4ShareResponse {
206+
const xdr = this.xdr;
207+
const cookie = this.readCookie();
208+
const stat = xdr.readUnsignedInt() as Nlm4Stat;
209+
const sequence = xdr.readInt();
210+
return new msg.Nlm4ShareResponse(cookie, stat, sequence);
211+
}
212+
213+
private decodeUnshareRequest(): msg.Nlm4UnshareRequest {
214+
const args = this.readShareArgs();
215+
return new msg.Nlm4UnshareRequest(args);
216+
}
217+
218+
private decodeNmLockRequest(): msg.Nlm4NmLockRequest {
219+
const args = this.readLockArgs();
220+
return new msg.Nlm4NmLockRequest(args);
221+
}
222+
223+
private decodeFreeAllRequest(): msg.Nlm4FreeAllRequest {
224+
const xdr = this.xdr;
225+
const name = xdr.readString();
226+
const state = xdr.readInt();
227+
const notify = new structs.Nlm4Notify(name, state);
228+
return new msg.Nlm4FreeAllRequest(notify);
229+
}
230+
}

0 commit comments

Comments
 (0)