diff --git a/Makefile b/Makefile index 39ff6455..a781c4a6 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,3 @@ -all: - node-gyp configure build - -clean: - node-gyp clean - autobahn: @NODE_PATH=lib node test/autobahn-test-client.js --host=127.0.0.1 --port=9000 diff --git a/binding.gyp b/binding.gyp deleted file mode 100644 index 77b2ed52..00000000 --- a/binding.gyp +++ /dev/null @@ -1,18 +0,0 @@ -{ - 'targets': [ - { - 'target_name': 'validation', - 'include_dirs': [" - * MIT Licensed - */ - -/* jshint -W086 */ - -module.exports.BufferUtil = { - merge: function(mergedBuffer, buffers) { - var offset = 0; - for (var i = 0, l = buffers.length; i < l; ++i) { - var buf = buffers[i]; - buf.copy(mergedBuffer, offset); - offset += buf.length; - } - }, - mask: function(source, mask, output, offset, length) { - var maskNum = mask.readUInt32LE(0); - var i = 0; - for (; i < length - 3; i += 4) { - var num = maskNum ^ source.readUInt32LE(i); - if (num < 0) { num = 4294967296 + num; } - output.writeUInt32LE(num, offset + i); - } - switch (length % 4) { - case 3: output[offset + i + 2] = source[i + 2] ^ mask[2]; - case 2: output[offset + i + 1] = source[i + 1] ^ mask[1]; - case 1: output[offset + i] = source[i] ^ mask[0]; - case 0: - } - }, - unmask: function(data, mask) { - var maskNum = mask.readUInt32LE(0); - var length = data.length; - var i = 0; - for (; i < length - 3; i += 4) { - var num = maskNum ^ data.readUInt32LE(i); - if (num < 0) { num = 4294967296 + num; } - data.writeUInt32LE(num, i); - } - switch (length % 4) { - case 3: data[i + 2] = data[i + 2] ^ mask[2]; - case 2: data[i + 1] = data[i + 1] ^ mask[1]; - case 1: data[i] = data[i] ^ mask[0]; - case 0: - } - } -}; - -/* jshint +W086 */ \ No newline at end of file diff --git a/lib/BufferUtil.js b/lib/BufferUtil.js deleted file mode 100644 index fa37c808..00000000 --- a/lib/BufferUtil.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Copied from: - * ws: a node.js websocket client - * Copyright(c) 2011 Einar Otto Stangvik - * MIT Licensed - */ - -try { - module.exports = require('../build/Release/bufferutil'); -} catch (e) { try { - module.exports = require('../build/default/bufferutil'); -} catch (e) { try { - module.exports = require('./BufferUtil.fallback'); -} catch (e) { - console.error('bufferutil.node seems to not have been built. Run npm install.'); - throw e; -}}} diff --git a/lib/Validation.fallback.js b/lib/Validation.fallback.js deleted file mode 100644 index 6160f888..00000000 --- a/lib/Validation.fallback.js +++ /dev/null @@ -1,12 +0,0 @@ -/*! - * UTF-8 Validation Fallback Code originally from: - * ws: a node.js websocket client - * Copyright(c) 2011 Einar Otto Stangvik - * MIT Licensed - */ - -module.exports.Validation = { - isValidUTF8: function() { - return true; - } -}; diff --git a/lib/Validation.js b/lib/Validation.js deleted file mode 100644 index b4106e8d..00000000 --- a/lib/Validation.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * UTF-8 Validation Code originally from: - * ws: a node.js websocket client - * Copyright(c) 2011 Einar Otto Stangvik - * MIT Licensed - */ - -try { - module.exports = require('../build/Release/validation'); -} catch (e) { try { - module.exports = require('../build/default/validation'); -} catch (e) { try { - module.exports = require('./Validation.fallback'); -} catch (e) { - console.error('validation.node seems not to have been built. Run npm install.'); - throw e; -}}} diff --git a/lib/WebSocketConnection.js b/lib/WebSocketConnection.js index c14a24ea..04f8b0b8 100644 --- a/lib/WebSocketConnection.js +++ b/lib/WebSocketConnection.js @@ -19,7 +19,7 @@ var utils = require('./utils'); var EventEmitter = require('events').EventEmitter; var WebSocketFrame = require('./WebSocketFrame'); var BufferList = require('../vendor/FastBufferList'); -var Validation = require('./Validation').Validation; +var isValidUTF8 = require('utf-8-validate'); var bufferAllocUnsafe = utils.bufferAllocUnsafe; var bufferFromString = utils.bufferFromString; @@ -544,7 +544,7 @@ WebSocketConnection.prototype.processFrame = function(frame) { this._debug('-- Text Frame'); if (this.assembleFragments) { if (frame.fin) { - if (!Validation.isValidUTF8(frame.binaryPayload)) { + if (!isValidUTF8(frame.binaryPayload)) { this.drop(WebSocketConnection.CLOSE_REASON_INVALID_DATA, 'Invalid UTF-8 Data Received'); return; @@ -604,7 +604,7 @@ WebSocketConnection.prototype.processFrame = function(frame) { }); break; case 0x01: // WebSocketOpcode.TEXT_FRAME - if (!Validation.isValidUTF8(binaryPayload)) { + if (!isValidUTF8(binaryPayload)) { this.drop(WebSocketConnection.CLOSE_REASON_INVALID_DATA, 'Invalid UTF-8 Data Received'); return; @@ -686,7 +686,7 @@ WebSocketConnection.prototype.processFrame = function(frame) { // If there is a textual description in the close frame, extract it. if (frame.binaryPayload.length > 1) { - if (!Validation.isValidUTF8(frame.binaryPayload)) { + if (!isValidUTF8(frame.binaryPayload)) { this.drop(WebSocketConnection.CLOSE_REASON_INVALID_DATA, 'Invalid UTF-8 Data Received'); return; diff --git a/lib/WebSocketFrame.js b/lib/WebSocketFrame.js index e4a3fb1e..16d75002 100644 --- a/lib/WebSocketFrame.js +++ b/lib/WebSocketFrame.js @@ -14,7 +14,7 @@ * limitations under the License. ***********************************************************************/ -var bufferUtil = require('./BufferUtil').BufferUtil; +var bufferUtil = require('bufferutil'); var bufferAllocUnsafe = require('./utils').bufferAllocUnsafe; const DECODE_HEADER = 1; diff --git a/package.json b/package.json index 130cbf62..51ceba2f 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,14 @@ }, "homepage": "https://github.com/theturtle32/WebSocket-Node", "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" }, "dependencies": { + "bufferutil": "^4.0.1", "debug": "^2.2.0", "es5-ext": "^0.10.50", - "nan": "^2.14.0", "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", "yaeti": "^0.0.6" }, "devDependencies": { @@ -46,7 +47,6 @@ "verbose": false }, "scripts": { - "install": "(node-gyp rebuild 2> builderror.log) || (exit 0)", "test": "faucet test/unit", "gulp": "gulp" }, diff --git a/src/bufferutil.cc b/src/bufferutil.cc deleted file mode 100644 index 888ac576..00000000 --- a/src/bufferutil.cc +++ /dev/null @@ -1,121 +0,0 @@ -/*! - * BufferUtil originally from: - * ws: a node.js websocket client - * Copyright(c) 2015 Einar Otto Stangvik - * MIT Licensed - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "nan.h" - -using namespace v8; -using namespace node; - -class BufferUtil : public ObjectWrap -{ -public: - - static void Initialize(v8::Local target) - { - Nan::HandleScope scope; - Local t = Nan::New(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetMethod(t, "unmask", BufferUtil::Unmask); - Nan::SetMethod(t, "mask", BufferUtil::Mask); - Nan::SetMethod(t, "merge", BufferUtil::Merge); - Nan::Set(target, Nan::New("BufferUtil").ToLocalChecked(), Nan::GetFunction(t).ToLocalChecked()); - } - -protected: - - static NAN_METHOD(New) - { - Nan::HandleScope scope; - BufferUtil* bufferUtil = new BufferUtil(); - bufferUtil->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - - static NAN_METHOD(Merge) - { - Nan::HandleScope scope; - Local bufferObj = Nan::To(info[0]).ToLocalChecked(); - char* buffer = Buffer::Data(bufferObj); - Local array = Local::Cast(info[1]); - unsigned int arrayLength = array->Length(); - size_t offset = 0; - unsigned int i; - for (i = 0; i < arrayLength; ++i) { - Local src = Nan::To(Nan::Get(array, Nan::New(i)).ToLocalChecked()).ToLocalChecked(); - size_t length = Buffer::Length(src); - memcpy(buffer + offset, Buffer::Data(src), length); - offset += length; - } - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(Unmask) - { - Nan::HandleScope scope; - Local buffer_obj = Nan::To(info[0]).ToLocalChecked(); - size_t length = Buffer::Length(buffer_obj); - Local mask_obj = Nan::To(info[1]).ToLocalChecked(); - unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj); - unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj); - size_t len32 = length / 4; - unsigned int i; - for (i = 0; i < len32; ++i) *(from + i) ^= *mask; - from += i; - switch (length % 4) { - case 3: *((unsigned char*)from+2) = *((unsigned char*)from+2) ^ ((unsigned char*)mask)[2]; - case 2: *((unsigned char*)from+1) = *((unsigned char*)from+1) ^ ((unsigned char*)mask)[1]; - case 1: *((unsigned char*)from ) = *((unsigned char*)from ) ^ ((unsigned char*)mask)[0]; - case 0:; - } - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(Mask) - { - Nan::HandleScope scope; - Local buffer_obj = Nan::To(info[0]).ToLocalChecked(); - Local mask_obj = Nan::To(info[1]).ToLocalChecked(); - unsigned int *mask = (unsigned int*)Buffer::Data(mask_obj); - Local output_obj = Nan::To(info[2]).ToLocalChecked(); - unsigned int dataOffset = Nan::To(info[3]).ToLocalChecked()->Value(); - unsigned int length = Nan::To(info[4]).ToLocalChecked()->Value(); - unsigned int* to = (unsigned int*)(Buffer::Data(output_obj) + dataOffset); - unsigned int* from = (unsigned int*)Buffer::Data(buffer_obj); - unsigned int len32 = length / 4; - unsigned int i; - for (i = 0; i < len32; ++i) *(to + i) = *(from + i) ^ *mask; - to += i; - from += i; - switch (length % 4) { - case 3: *((unsigned char*)to+2) = *((unsigned char*)from+2) ^ *((unsigned char*)mask+2); - case 2: *((unsigned char*)to+1) = *((unsigned char*)from+1) ^ *((unsigned char*)mask+1); - case 1: *((unsigned char*)to ) = *((unsigned char*)from ) ^ *((unsigned char*)mask); - case 0:; - } - info.GetReturnValue().Set(Nan::True()); - } -}; - -#if !NODE_VERSION_AT_LEAST(0,10,0) -extern "C" -#endif -void init (Local target) -{ - Nan::HandleScope scope; - BufferUtil::Initialize(target); -} - -NODE_MODULE(bufferutil, init) diff --git a/src/validation.cc b/src/validation.cc deleted file mode 100644 index be13c2e1..00000000 --- a/src/validation.cc +++ /dev/null @@ -1,148 +0,0 @@ -/*! - * UTF-8 Validation Code originally from: - * ws: a node.js websocket client - * Copyright(c) 2015 Einar Otto Stangvik - * MIT Licensed - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "nan.h" - -using namespace v8; -using namespace node; - -#define UNI_SUR_HIGH_START (uint32_t) 0xD800 -#define UNI_SUR_LOW_END (uint32_t) 0xDFFF -#define UNI_REPLACEMENT_CHAR (uint32_t) 0x0000FFFD -#define UNI_MAX_LEGAL_UTF32 (uint32_t) 0x0010FFFF - -static const uint8_t trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -static const uint32_t offsetsFromUTF8[6] = { - 0x00000000, 0x00003080, 0x000E2080, - 0x03C82080, 0xFA082080, 0x82082080 -}; - -static int isLegalUTF8(const uint8_t *source, const int length) -{ - uint8_t a; - const uint8_t *srcptr = source+length; - switch (length) { - default: return 0; - /* Everything else falls through when "true"... */ - /* RFC3629 makes 5 & 6 bytes UTF-8 illegal - case 6: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 5: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 2: if ((a = (*--srcptr)) > 0xBF) return 0; - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return 0; break; - case 0xED: if (a > 0x9F) return 0; break; - case 0xF0: if (a < 0x90) return 0; break; - case 0xF4: if (a > 0x8F) return 0; break; - default: if (a < 0x80) return 0; - } - - case 1: if (*source >= 0x80 && *source < 0xC2) return 0; - } - if (*source > 0xF4) return 0; - return 1; -} - -int is_valid_utf8 (size_t len, char *value) -{ - /* is the string valid UTF-8? */ - for (unsigned int i = 0; i < len; i++) { - uint32_t ch = 0; - uint8_t extrabytes = trailingBytesForUTF8[(uint8_t) value[i]]; - - if (extrabytes + i >= len) - return 0; - - if (isLegalUTF8 ((uint8_t *) (value + i), extrabytes + 1) == 0) return 0; - - switch (extrabytes) { - case 5 : ch += (uint8_t) value[i++]; ch <<= 6; - case 4 : ch += (uint8_t) value[i++]; ch <<= 6; - case 3 : ch += (uint8_t) value[i++]; ch <<= 6; - case 2 : ch += (uint8_t) value[i++]; ch <<= 6; - case 1 : ch += (uint8_t) value[i++]; ch <<= 6; - case 0 : ch += (uint8_t) value[i]; - } - - ch -= offsetsFromUTF8[extrabytes]; - - if (ch <= UNI_MAX_LEGAL_UTF32) { - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) - return 0; - } else { - return 0; - } - } - - return 1; -} - -class Validation : public ObjectWrap -{ -public: - - static void Initialize(v8::Local target) - { - Nan::HandleScope scope; - Local t = Nan::New(New); - t->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetMethod(t, "isValidUTF8", Validation::IsValidUTF8); - Nan::Set(target, Nan::New("Validation").ToLocalChecked(), Nan::GetFunction(t).ToLocalChecked()); - } - -protected: - - static NAN_METHOD(New) - { - Nan::HandleScope scope; - Validation* validation = new Validation(); - validation->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - - static NAN_METHOD(IsValidUTF8) - { - Nan::HandleScope scope; - if (!Buffer::HasInstance(info[0])) { - return Nan::ThrowTypeError("First argument needs to be a buffer"); - } - Local buffer_obj = Nan::To(info[0]).ToLocalChecked(); - char *buffer_data = Buffer::Data(buffer_obj); - size_t buffer_length = Buffer::Length(buffer_obj); - info.GetReturnValue().Set(is_valid_utf8(buffer_length, buffer_data) == 1 ? Nan::True() : Nan::False()); - } -}; -#if !NODE_VERSION_AT_LEAST(0,10,0) -extern "C" -#endif -void init (Local target) -{ - Nan::HandleScope scope; - Validation::Initialize(target); -} - -NODE_MODULE(validation, init)