ssh-buffer.js (3877B)
1 // Copyright 2015 Joyent, Inc. 2 3 module.exports = SSHBuffer; 4 5 var assert = require('assert-plus'); 6 var Buffer = require('safer-buffer').Buffer; 7 8 function SSHBuffer(opts) { 9 assert.object(opts, 'options'); 10 if (opts.buffer !== undefined) 11 assert.buffer(opts.buffer, 'options.buffer'); 12 13 this._size = opts.buffer ? opts.buffer.length : 1024; 14 this._buffer = opts.buffer || Buffer.alloc(this._size); 15 this._offset = 0; 16 } 17 18 SSHBuffer.prototype.toBuffer = function () { 19 return (this._buffer.slice(0, this._offset)); 20 }; 21 22 SSHBuffer.prototype.atEnd = function () { 23 return (this._offset >= this._buffer.length); 24 }; 25 26 SSHBuffer.prototype.remainder = function () { 27 return (this._buffer.slice(this._offset)); 28 }; 29 30 SSHBuffer.prototype.skip = function (n) { 31 this._offset += n; 32 }; 33 34 SSHBuffer.prototype.expand = function () { 35 this._size *= 2; 36 var buf = Buffer.alloc(this._size); 37 this._buffer.copy(buf, 0); 38 this._buffer = buf; 39 }; 40 41 SSHBuffer.prototype.readPart = function () { 42 return ({data: this.readBuffer()}); 43 }; 44 45 SSHBuffer.prototype.readBuffer = function () { 46 var len = this._buffer.readUInt32BE(this._offset); 47 this._offset += 4; 48 assert.ok(this._offset + len <= this._buffer.length, 49 'length out of bounds at +0x' + this._offset.toString(16) + 50 ' (data truncated?)'); 51 var buf = this._buffer.slice(this._offset, this._offset + len); 52 this._offset += len; 53 return (buf); 54 }; 55 56 SSHBuffer.prototype.readString = function () { 57 return (this.readBuffer().toString()); 58 }; 59 60 SSHBuffer.prototype.readCString = function () { 61 var offset = this._offset; 62 while (offset < this._buffer.length && 63 this._buffer[offset] !== 0x00) 64 offset++; 65 assert.ok(offset < this._buffer.length, 'c string does not terminate'); 66 var str = this._buffer.slice(this._offset, offset).toString(); 67 this._offset = offset + 1; 68 return (str); 69 }; 70 71 SSHBuffer.prototype.readInt = function () { 72 var v = this._buffer.readUInt32BE(this._offset); 73 this._offset += 4; 74 return (v); 75 }; 76 77 SSHBuffer.prototype.readInt64 = function () { 78 assert.ok(this._offset + 8 < this._buffer.length, 79 'buffer not long enough to read Int64'); 80 var v = this._buffer.slice(this._offset, this._offset + 8); 81 this._offset += 8; 82 return (v); 83 }; 84 85 SSHBuffer.prototype.readChar = function () { 86 var v = this._buffer[this._offset++]; 87 return (v); 88 }; 89 90 SSHBuffer.prototype.writeBuffer = function (buf) { 91 while (this._offset + 4 + buf.length > this._size) 92 this.expand(); 93 this._buffer.writeUInt32BE(buf.length, this._offset); 94 this._offset += 4; 95 buf.copy(this._buffer, this._offset); 96 this._offset += buf.length; 97 }; 98 99 SSHBuffer.prototype.writeString = function (str) { 100 this.writeBuffer(Buffer.from(str, 'utf8')); 101 }; 102 103 SSHBuffer.prototype.writeCString = function (str) { 104 while (this._offset + 1 + str.length > this._size) 105 this.expand(); 106 this._buffer.write(str, this._offset); 107 this._offset += str.length; 108 this._buffer[this._offset++] = 0; 109 }; 110 111 SSHBuffer.prototype.writeInt = function (v) { 112 while (this._offset + 4 > this._size) 113 this.expand(); 114 this._buffer.writeUInt32BE(v, this._offset); 115 this._offset += 4; 116 }; 117 118 SSHBuffer.prototype.writeInt64 = function (v) { 119 assert.buffer(v, 'value'); 120 if (v.length > 8) { 121 var lead = v.slice(0, v.length - 8); 122 for (var i = 0; i < lead.length; ++i) { 123 assert.strictEqual(lead[i], 0, 124 'must fit in 64 bits of precision'); 125 } 126 v = v.slice(v.length - 8, v.length); 127 } 128 while (this._offset + 8 > this._size) 129 this.expand(); 130 v.copy(this._buffer, this._offset); 131 this._offset += 8; 132 }; 133 134 SSHBuffer.prototype.writeChar = function (v) { 135 while (this._offset + 1 > this._size) 136 this.expand(); 137 this._buffer[this._offset++] = v; 138 }; 139 140 SSHBuffer.prototype.writePart = function (p) { 141 this.writeBuffer(p.data); 142 }; 143 144 SSHBuffer.prototype.write = function (buf) { 145 while (this._offset + buf.length > this._size) 146 this.expand(); 147 buf.copy(this._buffer, this._offset); 148 this._offset += buf.length; 149 };