UNPKG

@jsonjoy.com/json-pack

Version:

High-performance JSON serialization library

163 lines 6.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Nfsv4Connection = void 0; const tslib_1 = require("tslib"); const Reader_1 = require("@jsonjoy.com/buffers/lib/Reader"); const Nfsv4Decoder_1 = require("../Nfsv4Decoder"); const Nfsv4FullEncoder_1 = require("../Nfsv4FullEncoder"); const rm_1 = require("../../../rm"); const rpc_1 = require("../../../rpc"); const msg = tslib_1.__importStar(require("../messages")); const constants_1 = require("../constants"); const Nfsv4CompoundProcCtx_1 = require("./Nfsv4CompoundProcCtx"); const EMPTY_AUTH = new rpc_1.RpcOpaqueAuth(0 /* RpcAuthFlavor.AUTH_NONE */, constants_1.EMPTY_READER); class Nfsv4Connection { constructor(opts) { this.closed = false; this.maxIncomingMessage = 2 * 1024 * 1024; this.maxBackpressure = 2 * 1024 * 1024; /** Last known RPC transaction ID. Used to emit fatal connection errors. */ this.lastXid = 0; // ---------------------------------------------------------- Write to socket this.__uncorkTimer = null; this.debug = !!opts.debug; this.logger = opts.logger || console; const duplex = (this.duplex = opts.duplex); this.ops = opts.ops; this.rmDecoder = new rm_1.RmRecordDecoder(); this.rpcDecoder = new rpc_1.RpcMessageDecoder(); this.nfsDecoder = new Nfsv4Decoder_1.Nfsv4Decoder(); const nfsEncoder = (this.nfsEncoder = new Nfsv4FullEncoder_1.Nfsv4FullEncoder()); this.writer = nfsEncoder.writer; this.rmEncoder = nfsEncoder.rmEncoder; this.rpcEncoder = nfsEncoder.rpcEncoder; duplex.on('data', this.onData.bind(this)); duplex.on('timeout', () => this.close()); duplex.on('close', (hadError) => { this.close(); }); duplex.on('error', (err) => { this.logger.error('SOCKET ERROR:', err); this.close(); }); } onData(data) { const { rmDecoder, rpcDecoder } = this; rmDecoder.push(data); let record = rmDecoder.readRecord(); while (record) { if (record.size()) { const rpcMessage = rpcDecoder.decodeMessage(record); if (rpcMessage) this.onRpcMessage(rpcMessage); else { this.close(); return; } } record = rmDecoder.readRecord(); } } onRpcMessage(msg) { if (msg instanceof rpc_1.RpcCallMessage) { this.lastXid = msg.xid; this.onRpcCallMessage(msg); } else if (msg instanceof rpc_1.RpcAcceptedReplyMessage) { throw new Error('Not implemented RpcAcceptedReplyMessage'); } else if (msg instanceof rpc_1.RpcRejectedReplyMessage) { throw new Error('Not implemented RpcRejectedReplyMessage'); } } onRpcCallMessage(procedure) { const { debug, logger, writer, rmEncoder } = this; const { xid, proc } = procedure; switch (proc) { case 1 /* Nfsv4Proc.COMPOUND */: { if (debug) logger.log(`\n<COMPOUND{${xid}}>`); if (!(procedure.params instanceof Reader_1.Reader)) return; const compound = this.nfsDecoder.decodeCompoundRequest(procedure.params); if (compound instanceof msg.Nfsv4CompoundRequest) { new Nfsv4CompoundProcCtx_1.Nfsv4CompoundProcCtx(this, compound) .exec() .then((procResponse) => { if (debug) logger.log(`</COMPOUND{${xid}}>`); this.nfsEncoder.writeAcceptedCompoundReply(xid, EMPTY_AUTH, procResponse); this.write(writer.flush()); }) .catch((err) => { logger.error('NFS COMPOUND error:', xid, err); this.nfsEncoder.writeRejectedReply(xid, 10006 /* Nfsv4Stat.NFS4ERR_SERVERFAULT */); }); } else this.closeWithError(4 /* RpcAcceptStat.GARBAGE_ARGS */); break; } case 0 /* Nfsv4Proc.NULL */: { if (debug) logger.log('NULL', procedure); const state = rmEncoder.startRecord(); this.rpcEncoder.writeAcceptedReply(xid, EMPTY_AUTH, 0 /* RpcAcceptStat.SUCCESS */); rmEncoder.endRecord(state); this.write(writer.flush()); break; } default: { if (debug) logger.error(`Unknown procedure: ${proc}`); } } } closeWithError(error) { if (this.debug) this.logger.log(`Closing with error: RpcAcceptStat = ${error}, xid = ${this.lastXid}`); const xid = this.lastXid; if (xid) { const state = this.rmEncoder.startRecord(); const verify = new rpc_1.RpcOpaqueAuth(0 /* RpcAuthFlavor.AUTH_NONE */, constants_1.EMPTY_READER); this.rpcEncoder.writeAcceptedReply(xid, verify, error); this.rmEncoder.endRecord(state); const bin = this.writer.flush(); this.duplex.write(bin); } this.close(); } close() { if (this.closed) return; this.closed = true; clearImmediate(this.__uncorkTimer); this.__uncorkTimer = null; const duplex = this.duplex; duplex.removeAllListeners(); if (!duplex.destroyed) duplex.destroy(); } write(buf) { if (this.closed) return; const duplex = this.duplex; if (duplex.writableLength > this.maxBackpressure) { this.closeWithError(5 /* RpcAcceptStat.SYSTEM_ERR */); return; } const __uncorkTimer = this.__uncorkTimer; if (!__uncorkTimer) duplex.cork(); duplex.write(buf); if (!__uncorkTimer) this.__uncorkTimer = setImmediate(() => { this.__uncorkTimer = null; duplex.uncork(); }); } // TODO: Execute NFS Callback... send() { } } exports.Nfsv4Connection = Nfsv4Connection; //# sourceMappingURL=Nfsv4Connection.js.map