blob: f68815979ff73dfd9e6ebd4d6a42ae064701dbcf [file] [log] [blame]
/*!
* base64id v0.1.0
*/
/**
* Module dependencies
*/
var crypto = require('crypto');
/**
* Constructor
*/
var Base64Id = function() { };
/**
* Get random bytes
*
* Uses a buffer if available, falls back to crypto.randomBytes
*/
Base64Id.prototype.getRandomBytes = function(bytes) {
var BUFFER_SIZE = 4096
var self = this;
bytes = bytes || 12;
if (bytes > BUFFER_SIZE) {
return crypto.randomBytes(bytes);
}
var bytesInBuffer = parseInt(BUFFER_SIZE/bytes);
var threshold = parseInt(bytesInBuffer*0.85);
if (!threshold) {
return crypto.randomBytes(bytes);
}
if (this.bytesBufferIndex == null) {
this.bytesBufferIndex = -1;
}
if (this.bytesBufferIndex == bytesInBuffer) {
this.bytesBuffer = null;
this.bytesBufferIndex = -1;
}
// No buffered bytes available or index above threshold
if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) {
if (!this.isGeneratingBytes) {
this.isGeneratingBytes = true;
crypto.randomBytes(BUFFER_SIZE, function(err, bytes) {
self.bytesBuffer = bytes;
self.bytesBufferIndex = 0;
self.isGeneratingBytes = false;
});
}
// Fall back to sync call when no buffered bytes are available
if (this.bytesBufferIndex == -1) {
return crypto.randomBytes(bytes);
}
}
var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1));
this.bytesBufferIndex++;
return result;
}
/**
* Generates a base64 id
*
* (Original version from socket.io <http://socket.io>)
*/
Base64Id.prototype.generateId = function () {
var rand = new Buffer(15); // multiple of 3 for base64
if (!rand.writeInt32BE) {
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
}
this.sequenceNumber = (this.sequenceNumber + 1) | 0;
rand.writeInt32BE(this.sequenceNumber, 11);
if (crypto.randomBytes) {
this.getRandomBytes(12).copy(rand);
} else {
// not secure for node 0.4
[0, 4, 8].forEach(function(i) {
rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i);
});
}
return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
};
/**
* Export
*/
exports = module.exports = new Base64Id();