Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

version 0.0.2a

  • Loading branch information...
commit d9f573ddc4d0d63353ce135447e304db71cd9529 1 parent 230edaa
@billywhizz authored
View
8 CHANGELOG
@@ -1,3 +1,9 @@
+2010.10.14, Version 0.0.2
+ * Big speed improvements to buffer handling code (Andrew Johnston)
+ * fixed issue with signed binary numbers (Andrew Johnston)
+ * added callbacks for header and params (Andrew Johnston)
+ * changed events to callbacks for better performance (Andrew Johnston)
+ * reorganised directories (Andrew Johnston)
2010.10.13, Version 0.0.1
- * Initial Commit (Andrew Johnston)
+ * Initial Commit (Andrew Johnston)
View
0  benchmark/createtestfiles.js 100755 → 100644
File mode changed
View
0  benchmark/speed-fcgi.js 100755 → 100644
File mode changed
View
0  benchmark/speed-http.js 100755 → 100644
File mode changed
View
0  examples/client.js 100755 → 100644
File mode changed
View
0  examples/php-server.js 100755 → 100644
File mode changed
View
0  examples/server.js 100755 → 100644
File mode changed
View
179 lib/buffer_extras.js
@@ -1,82 +1,28 @@
-/*
-Copyright (c) 2010 Tim Caswell <tim@creationix.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
var Buffer = module.exports = require('buffer').Buffer;
var proto = Buffer.prototype;
-// Cleans the buffer to be all zeroes
-proto.zeroOut = function zeroOut() {
- for (var i = 0, l = this.length; i < l; i++) {
- this[i] = 0;
- }
-};
-
// Writes a 32 bit integer at offset
proto.int32Write = function int32Write(number, offset) {
- offset = offset || 0;
- var unsigned = (number < 0) ? (number + 0x100000000) : number;
- this[offset] = Math.floor(unsigned / 0xffffff);
- unsigned &= 0xffffff;
- this[offset + 1] = Math.floor(unsigned / 0xffff);
- unsigned &= 0xffff;
- this[offset + 2] = Math.floor(unsigned / 0xff);
- unsigned &= 0xff;
- this[offset + 3] = Math.floor(unsigned);
+ offset = offset || 0;
+ this[offset] = (number & 0xff000000) >> 24;
+ this[offset + 1] = (number & 0xff0000) >> 16;
+ this[offset + 2] = (number & 0xff00) >> 8;
+ this[offset + 3] = (number & 0xff);
};
// Writes a 16 bit integer at offset
proto.int16Write = function int16Write(number, offset) {
- offset = offset || 0;
- var unsigned = (number < 0) ? (number + 0x10000) : number;
- this[offset] = Math.floor(unsigned / 0xff);
- unsigned &= 0xff;
- this[offset + 1] = Math.floor(unsigned);
+ offset = offset || 0;
+ this[offset] = (number & 0xff00) >> 8;
+ this[offset + 1] = (number & 0xff);
}
// Writes a 16 bit integer at offset
proto.intWrite = function intWrite(number, offset) {
- offset = offset || 0;
- var unsigned = (number < 0) ? (number + 0x100) : number;
- this[offset] = Math.floor(unsigned);
+ offset = offset || 0;
+ this[offset] = (number & 0xff);
}
-// Reads a 32 bit integer from offset
-proto.int32Read = function int32Read(offset) {
- offset = offset || 0;
- var unsigned = this[offset] * 0x1000000 +
- this[offset + 1] * 0x10000 +
- this[offset + 2] * 0x100 +
- this[offset + 3];
- return (unsigned & 0x80000000) ? (unsigned - 0x100000000) : unsigned
-};
-
-// Reads a 32 bit integer from offset
-proto.int16Read = function int16Read(offset) {
- offset = offset || 0;
- var unsigned = this[offset] * 0x100 +
- this[offset + 1];
- return (unsigned & 0x8000) ? (unsigned - 0x10000) : unsigned
-};
-
Buffer.fromString = function fromString(string) {
var b = new Buffer(Buffer.byteLength(string));
b.write(string, 'utf8');
@@ -108,30 +54,6 @@ Buffer.makeWriter = function makeWriter() {
string: function pushString(string) {
data.push(Buffer.fromString(string));
return writer;
- },
- byte1: function byte1(string) {
- var b = new Buffer(1); // one octet.
- b.write(string, 'utf8', 0);
- data.push(b);
- return writer;
- },
- cstring: function pushCstring(string) {
- data.push(Buffer.fromString(string + "\0"));
- return writer;
- },
- multicstring: function pushMulticstring(fields) {
- data.push(Buffer.fromString(fields.join("\0") + "\0\0"));
- return writer;
- },
- hash: function pushHash(hash) {
- var keys = Object.keys(hash);
- var pairs = [];
- for (var i = 0, l = keys.length; i < l; i++) {
- var key = keys[i];
- pairs.push(key + "\0" + hash[key] + "\0");
- }
- data.push(Buffer.fromString(pairs.join("") + "\0"));
- return writer;
}
};
writer = {
@@ -155,83 +77,4 @@ Buffer.makeWriter = function makeWriter() {
}
};
return writer;
-}
-
-proto.toReader = function toReader() {
- var offset = 0, length = this.length, buffer = this;
- return {
- empty: function empty() {
- return offset >= length;
- },
- int32: function shiftInt32() {
- var number = buffer.int32Read(offset);
- offset += 4;
- return number;
- },
- int16: function shiftInt16() {
- var number = buffer.int16Read(offset);
- offset += 2;
- return number;
- },
- buffer: function shiftBuffer(length) {
- var b = buffer.slice(offset, offset + length);
- offset += length;
- return b;
- },
- string: function shiftString(length) {
- var string = buffer.toString('utf8', offset, offset + length);
- offset += length;
- return string;
- },
- cstring: function shiftCstring() {
- var end = offset;
- while (buffer[end] > 0 && end < length) { end++; }
- var string = buffer.toString('utf8', offset, end);
- offset = end + 1;
- return string;
- },
- multicstring: function shiftMulticstring() {
- var fields = [];
- while (buffer[offset] > 0) {
- fields.push(this.cstring());
- }
- offset++;
- return fields;
- },
- hash: function shiftHash() {
- var hash = {};
- while (buffer[offset] > 0) {
- hash[this.cstring()] = this.cstring();
- }
- offset++;
- return hash;
- }
- }
-};
-
-// Test It
-// var sys = require('sys');
-//
-// var w = Buffer.makeWriter();
-// w.push.int32(305419896);
-// w.push.int16(4660);
-// w.push.string("12345");
-// w.push.cstring("Héllø Wø®l?");
-// w.push.multicstring(["Hello", "World"]);
-// w.push.hash({name: "Tim", age: "28"});
-// w.push.int32(0x12345678);
-// w.push.int16(0x1234);
-// var b = w.toBuffer();
-// // sys.p(b);
-// var r = b.toReader();
-// sys.p([
-// r.int32(),
-// r.int16(),
-// r.string(5),
-// r.cstring(),
-// r.multicstring(),
-// r.hash(),
-// r.int32(),
-// r.int16()
-// ]);
-//
+}
View
27 lib/fastcgi.js 100755 → 100644
@@ -1,5 +1,4 @@
var sys = require("sys");
-var events = require("events");
var Buffer = require('./buffer_extras');
var constants = {
@@ -28,16 +27,20 @@ var constants = {
"PADDING": 2
}
},
+ "general": {
+ "FCGI_HEADER_LEN": 8,
+ "FCGI_MAX_BODY": 8192
+ },
"errors": {
"BUFFER_OVERFLOW": {
"err": 1,
"description": "buffer overflow"
+ },
+ "MAX_BODY_EXCEEDED": {
+ "err": 2,
+ "description": "a body greater than maximum body size was read/written"
}
},
- "general": {
- "FCGI_HEADER_LEN": 8,
- "FCGI_MAX_BODY": 8192
- },
"flags": {
"FCGI_KEEP_CONN": 1
},
@@ -85,6 +88,8 @@ function Parser() {
var _body = new Buffer(constants.general.FCGI_MAX_BODY);
_parser.state = constants.parser.state.HEADER;
+ _parser.onRecord = _parser.onError = _parser.onHeader = _parser.onParam = null;
+
var tmp = null;
function parseBody() {
@@ -129,11 +134,11 @@ function Parser() {
if((ploc + hsize + vsize) <= _body.length) {
name = _body.toString('utf8', ploc, ploc += hsize);
value = _body.toString('utf8', ploc, ploc += vsize);
- _parser.emit("param", name, value);
+ if(_parser.onParam) _parser.onParam(name, value);
record.body.params[name] = value;
}
else {
- _parser.emit("error", new Error(JSON.stringify(constants.errors.BUFFER_OVERRUN)));
+ if(_parser.onError) _parser.onError(new Error(JSON.stringify(constants.errors.BUFFER_OVERRUN)));
ploc = params.length;
}
}
@@ -172,12 +177,12 @@ function Parser() {
record.body = {};
// finished parsing header. inform the caller
if(record.header.contentLength > 0) {
- _parser.emit("header", record.header);
+ if(_parser.onHeader) _parser.onHeader(record.header);
_parser.state = constants.parser.state.BODY;
}
else {
// the record has no body so skip the header event
- _parser.emit("record", record);
+ if(_parser.onRecord) _parser.onRecord(record);
}
loc=0;
}
@@ -190,7 +195,7 @@ function Parser() {
_body[loc] = buffer[i];
parseBody();
// finished parsing record. inform the caller
- _parser.emit("record", record);
+ if(_parser.onRecord) _parser.onRecord(record);
loc = 0;
if(record.header.paddingLength > 0) {
_parser.state = constants.parser.state.PADDING;
@@ -213,7 +218,6 @@ function Parser() {
}
}
}
-sys.inherits(Parser, events.EventEmitter);
function Writer() {
var _writer = this;
@@ -285,7 +289,6 @@ function Writer() {
}
}
-sys.inherits(Writer, events.EventEmitter);
exports.parser = Parser;
exports.writer = Writer;
View
61 tests/test.js 100755 → 100644
@@ -4,22 +4,22 @@ var fs = require("fs");
var parser = new fastcgi.parser();
-parser.addListener("param", function(name, value) {
+parser.onParam = function(name, value) {
sys.puts("param\n" + name + ":" + value);
-});
+};
-parser.addListener("header", function(header) {
+parser.onHeader = function(header) {
sys.puts("header\n" + JSON.stringify(header, null, "\t"));
-});
+};
-parser.addListener("record", function(record) {
+parser.onRecord = function(record) {
sys.puts("record\n" + JSON.stringify(record, null, "\t"));
-});
+};
-parser.addListener("error", function(err) {
+parser.onError = function(err) {
sys.puts("error\n" + JSON.stringify(err, null, "\t"));
throw(err);
-});
+};
var writer = new fastcgi.writer();
@@ -27,8 +27,8 @@ var message = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: 5\r\nCont
// out parser
writer.writeHeader({
- "version": 1,
- "type": 6,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_STDOUT,
"recordId": 1,
"contentLength": message.length,
"paddingLength": 0
@@ -36,16 +36,16 @@ writer.writeHeader({
writer.writeBody(message);
parser.execute(writer.tobuffer());
writer.writeHeader({
- "version": 1,
- "type": 6,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_STDOUT,
"recordId": 1,
"contentLength": 0,
"paddingLength": 0
});
parser.execute(writer.tobuffer());
writer.writeHeader({
- "version": 1,
- "type": 3,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_END,
"recordId": 1,
"contentLength": 8,
"paddingLength": 0
@@ -56,25 +56,20 @@ writer.writeEnd({
});
parser.execute(writer.tobuffer());
-var maxbuff = "";
-for(var i=0; i<16231; i++) {
- maxbuff += "0";
-}
-maxbuff = "hello";
-
var params = [
- ["SCRIPT_FILENAME", "/scripts/test.js"],
- ["HTTP_USER_AGENT", maxbuff],
+ ["SCRIPT_FILENAME", "/test.js"],
+ ["HTTP_USER_AGENT", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Supplied by blueyonder; .NET CLR 1.1.4322; .NET CLR 2.0.50215)"],
["HTTP_ACCEPT_ENCODING", "none"],
["HTTP_CONNECTION", "Keep-Alive"],
["HTTP_ACCEPT", "*/*"],
["HTTP_HOST", "shuttle.owner.net:82"]
];
+var paramlen = fastcgi.getParamLength(params);
// in parser
writer.writeHeader({
- "version": 1,
- "type": 1,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_BEGIN,
"recordId": 1,
"contentLength": 8,
"paddingLength": 0
@@ -85,25 +80,25 @@ writer.writeBegin({
});
parser.execute(writer.tobuffer());
writer.writeHeader({
- "version": 1,
- "type": 4,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_PARAMS,
"recordId": 1,
- "contentLength": fastcgi.getParamLength(params),
+ "contentLength": paramlen,
"paddingLength": 0
});
writer.writeParams(params);
parser.execute(writer.tobuffer());
writer.writeHeader({
- "version": 1,
- "type": 4,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_PARAMS,
"recordId": 1,
"contentLength": 0,
"paddingLength": 0
});
parser.execute(writer.tobuffer());
writer.writeHeader({
- "version": 1,
- "type": 5,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_STDIN,
"recordId": 1,
"contentLength": 5,
"paddingLength": 0
@@ -111,8 +106,8 @@ writer.writeHeader({
writer.writeBody("hello");
parser.execute(writer.tobuffer());
writer.writeHeader({
- "version": 1,
- "type": 5,
+ "version": fastcgi.constants.version,
+ "type": fastcgi.constants.record.FCGI_STDIN,
"recordId": 1,
"contentLength": 0,
"paddingLength": 0
Please sign in to comment.
Something went wrong with that request. Please try again.