oncrpc
Version:
Library for creating ONC RPC Node.js servers and clients
120 lines (88 loc) • 3.06 kB
JavaScript
// Copyright 2014 Joyent, Inc. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
var stream = require('stream');
var util = require('util');
var assert = require('assert-plus');
var once = require('once');
var auth = require('./auth');
var RpcMessage = require('./message').RpcMessage;
var XDR = require('./xdr').XDR;
///--- Globals
var sprintf = util.format;
///--- API
function RpcReply(opts) {
RpcMessage.call(this, opts);
this._buffer = null;
this.rpc_reply_header_sent = false;
this.type = 1;
}
util.inherits(RpcReply, RpcMessage);
RpcReply.prototype._serialize = function _serialize(size) {
assert.optionalNumber(size, 'size');
// 8 bytes for header, 8 for NULL verifier
var xdr = this.__serialize(16, size);
xdr.writeInt(0); // reply_stat: accepted
xdr.writeDouble(0x000000000); // verifier (null)
xdr.writeInt(0); // accept_stat: ok
return (xdr);
};
RpcReply.prototype._transform = function _transform(chunk, encoding, cb) {
cb = once(cb);
if (!Buffer.isBuffer(chunk))
chunk = new Buffer(chunk, encoding);
if (this.incoming) {
if (this._buffer) {
chunk = Buffer.concat(this._buffer, chunk);
this._buffer = null;
}
// The shortest response we could get is 3 ints (reply_stat - denied,
// reject_stat - auth error, auth_stat).
if (chunk.length < 12) {
this._buffer = chunk;
return;
}
var xdr = new XDR(chunk);
this.reply_stat = xdr.readInt();
if (this.reply_stat === 0) { // ACCEPTED
// TODO inspect length
this.verifier = auth.parse(xdr);
this.accept_stat = xdr.readInt();
if (this.accept_stat === 0) {
if (xdr.remain())
this.push(xdr.slice());
} else if (this.accept_stat === 2) {
this.mismatch_info = {
low: xdr.readInt(),
high: xdr.readInt()
};
}
// otherwise "void"
} else if (this.reply_stat === 1) { // DENIED
this.reject_stat = xdr.readInt();
if (this.reject_stat === 0) { // RPC_MISMATCH
this.mismatch_info = {
low: xdr.readInt(),
high: xdr.readInt()
};
} else if (this.reject_stat === 1) { // AUTH_ERROR
this.auth_stat = xdr.readInt();
} else {
cb(new Error('invalid reject_stat: ' + this.reject_stat));
return;
}
} else {
cb(new Error('invalid reply_stat: ' + this.reply_stat));
return;
}
} else {
this.push(chunk);
}
cb();
};
///--- Exports
module.exports = {
RpcReply: RpcReply
};