Created
October 31, 2012 03:24
-
-
Save MatthaeusHarris/3984608 to your computer and use it in GitHub Desktop.
JSON TCP buffer implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var util = require('util'); | |
var events = require('events'); | |
function JSONBuffer(sock) { | |
if (false === this instanceof JSONBuffer) { | |
return new JSONBuffer(); | |
} | |
events.EventEmitter.call(this); | |
this.sock = sock; | |
this.sock.on('connect', function() { this.emit('connect') }.bind(this)); | |
this.sock.on('end', function() { this.emit('end') }.bind(this)); | |
this.sock.on('timeout', function() { this.emit('timeout') }.bind(this)); | |
this.sock.on('drain', function() { this.emit('drain') }.bind(this)); | |
this.sock.on('error', function(e) { | |
console.log("JSONBuffer detected an error: " + e.message); | |
console.log(e.stack); | |
if (e.message == "This socket is closed.") { | |
console.log("The socket was closed prematurely. We should handle this more gracefully, but for now we'll just return."); | |
this.emit('closed'); | |
} else { | |
console.log("Some other error happened, so we'll chuck it upstream."); | |
console.log(this); | |
console.log("Chucking the error upstream disabled for now, especially since there can be no error handlers in the upstream flow."); | |
//this.emit('error', e) | |
} | |
}.bind(this)); | |
this.sock.on('close', function(e) { this.emit('close', e) }.bind(this)); | |
this.sock.on('data',function(buf) { | |
this.buffer += buf; | |
// console.log("\n\n####################################################################"); | |
// console.log("JSONBuffer buffer: "); | |
// console.log(this.buffer); | |
// console.log("####################################################################"); | |
var stack = []; | |
var jsonStartIndex = -1; | |
var inQuotes = false; | |
for (var i = 0; i < this.buffer.length; i++) { | |
// console.log("Starting at character " + i + ": " + stack + " " + this.buffer[i]); | |
if ((this.buffer[i] == '\'' || this.buffer[i] == '\"') && i >=1 && this.buffer[i-1] != '\\') { | |
inQuotes = !inQuotes; | |
} | |
if (!inQuotes) { | |
switch(this.buffer[i]) { | |
case '{': | |
case '[': | |
stack.push(this.buffer[i]); | |
if (jsonStartIndex == -1) { | |
jsonStartIndex = i; | |
} | |
break; | |
case ']': | |
if (stack[stack.length-1] == "[") { | |
stack.pop(); | |
} | |
break; | |
case '}': | |
if (stack[stack.length-1] == "{") { | |
stack.pop(); | |
} | |
break; | |
default: | |
break; | |
} | |
if (stack.length == 0 && jsonStartIndex != -1) { | |
// console.log("JB: Found JSON, emitting data signal"); | |
// console.log("JB: stack: " + JSON.stringify(stack)); | |
var out = this.buffer.substr(jsonStartIndex,i-jsonStartIndex+1); | |
this.emit('data', out); | |
jsonStartIndex = -1; | |
this.buffer = this.buffer.slice(i); | |
i = 0; | |
} | |
} | |
} | |
}.bind(this)); | |
} | |
util.inherits(JSONBuffer, events.EventEmitter); | |
JSONBuffer.prototype.__proto__ = events.EventEmitter.prototype; | |
JSONBuffer.prototype.sock = {}; | |
JSONBuffer.prototype.buffer = ""; | |
JSONBuffer.prototype.write = function(data, callback) { | |
try { | |
return(this.sock.write(data, callback)); | |
} catch (e) { | |
console.log("Error writing to socket: " + e.message); | |
console.log(e.stack); | |
return false; | |
} | |
} | |
JSONBuffer.prototype.end = function() { | |
// var e = new Error("not really an error"); | |
// console.log("JSONBuffer.end() called. "); | |
// console.log(e.stack); | |
try { | |
return(this.sock.end()); | |
} catch (e) { | |
console.log("Error closing socket: " + e.message); | |
console.log(e.stack); | |
return false; | |
} | |
} | |
JSONBuffer.prototype.destroy = function() { | |
// var e = new Error("not really an error"); | |
// console.log("JSONBuffer.destroy() called."); | |
// console.log(e.stack); | |
try { | |
return(this.sock.destroy()); | |
} catch (e) { | |
console.log("Error destroying socket: " + e.message); | |
console.log(e.stack); | |
return false; | |
} | |
} | |
JSONBuffer.prototype.setTimeout = function(timeout, callback) { | |
return(this.sock.setTimeout(timeout, callback)); | |
} | |
module.exports = JSONBuffer; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment